aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/lang/translation/ruby/eval.jvm.lux
blob: 52a261b2ad33bb68b9f2b6a4c2679272d3047226 (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
(.module:
  lux
  (lux (control ["ex" exception #+ exception:])
       (data [bit]
             [maybe]
             ["e" error #+ Error]
             text/format
             (coll [array]))
       [host])
  (luxc [lang]
        (lang (host [ruby #+ Ruby 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/jruby/RubyArray
  (getLength [] int)
  (get [int] #? Object))

(host.import: org/jruby/RubyHash
  (get [Object] #? Object))

(def: (tuple lux-object host-object)
  (-> (-> Object (Error Any)) RubyArray (Error Any))
  (let [size (:coerce Nat (RubyArray::getLength [] host-object))]
    (loop [idx +0
           output (:coerce (Array Any) (array.new size))]
      (if (n/< size idx)
        (case (RubyArray::get [(:coerce Int idx)] host-object)
          #.None
          (recur (inc idx) output)
          
          (#.Some value)
          (case (lux-object value)
            (#e.Error error)
            (#e.Error error)

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

(def: (variant lux-object host-object)
  (-> (-> Object (Error Any)) RubyHash (Error Any))
  (case [(RubyHash::get [(:coerce Object //.variant-tag-field)] host-object)
         (RubyHash::get [(:coerce Object //.variant-flag-field)] host-object)
         (RubyHash::get [(:coerce Object //.variant-value-field)] host-object)]
    (^multi [(#.Some tag) ?flag (#.Some value)]
            [(lux-object value)
             (#.Some value)])
    (#e.Success [(Long::intValue [] (:coerce Long tag))
                 (: Any (case ?flag (#.Some _) "" #.None (host.null)))
                 value])

    _
    (ex.throw Not-A-Variant "")))

(def: (lux-object host-object)
  (-> Object (Error Any))
  (`` (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? org/jruby/RubyArray host-object)
            (tuple lux-object (:coerce RubyArray host-object))

            (host.instance? org/jruby/RubyHash host-object)
            (case (variant lux-object (:coerce RubyHash host-object))
              (#e.Success value)
              (#e.Success value)

              _
              (let [object-class (:coerce Text (Object::toString [] (Object::getClass [] (:coerce Object host-object))))
                    text-representation (:coerce Text (Object::toString [] (:coerce Object host-object)))]
                (ex.throw Unknown-Kind-Of-Host-Object (format object-class " --- " text-representation))))

            ## else
            (let [object-class (:coerce Text (Object::toString [] (Object::getClass [] (:coerce Object host-object))))
                  text-representation (:coerce Text (Object::toString [] (:coerce Object host-object)))]
              (ex.throw Unknown-Kind-Of-Host-Object (format object-class " --- " text-representation)))
            )))

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

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

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