(;module: lux (lux (control [monad #+ do] ["ex" exception #+ exception:]) (data ["e" error] [product] text/format) [meta] (meta [type] (type ["tc" check])) [host]) (luxc ["&" base] [";L" host] (lang ["la" analysis]) ["&;" module] (generator [";G" common])) (.. [";A" common] [";A" function] [";A" primitive] [";A" reference] [";A" structure] [";A" procedure])) (for {"JVM" (as-is (host;import java.lang.reflect.Method (invoke [Object (Array Object)] #try Object)) (host;import (java.lang.Class c) (getMethod [String (Array (Class Object))] #try Method)) (host;import java.lang.Object (getClass [] (Class Object)) (toString [] String)) (def: _object-class (Class Object) (host;class-for Object)) (def: _apply-args (Array (Class Object)) (|> (host;array (Class Object) +2) (host;array-write +0 _object-class) (host;array-write +1 _object-class))) (def: (call-macro macro inputs) (-> Macro (List Code) (Meta (List Code))) (do meta;Monad [class (commonG;load-class hostL;function-class)] (function [compiler] (do e;Monad [apply-method (Class.getMethod ["apply" _apply-args] class) output (Method.invoke [(:! Object macro) (|> (host;array Object +2) (host;array-write +0 (:! Object inputs)) (host;array-write +1 (:! Object compiler)))] apply-method)] (:! (e;Error [Compiler (List Code)]) output)))))) }) (exception: #export Macro-Expression-Must-Have-Single-Expansion) (exception: #export Unrecognized-Syntax) (def: #export (analyser eval) (-> &;Eval &;Analyser) (: (-> Code (Meta la;Analysis)) (function analyse [ast] (do meta;Monad [expectedT meta;expected-type] (let [[cursor ast'] ast] ## The cursor must be set in the compiler for the sake ## of having useful error messages. (&;with-cursor cursor (case ast' (^template [ ] ( value) ( value)) ([#;Bool primitiveA;analyse-bool] [#;Nat primitiveA;analyse-nat] [#;Int primitiveA;analyse-int] [#;Deg primitiveA;analyse-deg] [#;Frac primitiveA;analyse-frac] [#;Text primitiveA;analyse-text]) (^ (#;Tuple (list))) primitiveA;analyse-unit ## Singleton tuples are equivalent to the element they contain. (^ (#;Tuple (list singleton))) (analyse singleton) (^ (#;Tuple elems)) (structureA;analyse-product analyse elems) (^ (#;Record pairs)) (structureA;analyse-record analyse pairs) (#;Symbol reference) (referenceA;analyse-reference reference) (^ (#;Form (list& [_ (#;Text proc-name)] proc-args))) (procedureA;analyse-procedure analyse eval proc-name proc-args) (^template [ ] (^ (#;Form (list& [_ ( tag)] values))) (case values (#;Cons value #;Nil) ( analyse tag value) _ ( analyse tag (` [(~@ values)])))) ([#;Nat structureA;analyse-sum] [#;Tag structureA;analyse-tagged-sum]) (#;Tag tag) (structureA;analyse-tagged-sum analyse tag (' [])) (^ (#;Form (list& func args))) (do meta;Monad [[funcT =func] (commonA;with-unknown-type (analyse func))] (case =func [_ (#;Symbol def-name)] (do @ [[def-type def-anns def-value] (meta;find-def def-name)] (if (meta;macro? def-anns) (do @ [expansion (function [compiler] (case (call-macro (:! Macro def-value) args compiler) (#e;Success [compiler' output]) (#e;Success [compiler' output]) (#e;Error error) ((&;fail error) compiler)))] (case expansion (^ (list single)) (analyse single) _ (&;throw Macro-Expression-Must-Have-Single-Expansion (%code ast)))) (functionA;analyse-apply analyse funcT =func args))) _ (functionA;analyse-apply analyse funcT =func args))) _ (&;throw Unrecognized-Syntax (%code ast)) )))))))