aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/lang/translation/python/eval.jvm.lux
blob: 6f4e43f9d9d1f1925d86696eb0bfd5c36f0d7799 (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
(.module:
  lux
  (lux (control ["ex" exception #+ exception:])
       (data [bit]
             [maybe]
             ["e" error #+ Error]
             text/format
             (coll [array]))
       [host])
  (luxc [lang]
        (lang (host [python #+ Expression Statement])))
  [//])

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

  [Not-A-Variant]
  [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 org/python/core/PyType
  (getName [] String))

(host.import org/python/core/PyString
  (new [String]))

(host.import org/python/core/PyObject
  (asLong [] long)
  (asDouble [] double)
  (asString [] String)
  (__nonzero__ [] boolean)
  (__getitem__ [int] #try PyObject)
  (__getitem__ #as __getitem__dict [PyObject] #try PyObject)
  (__len__ [] int)
  (getType [] PyType))

(def: (tuple lux-object host-object)
  (-> (-> PyObject (Error Any)) PyObject (Error Any))
  (let [size (:! Nat (PyObject::__len__ [] host-object))]
    (loop [idx +0
           output (:! (Array Any) (array.new size))]
      (if (n/< size idx)
        (case (PyObject::__getitem__ [(:! Int idx)] host-object)
          (#e.Error error)
          (#e.Error error)
          
          (#e.Success value)
          (case (lux-object value)
            (#e.Error error)
            (#e.Error error)

            (#e.Success lux-value)
            (recur (n/inc idx) (array.write idx lux-value output))))
        (#e.Success output)))))

(def: python-type
  (-> PyObject Text)
  (|>> (PyObject::getType []) (PyType::getName []) (:! Text)))

(def: tag-field (PyString::new [//.variant-tag-field]))
(def: flag-field (PyString::new [//.variant-flag-field]))
(def: value-field (PyString::new [//.variant-value-field]))

(def: (variant lux-object host-object)
  (-> (-> PyObject (Error Any)) PyObject (Error Any))
  (case [(PyObject::__getitem__dict [tag-field] host-object)
         (PyObject::__getitem__dict [flag-field] host-object)
         (PyObject::__getitem__dict [value-field] host-object)]
    (^or [(#e.Error error) _ _] [_ (#e.Error error) _] [_ _ (#e.Error error)])
    (#e.Error error)
    
    (^multi [(#e.Success tag) (#e.Success flag) (#e.Success value)]
            [(lux-object tag)
             (#e.Success tag)]
            [(lux-object value)
             (#e.Success value)])
    (#e.Success [(Long::intValue [] (:! Long tag))
                 (: Any
                    (case (python-type (:! PyObject flag))
                      "NoneType"
                      (host.null)

                      _
                      ""))
                 value])

    _
    (ex.throw Not-A-Variant (Object::toString [] host-object))))

(def: (lux-object host-object)
  (-> PyObject (Error Any))
  (case (python-type host-object)
    "str"
    (#e.Success (PyObject::asString [] host-object))
    
    "bool"
    (#e.Success (PyObject::__nonzero__ [] host-object))

    "float"
    (#e.Success (PyObject::asDouble [] host-object))

    (^or "int" "long")
    (#e.Success (PyObject::asLong [] host-object))

    "tuple"
    (tuple lux-object host-object)

    "dict"
    (variant lux-object host-object)

    "NoneType"
    (#e.Success [])
    
    type
    (ex.throw Unknown-Kind-Of-Host-Object (format type " " (Object::toString [] host-object)))))

(def: #export (eval code)
  (-> Expression (Meta Any))
  (function (_ compiler)
    (let [interpreter (|> compiler (get@ #.host) (:! //.Host) (get@ #//.interpreter))]
      (case (interpreter code)
        (#e.Error error)
        (exec (log! (format "eval #e.Error\n"
                            "<< " (python.expression code) "\n"
                            error))
          ((lang.throw Cannot-Evaluate error) compiler))

        (#e.Success output)
        (case (lux-object output)
          (#e.Success parsed-output)
          (exec ## (log! (format "eval #e.Success\n"
            ##               "<< " (python.expression code)))
            (#e.Success [compiler parsed-output]))

          (#e.Error error)
          (exec (log! (format "eval #e.Error\n"
                              "<< " (python.expression code) "\n"
                              error))
            ((lang.throw Cannot-Evaluate error) compiler)))))))