(.module: [library [lux "*" [abstract ["[0]" monad {"+" do}]] [control ["[0]" function]] [data [collection ["[0]" list ("[1]@[0]" functor monoid)]]] [math [number ["n" nat]]] [tool [compiler ["[0]" phase] [reference [variable {"+" Register}]] [language [lux ["[0]" synthesis {"+" Synthesis}] ["[0]" generation]]]]]]] [luxc [lang [host [jvm {"+" Inst Operation Phase Generator} ["_" inst]]]]] ["[0]" //]) (def: (invariant? expected actual) (-> Register Synthesis Bit) (case actual (^ (synthesis.variable/local actual)) (n.= expected actual) _ false)) (def: .public (recur translate archive argsS) (Generator (List Synthesis)) (do [@ phase.monad] [[@begin start] generation.anchor .let [pairs (|> argsS list.enumeration (list@each (function (_ [register argument]) [(n.+ start register) argument])))] ... It may look weird that first I compile the values separately, ... and then I compile the stores/allocations. ... It must be done that way in order to avoid a potential bug. ... Let's say that you'll recur with 2 expressions: X and Y. ... If Y depends on the value of X, and you don't compile values ... and stores separately, then by the time Y is evaluated, it ... will refer to the new value of X, instead of the old value, and ... shouldn't be the case. valuesI+ (monad.each @ (function (_ [register argS]) (: (Operation Inst) (if (invariant? register argS) (in function.identity) (translate archive argS)))) pairs) .let [storesI+ (list@each (function (_ [register argS]) (: Inst (if (invariant? register argS) function.identity (_.ASTORE register)))) (list.reversed pairs))]] (in (|>> (_.fuse valuesI+) (_.fuse storesI+) (_.GOTO @begin))))) (def: .public (scope translate archive [start initsS+ iterationS]) (Generator [Nat (List Synthesis) Synthesis]) (do [@ phase.monad] [@begin _.make_label initsI+ (monad.each @ (translate archive) initsS+) iterationI (generation.with_anchor [@begin start] (translate archive iterationS)) .let [initializationI (|> (list.enumeration initsI+) (list@each (function (_ [register initI]) (|>> initI (_.ASTORE (n.+ start register))))) _.fuse)]] (in (|>> initializationI (_.label @begin) iterationI))))