(.module: lux (lux (control [monad #+ do] pipe) (data [product] [text] text/format (coll [list "list/" Functor Fold])) [macro]) (luxc ["&" lang] (lang ["ls" synthesis] [".L" variable #+ Variable] (host [python #+ Expression Statement @@]))) [//] (// [".T" reference])) (def: #export (translate-apply translate functionS argsS+) (-> (-> ls.Synthesis (Meta Expression)) ls.Synthesis (List ls.Synthesis) (Meta Expression)) (do macro.Monad [functionO (translate functionS) argsO+ (monad.map @ translate argsS+)] (wrap (python.apply argsO+ functionO)))) (def: $curried (python.var "curried")) (def: (input-declaration register) (python.set! (list (referenceT.variable (inc register))) (python.nth (|> register .int python.int) (@@ $curried)))) (def: (with-closure function-name inits function-definition) (-> Text (List Expression) Statement (Meta Expression)) (let [$closure (python.var (format function-name "___CLOSURE"))] (case inits #.Nil (do macro.Monad [_ (//.save function-definition)] (wrap (python.global function-name))) _ (do macro.Monad [_ (//.save (python.def! $closure (|> (list.enumerate inits) (list/map (|>> product.left referenceT.closure))) ($_ python.then! function-definition (python.return! (python.global function-name)))))] (wrap (python.apply inits (@@ $closure))))))) (def: #export (translate-function translate env arity bodyS) (-> (-> ls.Synthesis (Meta Expression)) (List Variable) ls.Arity ls.Synthesis (Meta Expression)) (do macro.Monad [[function-name bodyO] (//.with-sub-context (do @ [function-name //.context] (//.with-anchor [function-name +1] (translate bodyS)))) closureO+ (monad.map @ referenceT.translate-variable env) #let [args-initsO+ (|> (list.n/range +0 (dec arity)) (list/map input-declaration) (case> #.Nil python.no-op! (#.Cons head tail) (list/fold python.then! head tail))) arityO (|> arity .int python.int) @curried (@@ $curried) $num_args (python.var "num_args") @num_args (@@ $num_args) $function (python.var function-name) @function (@@ $function)]] (with-closure function-name closureO+ (python.def! $function (list (python.poly $curried)) ($_ python.then! (let [@len (python.global "len")] (python.set! (list $num_args) (python.apply (list @curried) @len))) (python.if! (python.= arityO @num_args) ($_ python.then! (python.set! (list (referenceT.variable +0)) @function) args-initsO+ (python.while! (python.bool true) (python.return! bodyO))) (python.if! (python.> arityO @num_args) (let [arity-args (python.slice (python.int 0) arityO @curried) output-func-args (python.slice arityO @num_args @curried)] (python.return! (|> @function (python.apply-poly (list) arity-args) (python.apply-poly (list) output-func-args)))) (let [$next (python.var "next") $missing (python.var "missing")] ($_ python.then! (python.def! $next (list (python.poly $missing)) (python.return! (|> @function (python.apply-poly (list) (|> @curried (python.+ (@@ $missing))))))) (python.return! (@@ $next))))))))) ))