diff options
Diffstat (limited to '')
-rw-r--r-- | stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/loop.lux | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/loop.lux b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/loop.lux new file mode 100644 index 000000000..465e8d1af --- /dev/null +++ b/stdlib/source/library/lux/tool/compiler/language/lux/phase/generation/jvm/loop.lux @@ -0,0 +1,90 @@ +(.module: + [library + [lux #* + [abstract + ["." monad (#+ do)]] + [control + ["." function]] + [data + ["." product] + [number + ["n" nat]] + [collection + ["." list ("#\." functor)]]] + [target + [jvm + ["_" bytecode (#+ Label Bytecode) ("#\." monad)]]]]] + ["." // #_ + ["#." runtime (#+ Operation Phase Generator)] + ["#." value] + [//// + ["." synthesis (#+ Path Synthesis)] + ["." generation] + [/// + ["." phase] + [reference + [variable (#+ Register)]]]]]) + +(def: (invariant? register changeS) + (-> Register Synthesis Bit) + (case changeS + (^ (synthesis.variable/local var)) + (n.= register var) + + _ + false)) + +(def: no-op + (_\wrap [])) + +(def: #export (recur translate archive updatesS) + (Generator (List Synthesis)) + (do {! phase.monad} + [[@begin offset] generation.anchor + updatesG (|> updatesS + list.enumeration + (list\map (function (_ [index updateS]) + [(n.+ offset index) updateS])) + (monad.map ! (function (_ [register updateS]) + (if (invariant? register updateS) + (wrap [..no-op + ..no-op]) + (do ! + [fetchG (translate archive updateS) + #let [storeG (_.astore register)]] + (wrap [fetchG storeG]))))))] + (wrap ($_ _.compose + ## It may look weird that first I fetch all the values separately, + ## and then I store them all. + ## 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 perform fetches + ## and stores separately, then by the time Y is evaluated, it + ## will refer to the new value of X, instead of the old value, as + ## should be the case. + (|> updatesG + (list\map product.left) + (monad.seq _.monad)) + (|> updatesG + list.reverse + (list\map product.right) + (monad.seq _.monad)) + (_.goto @begin))))) + +(def: #export (scope translate archive [offset initsS+ iterationS]) + (Generator [Nat (List Synthesis) Synthesis]) + (do {! phase.monad} + [@begin //runtime.forge-label + initsI+ (monad.map ! (translate archive) initsS+) + iterationG (generation.with-anchor [@begin offset] + (translate archive iterationS)) + #let [initializationG (|> (list.enumeration initsI+) + (list\map (function (_ [index initG]) + ($_ _.compose + initG + (_.astore (n.+ offset index))))) + (monad.seq _.monad))]] + (wrap ($_ _.compose + initializationG + (_.set-label @begin) + iterationG)))) |