aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/lang/translation/lua/eval.jvm.lux
blob: 8be5667e9fdedee6d93d9284f0efe3c59c7ce63e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
(.module:
  lux
  (lux (control ["ex" exception #+ exception:])
       (data [bit]
             [maybe]
             ["e" error #+ Error]
             text/format
             (coll [array]))
       [host])
  (luxc [lang]
        (lang (host [lua #+ Lua Expression Statement])))
  [//])

(do-template [<name>]
  [(exception: #export (<name> {message Text})
     message)]

  [Unknown-Kind-Of-Host-Object]
  [Null-Has-No-Lux-Representation]
  [Cannot-Evaluate]
  )

(host.import java/lang/Object
  (toString [] String)
  (getClass [] (Class Object)))

(host.import java/lang/Long
  (intValue [] Integer))

(host.import net/sandius/rembulan/ByteString
  (decode [] String))

(host.import net/sandius/rembulan/Table
  (rawget #as get-idx [long] #? Object)
  (rawget #as get-key [Object] #? Object)
  (rawlen [] long))

(host.import net/sandius/rembulan/impl/DefaultTable)

(def: (variant lux-object host-object)
  (-> (-> Object (Error Top)) DefaultTable (Maybe Top))
  (case [(Table::get-key [//.variant-tag-field] host-object)
         (Table::get-key [//.variant-flag-field] host-object)
         (Table::get-key [//.variant-value-field] host-object)]
    (^multi [(#.Some tag) ?flag (#.Some value)]
            [(lux-object value)
             (#.Some value)])
    (#.Some [(Long::intValue [] (:! Long tag))
             (: Top (case ?flag (#.Some _) "" #.None (host.null)))
             value])

    _
    #.None))

(def: (array lux-object host-object)
  (-> (-> Object (Error Top)) DefaultTable (Maybe (Array Object)))
  (let [init-num-keys (:! Nat (Table::rawlen [] host-object))]
    (loop [num-keys init-num-keys
           idx +0
           output (: (Array Object)
                     (array.new init-num-keys))]
      (if (n/< num-keys idx)
        (case (Table::get-idx (:! Long (n/inc idx)) host-object)
          (#.Some member)
          (case (lux-object member)
            (#e.Success parsed-member)
            (recur num-keys (n/inc idx) (array.write idx (:! Object parsed-member) output))

            (#e.Error error)
            #.None)

          #.None
          (recur num-keys (n/inc idx) output))
        (#.Some output)))))

(def: (lux-object host-object)
  (-> Object (Error Top))
  (`` (cond (host.null? host-object)
            (ex.throw Null-Has-No-Lux-Representation "")

            (or (host.instance? java/lang/Boolean host-object)
                (host.instance? java/lang/Long host-object)
                (host.instance? java/lang/Double host-object)
                (host.instance? java/lang/String host-object))
            (ex.return host-object)

            (host.instance? ByteString host-object)
            (ex.return (ByteString::decode [] (:! ByteString host-object)))

            (host.instance? DefaultTable host-object)
            (let [host-object (:! DefaultTable host-object)]
              (case (variant lux-object host-object)
                (#.Some value)
                (ex.return value)

                #.None
                (case (array lux-object host-object)
                  (#.Some value)
                  (ex.return value)

                  #.None
                  (ex.throw Unknown-Kind-Of-Host-Object (format "SECOND " (Object::toString [] (:! Object host-object)))))))

            ## else
            (ex.throw Unknown-Kind-Of-Host-Object (format "FIRST " (Object::toString [] (:! Object host-object))))
            )))

(def: #export (eval code)
  (-> Expression (Meta Top))
  (function (_ compiler)
    (let [interpreter (|> compiler (get@ #.host) (:! //.Host) (get@ #//.interpreter))]
      (case (interpreter (format "return " code ";"))
        (#e.Error error)
        ((lang.throw Cannot-Evaluate error) compiler)

        (#e.Success output)
        (case (lux-object (|> output
                              (:! (Array Object))
                              (array.read +0)
                              maybe.assume))
          (#e.Success parsed-output)
          (#e.Success [compiler parsed-output])

          (#e.Error error)
          ((lang.throw Cannot-Evaluate error) compiler))))))