(.module: lux (lux (control [monad #+ do] ["ex" exception #+ exception:]) (data ["e" error] [product] text/format) [macro] (lang [type] (type ["tc" check])) [host]) (luxc ["&" lang] (lang ["&." module] [".L" host] [".L" macro] [".L" extension] ["la" analysis] (translation [".T" common]))) (// [".A" common] [".A" function] [".A" primitive] [".A" reference] [".A" structure])) (exception: #export Macro-Expression-Must-Have-Single-Expansion) (exception: #export Unrecognized-Syntax) (exception: #export Macro-Expansion-Failed) (def: #export (analyser eval) (-> &.Eval &.Analyser) (: (-> Code (Meta la.Analysis)) (function analyse [code] (do macro.Monad [expectedT macro.expected-type] (let [[cursor code'] code] ## The cursor must be set in the compiler for the sake ## of having useful error messages. (&.with-cursor cursor (case code' (^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))) (do macro.Monad [procedure (extensionL.find-analysis proc-name)] (procedure analyse eval 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 macro.Monad [[funcT funcA] (commonA.with-unknown-type (analyse func))] (case funcA [_ (#.Symbol def-name)] (do @ [?macro (&.with-error-tracking (macro.find-macro def-name))] (case ?macro (#.Some macro) (do @ [expansion (: (Meta (List Code)) (function [compiler] (case (macroL.expand macro args compiler) (#e.Error error) ((&.throw Macro-Expansion-Failed error) compiler) output output)))] (case expansion (^ (list single)) (analyse single) _ (&.throw Macro-Expression-Must-Have-Single-Expansion (%code code)))) _ (functionA.analyse-apply analyse funcT funcA args))) _ (functionA.analyse-apply analyse funcT funcA args))) _ (&.throw Unrecognized-Syntax (%code code)) )))))))