(.module: lux (lux (control ["ex" exception #+ exception:] [monad #+ do]) (data [bit] [maybe] ["e" error #+ Error] [text "text/" Eq] text/format (coll [array])) [host]) (luxc [lang] (lang (host [scheme #+ Expression]))) [//]) (do-template [] [(exception: #export ( {message Text}) message)] [Unknown-Kind-Of-Host-Object] [Null-Has-No-Lux-Representation] [Cannot-Evaluate] [invalid-variant] ) (host.import: java/lang/Object (toString [] String) (getClass [] (Class Object))) (host.import: java/lang/Long (intValue [] Integer)) (host.import: java/lang/Boolean) (host.import: java/lang/String) (host.import: gnu/math/IntNum (longValue [] long)) (host.import: gnu/math/DFloNum (doubleValue [] double)) (host.import: (gnu/lists/FVector E) (getBufferLength [] int) (get [int] E)) (host.import: gnu/lists/EmptyList) (host.import: gnu/lists/FString (toString [] String)) (host.import: gnu/lists/Pair (getCar [] Object) (getCdr [] Object) (get [int] Object)) (host.import: gnu/mapping/Symbol (getName [] String)) (host.import: gnu/mapping/SimpleSymbol) (def: (parse-tuple lux-object host-object) (-> (-> Object (Error Any)) (FVector Object) (Error Any)) (let [size (:coerce Nat (FVector::getBufferLength [] host-object))] (loop [idx +0 output (:coerce (Array Any) (array.new size))] (if (n/< size idx) (case (lux-object (FVector::get [(:coerce Int idx)] host-object)) (#e.Error error) (#e.Error error) (#e.Success lux-value) (recur (inc idx) (array.write idx (:coerce Any lux-value) output))) (#e.Success output))))) (def: (variant tag flag value) (-> Nat Bit Any Any) [(Long::intValue [] (:coerce Long tag)) (: Any (if flag //.unit (host.null))) value]) (def: (to-text value) (-> Any Text) (let [value-text (:coerce Text (Object::toString [] (:coerce Object value))) class-text (:coerce Text (Object::toString [] (Object::getClass [] (:coerce Object value))))] (format value-text " : " class-text))) (def: (parse-variant lux-object host-object) (-> (-> Object (Error Any)) Pair (Error Any)) (let [variant-tag (Pair::getCar [] host-object)] (if (and (host.instance? gnu/mapping/SimpleSymbol variant-tag) (text/= //.variant-tag (Symbol::getName [] (:coerce Symbol variant-tag)))) (do e.Monad [#let [host-object (:coerce Pair (Pair::getCdr [] host-object))] tag (lux-object (Pair::getCar [] host-object)) #let [host-object (:coerce Pair (Pair::getCdr [] host-object))] #let [flag (host.instance? java/lang/String (Pair::getCar [] host-object))] value (lux-object (Pair::getCdr [] host-object))] (wrap (..variant (:coerce Nat tag) flag value))) (ex.throw invalid-variant (:coerce Text (Object::toString [] (:coerce Object host-object))))))) (def: (lux-object host-object) (-> Object (Error Any)) (cond (or (host.instance? java/lang/Boolean host-object) (host.instance? java/lang/String host-object)) (#e.Success host-object) (host.instance? gnu/math/IntNum host-object) (#e.Success (IntNum::longValue [] (:coerce IntNum host-object))) (host.instance? gnu/math/DFloNum host-object) (#e.Success (DFloNum::doubleValue [] (:coerce DFloNum host-object))) (host.instance? gnu/lists/FString host-object) (#e.Success (FString::toString [] (:coerce FString host-object))) (host.instance? gnu/lists/FVector host-object) (parse-tuple lux-object (:coerce (FVector Object) host-object)) (host.instance? gnu/lists/EmptyList host-object) (#e.Success //.unit) (host.instance? gnu/lists/Pair host-object) (parse-variant lux-object (:coerce Pair host-object)) ## 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" "<< " (scheme.expression code) "\n" error)) ((lang.throw Cannot-Evaluate error) compiler)) (#e.Success output) (case (lux-object output) (#e.Success parsed-output) (#e.Success [compiler parsed-output]) (#e.Error error) (exec (log! (format "eval #e.Error\n" "<< " (scheme.expression code) "\n" error)) ((lang.throw Cannot-Evaluate error) compiler)))))))