## First things first, must define functions (jvm-interface Function (:' (-> [java.lang.Object] java.lang.Object) apply)) ## Basic types (def' Bool (#DataT "java.lang.Boolean")) (export' Bool) (def' Int (#DataT "java.lang.Long")) (export' Int) (def' Real (#DataT "java.lang.Double")) (export' Real) (def' Char (#DataT "java.lang.Character")) (export' Char) (def' Text (#DataT "java.lang.String")) (export' Text) (def' Void (#VariantT #Nil)) (export' Void) ## (deftype (List a) ## (| #Nil ## (#Cons (, a (List a))))) (def' List (#AllT [#None "List" "a" (#VariantT (#Cons [["lux;Nil" (#TupleT #Nil)] (#Cons [["lux;Cons" (#TupleT (#Cons [(#BoundT "a") (#Cons [(#AppT [(#BoundT "List") (#BoundT "a")]) #Nil])]))] #Nil])]))])) (export' List) ## (deftype (Maybe a) ## (| #None ## (#Some a))) (def' Maybe (#AllT [#None "Maybe" "a" (#VariantT (#Cons [["lux;None" (#TupleT #Nil)] (#Cons [["lux;Some" (#BoundT "a")] #Nil])]))])) (export' Maybe) ## (deftype #rec Type ## (| (#DataT Text) ## (#TupleT (List Type)) ## (#VariantT (List (, Text Type))) ## (#RecordT (List (, Text Type))) ## (#LambdaT (, Type Type)) ## (#BoundT Text) ## (#VarT Int) ## (#AllT (, (Maybe (List (, Text Type))) Text Text Type)) ## (#AppT (, Type Type)))) (def' Type (case' (#AppT [(#BoundT "Type") (#BoundT "_")]) Type (case' (#AppT [List (#TupleT (#Cons [Text (#Cons [Type #Nil])]))]) TypeEnv (#AppT [(#AllT [#None "Type" "_" (#VariantT (#Cons [["lux;DataT" Text] (#Cons [["lux;TupleT" (#AppT [List Type])] (#Cons [["lux;VariantT" TypeEnv] (#Cons [["lux;RecordT" TypeEnv] (#Cons [["lux;LambdaT" (#TupleT (#Cons [Type (#Cons [Type #Nil])]))] (#Cons [["lux;BoundT" Text] (#Cons [["lux;VarT" Int] (#Cons [["lux;AllT" (#TupleT (#Cons [(#AppT [Maybe TypeEnv]) (#Cons [Text (#Cons [Text (#Cons [Type #Nil])])])]))] (#Cons [["lux;AppT" (#TupleT (#Cons [Type (#Cons [Type #Nil])]))] #Nil])])])])])])])])]))]) Void])))) (export' Type) ## (deftype (Bindings k v) ## (& #counter Int ## #mappings (List (, k v)))) (def' Bindings (#AllT [#None "Bindings" "k" (#AllT [#None "" "v" (#RecordT (#Cons [["lux;counter" Int] (#Cons [["lux;mappings" (#AppT [List (#TupleT (#Cons [(#BoundT "k") (#Cons [(#BoundT "v") #Nil])]))])] #Nil])]))])])) ## (deftype (Env k v) ## (& #name Text ## #inner-closures Int ## #locals (Bindings k v) ## #closure (Bindings k v))) (def' Env (#AllT [#None "Env" "k" (#AllT [#None "" "v" (#RecordT (#Cons [["lux;name" Text] (#Cons [["lux;inner-closures" Int] (#Cons [["lux;locals" (#AppT [(#AppT [Bindings (#BoundT "k")]) (#BoundT "v")])] (#Cons [["lux;closure" (#AppT [(#AppT [Bindings (#BoundT "k")]) (#BoundT "v")])] #Nil])])])]))])])) ## (deftype Cursor ## (, Text Int Int)) (def' Cursor (#TupleT (#Cons [Text (#Cons [Int (#Cons [Int #Nil])])]))) ## (deftype (Meta m v) ## (| (#Meta (, m v)))) (def' Meta (#AllT [#None "Meta" "m" (#AllT [#None "" "v" (#VariantT (#Cons [["lux;Meta" (#TupleT (#Cons [(#BoundT "m") (#Cons [(#BoundT "v") #Nil])]))] #Nil]))])])) (export' Meta) ## (deftype (Syntax' w) ## (| (#Bool Bool) ## (#Int Int) ## (#Real Real) ## (#Char Char) ## (#Text Text) ## (#Symbol (, Text Text)) ## (#Tag (, Text Text)) ## (#Form (List (w (Syntax' w)))) ## (#Tuple (List (w (Syntax' w)))) ## (#Record (List (, (w (Syntax' w)) (w (Syntax' w))))))) (def' Syntax' (case' (#AppT [(#BoundT "w") (#AppT [(#BoundT "Syntax'") (#BoundT "w")])]) Syntax (case' (#AppT [List Syntax]) SyntaxList (case' (#TupleT (#Cons [Text (#Cons [Text #Nil])])) Ident (#AllT [#None "Syntax'" "w" (#VariantT (#Cons [["lux;Bool" Bool] (#Cons [["lux;Int" Int] (#Cons [["lux;Real" Real] (#Cons [["lux;Char" Char] (#Cons [["lux;Text" Text] (#Cons [["lux;Symbol" Ident] (#Cons [["lux;Tag" Ident] (#Cons [["lux;Form" SyntaxList] (#Cons [["lux;Tuple" SyntaxList] (#Cons [["lux;Record" (#AppT [List (#TupleT (#Cons [Syntax (#Cons [Syntax #Nil])]))])] #Nil]) ])])])])])])])])]) )]) )))) (export' Syntax') ## (deftype Syntax ## (Meta Cursor (Syntax' (Meta Cursor)))) (def' Syntax (case' (#AppT [Meta Cursor]) w (#AppT [w (#AppT [Syntax' w])]))) (export' Syntax) (def' SyntaxList (#AppT [List Syntax])) ## (deftype (Either l r) ## (| (#Left l) ## (#Right r))) (def' Either (#AllT [#None "_" "l" (#AllT [#None "" "r" (#VariantT (#Cons [["lux;Left" (#BoundT "l")] (#Cons [["lux;Right" (#BoundT "r")] #Nil])]))])])) (export' Either) ## (deftype (StateE s a) ## (-> s (Either Text (, s a)))) (def' StateE (#AllT [#None "StateE" "s" (#AllT [#None "" "a" (#LambdaT [(#BoundT "s") (#AppT [(#AppT [Either Text]) (#TupleT (#Cons [(#BoundT "s") (#Cons [(#BoundT "a") #Nil])]))])])])])) ## (def' Reader ## (List (Meta Cursor Text))) (def' Reader (#AppT [List (#AppT [(#AppT [Meta Cursor]) Text])])) (export' Reader) ## (deftype HostState ## (& #writer (^ org.objectweb.asm.ClassWriter) ## #loader (^ java.net.URLClassLoader) ## #eval-ctor Int)) (def' HostState (#RecordT (#Cons [["lux;writer" (#DataT "org.objectweb.asm.ClassWriter")] (#Cons [["lux;loader" (#DataT "java.lang.ClassLoader")] (#Cons [["lux;eval-ctor" Int] #Nil])])]))) ## (deftype (DefData' m) ## (| #TypeD ## (#ValueD Type) ## (#MacroD m))) (def' DefData' (#AllT [#None "DefData'" "" (#VariantT (#Cons [["lux;TypeD" (#TupleT #Nil)] (#Cons [["lux;ValueD" Type] (#Cons [["lux;MacroD" (#BoundT "")] #Nil])])]))])) ## (deftype #rec CompilerState ## (& #source (Maybe Reader) ## #modules (List (, Text (List (, Text (DefData' (-> (List Syntax) (StateE CompilerState (List Syntax)))))))) ## #module-aliases (List Void) ## #envs (List (Env Text Void)) ## #types (Bindings Int Type) ## #host HostState)) (def' CompilerState (#AppT [(#AllT [#None "CompilerState" "" (#RecordT (#Cons [["lux;source" (#AppT [Maybe Reader])] (#Cons [["lux;modules" (#AppT [List (#TupleT (#Cons [Text (#Cons [(#AppT [List (#TupleT (#Cons [Text (#Cons [(#AppT [DefData' (#LambdaT [SyntaxList (#AppT [(#AppT [StateE (#AppT [(#BoundT "CompilerState") (#BoundT "")])]) SyntaxList])])]) #Nil])]))]) #Nil])]))])] (#Cons [["lux;module-aliases" (#AppT [List Void])] (#Cons [["lux;envs" (#AppT [List (#AppT [(#AppT [Env Text]) Void])])] (#Cons [["lux;types" (#AppT [(#AppT [Bindings Int]) Type])] (#Cons [["lux;host" HostState] (#Cons [["lux;seed" Int] #Nil])])])])])])]))]) Void])) (export' CompilerState) ## (deftype Macro ## (-> (List Syntax) (StateE CompilerState (List Syntax)))) (def' Macro (#LambdaT [SyntaxList (#AppT [(#AppT [StateE CompilerState]) SyntaxList])])) (export' Macro) ## Base functions & macros ## (def (_meta data) ## (-> (Syntax' (Meta Cursor)) Syntax) ## (#Meta [["" -1 -1] data])) (def' _meta (:' (#LambdaT [(#AppT [Syntax' (#AppT [Meta Cursor])]) Syntax]) (lambda' _ data (#Meta [["" -1 -1] data])))) ## (def (return x) ## (All [a] ## (-> a CompilerState ## (Either Text (, CompilerState a)))) ## ...) (def' return (:' (#AllT [#None "" "a" (#LambdaT [(#BoundT "a") (#LambdaT [CompilerState (#AppT [(#AppT [Either Text]) (#TupleT (#Cons [CompilerState (#Cons [(#BoundT "a") #Nil])]))])])])]) (lambda' _ val (lambda' _ state (#Right [state val]))))) ## (def (fail msg) ## (All [a] ## (-> Text CompilerState ## (Either Text (, CompilerState a)))) ## ...) (def' fail (:' (#AllT [#None "" "a" (#LambdaT [Text (#LambdaT [CompilerState (#AppT [(#AppT [Either Text]) (#TupleT (#Cons [CompilerState (#Cons [(#BoundT "a") #Nil])]))])])])]) (lambda' _ msg (lambda' _ state (#Left msg))))) (def' Ident (#TupleT (#Cons [Text (#Cons [Text #Nil])]))) (export' Ident) (def' $text (:' (#LambdaT [Text Syntax]) (lambda' _ text (_meta (#Text text))))) (export' $text) (def' $symbol (:' (#LambdaT [Ident Syntax]) (lambda' _ ident (_meta (#Symbol ident))))) (export' $symbol) (def' $tag (:' (#LambdaT [Ident Syntax]) (lambda' _ ident (_meta (#Tag ident))))) (export' $tag) (def' $form (:' (#LambdaT [(#AppT [List Syntax]) Syntax]) (lambda' _ tokens (_meta (#Form tokens))))) (export' $form) (def' $tuple (:' (#LambdaT [(#AppT [List Syntax]) Syntax]) (lambda' _ tokens (_meta (#Tuple tokens))))) (export' $tuple) (def' $record (:' (#LambdaT [(#AppT [List (#TupleT (#Cons [Syntax (#Cons [Syntax #Nil])]))]) Syntax]) (lambda' _ tokens (_meta (#Record tokens))))) (export' $record) (def' let' (:' Macro (lambda' _ tokens (case' tokens (#Cons [lhs (#Cons [rhs (#Cons [body #Nil])])]) (return (:' SyntaxList (#Cons [($form (#Cons [($symbol ["" "case'"]) (#Cons [rhs (#Cons [lhs (#Cons [body #Nil])])])])) #Nil]))) _ (fail "Wrong syntax for let'"))))) (declare-macro' let') (def' lambda_ (:' Macro (lambda' _ tokens (case' tokens (#Cons [(#Meta [_ (#Tuple (#Cons [arg args']))]) (#Cons [body #Nil])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" "lambda'"])) (#Cons [(_meta (#Symbol ["" ""])) (#Cons [arg (#Cons [(case' args' #Nil body _ (_meta (#Form (#Cons [(_meta (#Symbol ["lux" "lambda_"])) (#Cons [(_meta (#Tuple args')) (#Cons [body #Nil])])])))) #Nil])])])]))) #Nil]))) (#Cons [(#Meta [_ (#Symbol self)]) (#Cons [(#Meta [_ (#Tuple (#Cons [arg args']))]) (#Cons [body #Nil])])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" "lambda'"])) (#Cons [(_meta (#Symbol self)) (#Cons [arg (#Cons [(case' args' #Nil body _ (_meta (#Form (#Cons [(_meta (#Symbol ["lux" "lambda_"])) (#Cons [(_meta (#Tuple args')) (#Cons [body #Nil])])])))) #Nil])])])]))) #Nil]))) _ (fail "Wrong syntax for lambda"))))) (declare-macro' lambda_) (def' def_ (:' Macro (lambda_ [tokens] (case' tokens (#Cons [(#Meta [_ (#Tag ["" "export"])]) (#Cons [(#Meta [_ (#Form (#Cons [name args]))]) (#Cons [type (#Cons [body #Nil])])])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" "def'"])) (#Cons [name (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" ":'"])) (#Cons [type (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["lux" "lambda_"])) (#Cons [name (#Cons [(_meta (#Tuple args)) (#Cons [body #Nil])])])]))) #Nil])])]))) #Nil])])]))) (#Cons [(_meta (#Form (#Cons [($symbol ["" "export'"]) (#Cons [name #Nil])]))) #Nil])]))) (#Cons [(#Meta [_ (#Tag ["" "export"])]) (#Cons [name (#Cons [type (#Cons [body #Nil])])])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" "def'"])) (#Cons [name (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" ":'"])) (#Cons [type (#Cons [body #Nil])])]))) #Nil])])]))) (#Cons [(_meta (#Form (#Cons [($symbol ["" "export'"]) (#Cons [name #Nil])]))) #Nil])]))) (#Cons [(#Meta [_ (#Form (#Cons [name args]))]) (#Cons [type (#Cons [body #Nil])])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" "def'"])) (#Cons [name (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" ":'"])) (#Cons [type (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["lux" "lambda_"])) (#Cons [name (#Cons [(_meta (#Tuple args)) (#Cons [body #Nil])])])]))) #Nil])])]))) #Nil])])]))) #Nil]))) (#Cons [name (#Cons [type (#Cons [body #Nil])])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" "def'"])) (#Cons [name (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["" ":'"])) (#Cons [type (#Cons [body #Nil])])]))) #Nil])])]))) #Nil]))) _ (fail "Wrong syntax for def") )))) (declare-macro' def_) (def_ #export (defmacro tokens) Macro (case' tokens (#Cons [(#Meta [_ (#Form (#Cons [name args]))]) (#Cons [body #Nil])]) (return (:' SyntaxList (#Cons [($form (#Cons [($symbol ["lux" "def_"]) (#Cons [($form (#Cons [name args])) (#Cons [($symbol ["lux" "Macro"]) (#Cons [body #Nil])]) ])])) (#Cons [($form (#Cons [($symbol ["" "declare-macro'"]) (#Cons [name #Nil])])) #Nil])]))) (#Cons [(#Meta [_ (#Tag ["" "export"])]) (#Cons [(#Meta [_ (#Form (#Cons [name args]))]) (#Cons [body #Nil])])]) (return (:' SyntaxList (#Cons [($form (#Cons [($symbol ["lux" "def_"]) (#Cons [($tag ["" "export"]) (#Cons [($form (#Cons [name args])) (#Cons [($symbol ["lux" "Macro"]) (#Cons [body #Nil])]) ])])])) (#Cons [($form (#Cons [($symbol ["" "declare-macro'"]) (#Cons [name #Nil])])) #Nil])]))) _ (fail "Wrong syntax for defmacro"))) (declare-macro' defmacro) (defmacro #export (comment tokens) (return (:' SyntaxList #Nil))) (defmacro (->' tokens) (case' tokens (#Cons [input (#Cons [output #Nil])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Tag ["lux" "LambdaT"])) (#Cons [(_meta (#Tuple (#Cons [input (#Cons [output #Nil])]))) #Nil])]))) #Nil]))) (#Cons [input (#Cons [output others])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Tag ["lux" "LambdaT"])) (#Cons [(_meta (#Tuple (#Cons [input (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["lux" "->'"])) (#Cons [output others])]))) #Nil])]))) #Nil])]))) #Nil]))) _ (fail "Wrong syntax for ->'"))) (defmacro (All' tokens) (case' tokens (#Cons [(#Meta [_ (#Tuple #Nil)]) (#Cons [body #Nil])]) (return (:' SyntaxList (#Cons [body #Nil]))) (#Cons [(#Meta [_ (#Tuple (#Cons [(#Meta [_ (#Symbol ["" arg-name])]) other-args]))]) (#Cons [body #Nil])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Tag ["lux" "AllT"])) (#Cons [(_meta (#Tuple (#Cons [(_meta (#Tag ["lux" "None"])) (#Cons [(_meta (#Text "")) (#Cons [(_meta (#Text arg-name)) (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["lux" "All'"])) (#Cons [(_meta (#Tuple other-args)) (#Cons [body #Nil])])]))) #Nil])])])]))) #Nil])]))) #Nil]))) _ (fail "Wrong syntax for All'"))) (defmacro (B' tokens) (case' tokens (#Cons [(#Meta [_ (#Symbol ["" bound-name])]) #Nil]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Tag ["lux" "BoundT"])) (#Cons [(_meta (#Text bound-name)) #Nil])]))) #Nil]))) _ (fail "Wrong syntax for B'"))) (defmacro ($' tokens) (case' tokens (#Cons [x #Nil]) (return tokens) (#Cons [x (#Cons [y xs])]) (return (:' SyntaxList (#Cons [(_meta (#Form (#Cons [(_meta (#Symbol ["lux" "$'"])) (#Cons [(_meta (#Form (#Cons [(_meta (#Tag ["lux" "AppT"])) (#Cons [(_meta (#Tuple (#Cons [x (#Cons [y #Nil])]))) #Nil])]))) xs])]))) #Nil]))) _ (fail "Wrong syntax for $'"))) (def_ #export (fold f init xs) (All' [a b] (->' (->' (B' a) (B' b) (B' a)) (B' a) ($' List (B' b)) (B' a))) (case' xs #Nil init (#Cons [x xs']) (fold f (f init x) xs'))) (def_ #export (reverse list) (All' [a] (->' ($' List (B' a)) ($' List (B' a)))) (fold (:' (All' [a] (->' ($' List (B' a)) (B' a) ($' List (B' a)))) (lambda_ [tail head] (#Cons [head tail]))) #Nil list)) (defmacro #export (list xs) (return (:' SyntaxList (#Cons [(fold (:' (->' Syntax Syntax Syntax) (lambda_ [tail head] (_meta (#Form (#Cons [(_meta (#Tag ["lux" "Cons"])) (#Cons [(_meta (#Tuple (#Cons [head (#Cons [tail #Nil])]))) #Nil])]))))) (_meta (#Tag ["lux" "Nil"])) (reverse xs)) #Nil])))) (defmacro #export (list& xs) (case' (reverse xs) (#Cons [last init]) (return (:' SyntaxList (list (fold (:' (->' Syntax Syntax Syntax) (lambda_ [tail head] (_meta (#Form (list (_meta (#Tag ["lux" "Cons"])) (_meta (#Tuple (list head tail)))))))) last init)))) _ (fail "Wrong syntax for list&"))) (defmacro #export (lambda tokens) (let' [name tokens'] (:' (#TupleT (list Ident ($' List Syntax))) (case' tokens (#Cons [(#Meta [_ (#Symbol name)]) tokens']) [name tokens'] _ [["" ""] tokens])) (case' tokens' (#Cons [(#Meta [_ (#Tuple args)]) (#Cons [body #Nil])]) (case' args #Nil (fail "lambda requires a non-empty arguments tuple.") (#Cons [harg targs]) (let' body' (fold (:' (->' Syntax Syntax Syntax) (lambda_ [body' arg] ($form (list ($symbol ["" "lambda'"]) ($symbol ["" ""]) arg body')))) body (reverse targs)) (return (:' SyntaxList (list ($form (list ($symbol ["" "lambda'"]) ($symbol name) harg body'))))))) _ (fail "Wrong syntax for lambda")))) (defmacro #export (def tokens) (case' tokens (#Cons [(#Meta [_ (#Tag ["" "export"])]) (#Cons [(#Meta [_ (#Form (#Cons [name args]))]) (#Cons [type (#Cons [body #Nil])])])]) (return (:' SyntaxList (list ($form (list ($symbol ["" "def'"]) name ($form (list ($symbol ["" ":'"]) type ($form (list ($symbol ["lux" "lambda"]) name ($tuple args) body)))))) ($form (list ($symbol ["" "export'"]) name))))) (#Cons [(#Meta [_ (#Tag ["" "export"])]) (#Cons [name (#Cons [type (#Cons [body #Nil])])])]) (return (:' SyntaxList (list ($form (list ($symbol ["" "def'"]) name ($form (list ($symbol ["" ":'"]) type body)))) ($form (list ($symbol ["" "export'"]) name))))) (#Cons [(#Meta [_ (#Form (#Cons [name args]))]) (#Cons [type (#Cons [body #Nil])])]) (return (:' SyntaxList (list ($form (list ($symbol ["" "def'"]) name ($form (list ($symbol ["" ":'"]) type ($form (list ($symbol ["lux" "lambda"]) name ($tuple args) body))))))))) (#Cons [name (#Cons [type (#Cons [body #Nil])])]) (return (:' SyntaxList (list ($form (list ($symbol ["" "def'"]) name ($form (list ($symbol ["" ":'"]) type body))))))) _ (fail "Wrong syntax for def") )) (def (as-pairs xs) (All' [a] (->' ($' List (B' a)) ($' List (#TupleT (list (B' a) (B' a)))))) (case' xs (#Cons [x (#Cons [y xs'])]) (#Cons [[x y] (as-pairs xs')]) _ #Nil)) (defmacro #export (let tokens) (case' tokens (#Cons [(#Meta [_ (#Tuple bindings)]) (#Cons [body #Nil])]) (return (:' SyntaxList (list (fold (:' (->' Syntax (#TupleT (list Syntax Syntax)) Syntax) (lambda [body binding] (case' binding [label value] (_meta (#Form (list (_meta (#Symbol ["lux" "let'"])) label value body)))))) body (fold (:' (->' ($' List (#TupleT (list Syntax Syntax))) (#TupleT (list Syntax Syntax)) ($' List (#TupleT (list Syntax Syntax)))) (lambda [tail head] (#Cons [head tail]))) #Nil (as-pairs bindings)))))) _ (fail "Wrong syntax for let"))) (def #export (map f xs) (All' [a b] (->' (->' (B' a) (B' b)) ($' List (B' a)) ($' List (B' b)))) (case' xs #Nil #Nil (#Cons [x xs']) (#Cons [(f x) (map f xs')]))) (def #export (any? p xs) (All' [a] (->' (->' (B' a) Bool) ($' List (B' a)) Bool)) (case' xs #Nil false (#Cons [x xs']) (case' (p x) true true false (any? p xs')))) (def (spliced? token) (->' Syntax Bool) (case' token (#Meta [_ (#Form (#Cons [(#Meta [_ (#Symbol ["" "~@"])]) (#Cons [_ #Nil])]))]) true _ false)) (def (wrap-meta content) (->' Syntax Syntax) (_meta (#Form (list (_meta (#Tag ["lux" "Meta"])) (_meta (#Tuple (list (_meta (#Tuple (list (_meta (#Text "")) (_meta (#Int -1)) (_meta (#Int -1))))) content))))))) (def (untemplate-list tokens) (->' ($' List Syntax) Syntax) (case' tokens #Nil (_meta (#Tag ["lux" "Nil"])) (#Cons [token tokens']) (_meta (#Form (list (_meta (#Tag ["lux" "Cons"])) (_meta (#Tuple (list token (untemplate-list tokens'))))))))) (def (list:++ xs ys) (All' [a] (->' ($' List (B' a)) ($' List (B' a)) ($' List (B' a)))) (case' xs (#Cons [x xs']) (#Cons [x (list:++ xs' ys)]) #Nil ys)) (defmacro #export ($ tokens) (case' tokens (#Cons [op (#Cons [init args])]) (return (:' SyntaxList (list (fold (:' (->' Syntax Syntax Syntax) (lambda [a1 a2] ($form (list op a1 a2)))) init args)))) _ (fail "Wrong syntax for $"))) (def (splice untemplate tag elems) (->' (->' Syntax Syntax) Syntax ($' List Syntax) Syntax) (case' (any? spliced? elems) true (let [elems' (map (:' (->' Syntax Syntax) (lambda [elem] (case' elem (#Meta [_ (#Form (#Cons [(#Meta [_ (#Symbol ["" "~@"])]) (#Cons [spliced #Nil])]))]) spliced _ ($form (list ($symbol ["" ":'"]) ($symbol ["lux" "SyntaxList"]) ($form (list ($symbol ["lux" "list"]) (untemplate elem)))))))) elems)] (wrap-meta ($form (list tag ($form (list& ($symbol ["lux" "$"]) ($symbol ["lux" "list:++"]) elems')))))) false (wrap-meta ($form (list tag (untemplate-list (map untemplate elems))))))) (def (untemplate token) (->' Syntax Syntax) (case' token (#Meta [_ (#Bool value)]) (wrap-meta ($form (list ($tag ["lux" "Bool"]) (_meta (#Bool value))))) (#Meta [_ (#Int value)]) (wrap-meta ($form (list ($tag ["lux" "Int"]) (_meta (#Int value))))) (#Meta [_ (#Real value)]) (wrap-meta ($form (list ($tag ["lux" "Real"]) (_meta (#Real value))))) (#Meta [_ (#Char value)]) (wrap-meta ($form (list ($tag ["lux" "Char"]) (_meta (#Char value))))) (#Meta [_ (#Text value)]) (wrap-meta ($form (list ($tag ["lux" "Text"]) (_meta (#Text value))))) (#Meta [_ (#Tag [module name])]) (wrap-meta ($form (list ($tag ["lux" "Tag"]) ($tuple (list (_meta (#Text module)) (_meta (#Text name))))))) (#Meta [_ (#Symbol [module name])]) (wrap-meta ($form (list ($tag ["lux" "Symbol"]) ($tuple (list (_meta (#Text module)) (_meta (#Text name))))))) (#Meta [_ (#Tuple elems)]) (splice untemplate ($tag ["lux" "Tuple"]) elems) (#Meta [_ (#Form (#Cons [(#Meta [_ (#Symbol ["" "~"])]) (#Cons [unquoted #Nil])]))]) unquoted (#Meta [_ (#Form elems)]) (splice untemplate ($tag ["lux" "Form"]) elems) (#Meta [_ (#Record fields)]) (wrap-meta ($form (list ($tag ["lux" "Record"]) (untemplate-list (map (:' (->' (#TupleT (list Syntax Syntax)) Syntax) (lambda [kv] (let [[k v] kv] ($tuple (list (untemplate k) (untemplate v)))))) fields))))) )) (defmacro #export (` tokens) (case' tokens (#Cons [template #Nil]) (return (:' SyntaxList (list (untemplate template)))) _ (fail "Wrong syntax for `"))) (defmacro #export (|> tokens) (case' tokens (#Cons [init apps]) (return (:' SyntaxList (list (fold (:' (->' Syntax Syntax Syntax) (lambda [acc app] (case' app (#Meta [_ (#Form parts)]) ($form (list:++ parts (list acc))) _ (` ((~ app) (~ acc)))))) init apps)))) _ (fail "Wrong syntax for |>"))) (defmacro #export (if tokens) (case' tokens (#Cons [test (#Cons [then (#Cons [else #Nil])])]) (return (:' SyntaxList (list (` (case' (~ test) true (~ then) false (~ else)))))) _ (fail "Wrong syntax for if"))) ## (deftype (Lux a) ## (-> CompilerState (Either Text (, CompilerState a)))) (def #export Lux Type (All' [a] (->' CompilerState ($' Either Text (#TupleT (list CompilerState (B' a))))))) ## (defsig (Monad m) ## (: (All [a] (-> a (m a))) ## return) ## (: (All [a b] (-> (-> a (m b)) (m a) (m b))) ## bind)) (def Monad Type (All' [m] (#RecordT (list ["lux;return" (All' [a] (->' (B' a) ($' (B' m) (B' a))))] ["lux;bind" (All' [a b] (->' (->' (B' a) ($' (B' m) (B' b))) ($' (B' m) (B' a)) ($' (B' m) (B' b))))])))) (def Maybe:Monad ($' Monad Maybe) {#lux;return (lambda return [x] (#Some x)) #lux;bind (lambda [f ma] (case' ma #None #None (#Some a) (f a)))}) (def Lux:Monad ($' Monad Lux) {#lux;return (lambda return [x] (lambda [state] (#Right [state x]))) #lux;bind (lambda [f ma] (lambda [state] (case' (ma state) (#Left msg) (#Left msg) (#Right [state' a]) (f a state'))))}) (defmacro #export (^ tokens) (case' tokens (#Cons [(#Meta [_ (#Symbol ["" class-name])]) #Nil]) (return (:' SyntaxList (list (` (#DataT (~ (_meta (#Text class-name)))))))) _ (fail "Wrong syntax for ^"))) (defmacro #export (-> tokens) (case' (reverse tokens) (#Cons [output inputs]) (return (:' SyntaxList (list (fold (:' (->' Syntax Syntax Syntax) (lambda [o i] (` (#;LambdaT [(~ i) (~ o)])))) output inputs)))) _ (fail "Wrong syntax for ->"))) (defmacro #export (, tokens) (return (:' SyntaxList (list (` (#TupleT (list (~@ tokens)))))))) (defmacro (do tokens) (case' tokens (#Cons [monad (#Cons [(#Meta [_ (#Tuple bindings)]) (#Cons [body #Nil])])]) (let [body' (fold (:' (-> Syntax (, Syntax Syntax) Syntax) (lambda [body' binding] (let [[var value] binding] (` (;bind (lambda' (~ ($symbol ["" ""])) (~ var) (~ body')) (~ value)))))) body (reverse (as-pairs bindings)))] (return (:' SyntaxList (list (` (case' (~ monad) {#;return ;return #;bind ;bind} (~ body'))))))) _ (fail "Wrong syntax for do"))) (def (map% m f xs) ## (All [m a b] ## (-> (Monad m) (-> a (m b)) (List a) (m (List b)))) (All' [m a b] (-> ($' Monad (B' m)) (-> (B' a) ($' (B' m) (B' b))) ($' List (B' a)) ($' (B' m) ($' List (B' b))))) (let [{#;return ;return #;bind _} m] (case' xs #Nil (;return (:' List #Nil)) (#Cons [x xs']) (do m [y (f x) ys (map% m f xs')] (;return (:' List (#Cons [y ys])))) ))) (def #export (. f g) (All' [a b c] (-> (-> (B' b) (B' c)) (-> (B' a) (B' b)) (-> (B' a) (B' c)))) (lambda [x] (f (g x)))) (def (get-ident x) (-> Syntax ($' Maybe Text)) (case' x (#Meta [_ (#Symbol ["" sname])]) (#Some sname) _ #None)) (def (tuple->list tuple) (-> Syntax ($' Maybe ($' List Syntax))) (case' tuple (#Meta [_ (#Tuple members)]) (#Some members) _ #None)) (def RepEnv Type ($' List (, Text Syntax))) (def (make-env xs ys) (-> ($' List Text) ($' List Syntax) RepEnv) (case' (:' (, ($' List Text) ($' List Syntax)) [xs ys]) [(#Cons [x xs']) (#Cons [y ys'])] (#Cons [[x y] (make-env xs' ys')]) _ #Nil)) (def (text:= x y) (-> Text Text Bool) (jvm-invokevirtual java.lang.Object equals [java.lang.Object] x [y])) (def (get-rep key env) (-> Text RepEnv ($' Maybe Syntax)) (case' env #Nil #None (#Cons [[k v] env']) (if (text:= k key) (#Some v) (get-rep key env')))) (def (apply-template env template) (-> RepEnv Syntax Syntax) (case' template (#Meta [_ (#Symbol ["" sname])]) (case' (get-rep sname env) (#Some subst) subst _ template) (#Meta [_ (#Tuple elems)]) ($tuple (map (apply-template env) elems)) (#Meta [_ (#Form elems)]) ($form (map (apply-template env) elems)) (#Meta [_ (#Record members)]) ($record (map (:' (-> (, Syntax Syntax) (, Syntax Syntax)) (lambda [kv] (let [[slot value] kv] [(apply-template env slot) (apply-template env value)]))) members)) _ template)) (def (join-map f xs) (All' [a b] (-> (-> (B' a) ($' List (B' b))) ($' List (B' a)) ($' List (B' b)))) (case' xs #Nil #Nil (#Cons [x xs']) (list:++ (f x) (join-map f xs')))) (defmacro (do-template tokens) (case' tokens (#Cons [(#Meta [_ (#Tuple bindings)]) (#Cons [(#Meta [_ (#Tuple templates)]) data])]) (case' (:' (, ($' Maybe ($' List Text)) ($' Maybe ($' List ($' List Syntax)))) [(map% Maybe:Monad get-ident bindings) (map% Maybe:Monad tuple->list data)]) [(#Some bindings') (#Some data')] (let [apply (:' (-> RepEnv ($' List Syntax)) (lambda [env] (map (apply-template env) templates)))] (|> data' (join-map (. apply (make-env bindings'))) return)) _ (fail "All the do-template bindigns must be symbols.")) _ (fail "Wrong syntax for do-template"))) (do-template [ ] [(def #export ( x y) (-> Bool) ( x y))] [int:= jvm-leq Int] [int:> jvm-lgt Int] [int:< jvm-llt Int] [real:= jvm-deq Real] [real:> jvm-dgt Real] [real:< jvm-dlt Real] ) (do-template [ ] [(def #export ( x y) (-> ) ( x y))] [int:+ jvm-ladd Int] [int:- jvm-lsub Int] [int:* jvm-lmul Int] [int:/ jvm-ldiv Int] [int:% jvm-lrem Int] [real:+ jvm-dadd Real] [real:- jvm-dsub Real] [real:* jvm-dmul Real] [real:/ jvm-ddiv Real] [real:% jvm-drem Real] ) (def (multiple? div n) (-> Int Int Bool) (int:= 0 (int:% n div))) (def #export (length list) (-> List Int) (fold (lambda [acc _] (int:+ 1 acc)) 0 list)) (def #export (not x) (-> Bool Bool) (if x false true)) (def (text:++ x y) (-> Text Text Text) (jvm-invokevirtual java.lang.String concat [java.lang.String] x [y])) (def (ident->text ident) (-> Ident Text) (let [[module name] ident] ($ text:++ module ";" name))) (defmacro #export (| tokens) (do Lux:Monad [pairs (map% Lux:Monad (:' (-> Syntax ($' Lux Syntax)) (lambda [token] (case' token (#Meta [_ (#Tag ident)]) (;return (:' Syntax (` [(~ ($text (ident->text ident))) (,)]))) (#Meta [_ (#Form (#Cons [(#Meta [_ (#Tag ident)]) (#Cons [value #Nil])]))]) (;return (:' Syntax (` [(~ ($text (ident->text ident))) (~ value)]))) _ (fail "Wrong syntax for |")))) tokens)] (;return (:' SyntaxList (list (` (#VariantT (list (~@ pairs))))))))) (defmacro #export (& tokens) (if (not (multiple? 2 (length tokens))) (fail "& expects an even number of arguments.") (do Lux:Monad [pairs (map% Lux:Monad (:' (-> (, Syntax Syntax) ($' Lux Syntax)) (lambda [pair] (case' pair [(#Meta [_ (#Tag ident)]) value] (;return (:' Syntax (` [(~ ($text (ident->text ident))) (~ value)]))) _ (fail "Wrong syntax for &")))) (as-pairs tokens))] (;return (:' SyntaxList (list (` (#RecordT (list (~@ pairs)))))))))) (def (replace-syntax reps syntax) (-> RepEnv Syntax Syntax) (case' syntax (#Meta [_ (#Symbol ["" name])]) (case' (get-rep name reps) (#Some replacement) replacement #None syntax) (#Meta [_ (#Form parts)]) (#Meta [_ (#Form (map (replace-syntax reps) parts))]) (#Meta [_ (#Tuple members)]) (#Meta [_ (#Tuple (map (replace-syntax reps) members))]) (#Meta [_ (#Record slots)]) (#Meta [_ (#Record (map (:' (-> (, Syntax Syntax) (, Syntax Syntax)) (lambda [slot] (let [[k v] slot] [(replace-syntax reps k) (replace-syntax reps v)]))) slots))]) _ syntax) ) (defmacro #export (All tokens) (let [[self-ident tokens'] (:' (, Text SyntaxList) (case' tokens (#Cons [(#Meta [_ (#Symbol ["" self-ident])]) tokens']) [self-ident tokens'] _ ["" tokens]))] (case' tokens' (#Cons [(#Meta [_ (#Tuple args)]) (#Cons [body #Nil])]) (case' (map% Maybe:Monad get-ident args) (#Some idents) (case' idents #Nil (return (:' SyntaxList (list body))) (#Cons [harg targs]) (let [replacements (map (:' (-> Text (, Text Syntax)) (lambda [ident] [ident (` (#BoundT (~ ($text ident))))])) (list& self-ident idents)) body' (fold (:' (-> Syntax Text Syntax) (lambda [body' arg'] (` (#AllT [#None "" (~ ($text arg')) (~ body')])))) (replace-syntax replacements body) (reverse targs))] (return (:' SyntaxList (list (` (#AllT [#None (~ ($text self-ident)) (~ ($text harg)) (~ body')]))))))) #None (fail "'All' arguments must be symbols.")) _ (fail "Wrong syntax for All")) )) (def (get k plist) (All [a] (-> Text ($' List (, Text a)) ($' Maybe a))) (case' plist (#Cons [[k' v] plist']) (if (text:= k k') (#Some v) (get k plist')) #Nil #None)) ## (def #export (find-macro ident state) ## (-> Ident ($' Lux Macro)) ## (let [[module name] ident] ## (case' state ## {#source source #modules modules #module-aliases module-aliases ## #envs envs #types types #host host ## #seed seed} ## (case' (:' ($' Maybe Macro) ## (do Maybe:Monad ## [bindings (get module modules) ## gdef (get name bindings)] ## (case' gdef ## (#MacroD macro') ## (#Some macro') ## _ ## #None))) ## (#Some macro) ## (#Right [state macro]) ## #None ## (#Left ($ text:++ "There is no macro by the name: " module ";" name)))))) (def #export (find-macro ident state) (-> Ident ($' Lux Macro)) (let [[module name] ident] (case' state {#source source #modules modules #module-aliases module-aliases #envs envs #types types #host host #seed seed} (case' (:' ($' Maybe Macro) (case' (get module modules) (#Some bindings) (case' (get name bindings) (#Some gdef) (case' gdef (#MacroD macro') (#Some macro') _ #None) #None #None) #None #None)) (#Some macro) (#Right [state macro]) #None (#Left ($ text:++ "There is no macro by the name: " module ";" name)))))) (def (join-list xs) (All [a] (-> ($' List ($' List a)) ($' List a))) (fold list:++ #Nil xs)) ## (def #export (macro-expand syntax state) ## (-> Syntax ($' Lux ($' List Syntax))) ## (case' syntax ## (#Meta [_ (#Form (#Cons [(#Meta [_ (#Symbol macro-name)]) args]))]) ## (do Lux:Monad ## [macro' (find-macro macro-name)] ## (case' macro' ## (#Some macro) ## (do Lux:Monad ## [expansion (macro args) ## expansion' (map% Lux:Monad macro-expand expansion)] ## (return (:' SyntaxList (join-list expansion')))) ## #None ## (do Lux:Monad ## [parts' (map% Lux:Monad macro-expand (list& ($symbol macro-name) args))] ## (return (:' Syntax (list ($form (join-list parts')))))))) ## (#Meta [_ (#Tuple members)]) ## (do Lux:Monad ## [members' (map% Lux:Monad macro-expand members)] ## (return (:' Syntax (list ($tuple (join-list members')))))) ## _ ## (return (:' SyntaxList (list syntax))))) (def #export (macro-expand syntax state) (-> Syntax ($' Lux ($' List Syntax))) (case' syntax (#Meta [_ (#Form (#Cons [(#Meta [_ (#Symbol macro-name)]) args]))]) (do Lux:Monad [macro' (find-macro macro-name)] (case' macro' (#Some macro) (do Lux:Monad [expansion (macro args) expansion' (map% Lux:Monad macro-expand expansion)] (;return (:' SyntaxList (join-list expansion')))) #None (do Lux:Monad [parts' (map% Lux:Monad macro-expand (list& ($symbol macro-name) args))] (;return (:' Syntax (list ($form (join-list parts')))))))) (#Meta [_ (#Tuple members)]) (do Lux:Monad [members' (map% Lux:Monad macro-expand members)] (;return (:' Syntax (list ($tuple (join-list members')))))) _ (return (:' SyntaxList (list syntax))))) ## ## (def (walk-type type) ## ## (-> Syntax ($' Lux Syntax)) ## ## (case' type ## ## (#Meta [_ (#Form (#Cons [(#Meta [_ (#Symbol sym)]) args]))]) ## ## (do' [macro' (find-macro sym)] ## ## (case' macro' ## ## (#Some macro) ## ## (do' [expansion (macro args)] ## ## (case' expansion ## ## (#Cons [expansion' #Nil]) ## ## (walk-type expansion') ## ## _ ## ## (fail "Macro can't expand to more than 1 output."))) ## ## #None ## ## (do' [args' (map% walk-type args)] ## ## (return (fold (:' (-> Syntax Syntax Syntax) ## ## (lambda [f a] ## ## (` (#AppT [(~ f) (~ a)])))) ## ## sym ## ## args'))))) ## ## (#Meta [_ (#Form (#Cons [(#Meta [_ (#Tag tag)]) args]))]) ## ## ... ## ## (#Meta [_ (#Symbol _)]) ## ## (return type) ## ## _ ## ## (fail "Wrong syntax for walk-type"))) ## ## (defmacro (->type tokens) ## ## (case' tokens ## ## (#Cons [type #Nil]) ## ## (do' [type' (walk-type type)] ## ## (return (list type'))) ## ## _ ## ## (fail "Wrong syntax for ->type"))) ## ## (defmacro (: tokens) ## ## (case' tokens ## ## (#Cons [type (#Cons [value #Nil])]) ## ## (return (list (` (:' (->type (~ type)) (~ value))))) ## ## _ ## ## (fail "Wrong syntax for :"))) ## ## (defmacro (:! tokens) ## ## (case' tokens ## ## (#Cons [type (#Cons [value #Nil])]) ## ## (return (list (` (:!' (->type (~ type)) (~ value))))) ## ## _ ## ## (fail "Wrong syntax for :!"))) ## ## (deftype (IO a) ## ## (-> (,) a)) ## ## (defmacro (io tokens) ## ## (case' tokens ## ## (#Cons [value #Nil]) ## ## (return (list (` (lambda [_] (~ value))))))) ## (defmacro #export (exec tokens) ## (case' (reverse tokens) ## (#Cons [value actions]) ## (let [dummy ($symbol ["" ""])] ## (return (:' SyntaxList ## (list (fold (:' (-> Syntax Syntax Syntax) ## (lambda [post pre] ## (` (case' (~ pre) (~ dummy) (~ post))))) ## value ## actions))))) ## _ ## (fail "Wrong syntax for exec"))) ## (def #export (print x) ## (-> Text (IO (,))) ## (io (jvm-invokevirtual java.io.PrintStream print [java.lang.Object] ## (jvm-getstatic java.lang.System out) [x]))) ## (def #export (println x) ## (-> Text (IO (,))) ## (print (text:++ x "\n"))) ## ## (defmacro (loop tokens) ## ## (case' tokens ## ## (#Cons [bindings (#Cons [body #Nil])]) ## ## (let [pairs (as-pairs bindings)] ## ## (return (list (#Form (#Cons [(` (lambda (~ (#Symbol ["" "recur"])) (~ (#Tuple (map first pairs))) ## ## (~ body))) ## ## (map second pairs)]))))))) ## ## ## (do-template [ ] ## ## ## (def (int+ )) ## ## ## [inc 1] ## ## ## [dec -1]) ## ## ## (defmacro (get@ tokens) ## ## ## (let [output (case' tokens ## ## ## (#Cons [tag (#Cons [record #Nil])]) ## ## ## (` (get@' (~ tag) (~ record))) ## ## ## (#Cons [tag #Nil]) ## ## ## (` (lambda [record] (get@' (~ tag) record))))] ## ## ## (return (list output)))) ## ## ## (defmacro (set@ tokens) ## ## ## (let [output (case' tokens ## ## ## (#Cons [tag (#Cons [value (#Cons [record #Nil])])]) ## ## ## (` (set@' (~ tag) (~ value) (~ record))) ## ## ## (#Cons [tag (#Cons [value #Nil])]) ## ## ## (` (lambda [record] (set@' (~ tag) (~ value) record))) ## ## ## (#Cons [tag #Nil]) ## ## ## (` (lambda [value record] (set@' (~ tag) value record))))] ## ## ## (return (list output)))) ## ## ## (defmacro (update@ tokens) ## ## ## (let [output (case' tokens ## ## ## (#Cons [tag (#Cons [func (#Cons [record #Nil])])]) ## ## ## (` (let [_record_ (~ record)] ## ## ## (set@' (~ tag) ((~ func) (get@' (~ tag) _record_)) _record_))) ## ## ## (#Cons [tag (#Cons [func #Nil])]) ## ## ## (` (lambda [record] ## ## ## (` (set@' (~ tag) ((~ func) (get@' (~ tag) record)) record)))) ## ## ## (#Cons [tag #Nil]) ## ## ## (` (lambda [func record] ## ## ## (set@' (~ tag) (func (get@' (~ tag) record)) record))))] ## ## ## (return (list output)))) ## ## (def (show-int int) ## ## (-> Int Text) ## ## (jvm-invokevirtual java.lang.Object "toString" [] ## ## int [])) ## ## (def gensym ## ## (LuxStateM Syntax) ## ## (lambda [state] ## ## [(update@ [#gen-seed] inc state) ## ## (_meta (#Symbol ($ text-++ "__" (show-int (get@ [#gen-seed] state)) "__")))])) ## ## (do-template [ ] ## ## (def ( pair) ## ## (case' pair ## ## [f s] ## ## )) ## ## [first f] ## ## [second s]) ## ## (defmacro (case tokens) ## ## (case' tokens ## ## (#Cons value branches) ## ## (loop [kind #Pattern ## ## pieces branches ## ## new-pieces (list)] ## ## (case' pieces ## ## #Nil ## ## (return (list (' (case' (~ value) (~@ new-pieces))))) ## ## (#Cons piece pieces') ## ## (let [[kind' expanded more-pieces] (case' kind ## ## #Body ## ## [#Pattern (list piece) #Nil] ## ## #Pattern ## ## (do [expansion (macro-expand piece)] ## ## (case' expansion ## ## #Nil ## ## [#Pattern #Nil #Nil] ## ## (#Cons exp #Nil) ## ## [#Body (list exp) #Nil] ## ## (#Cons exp exps) ## ## [#Body (list exp) exps])) ## ## )] ## ## (recur kind' (++ expanded new-pieces) (++ more-pieces pieces)))) ## ## )))