More work on closures in loops. Fix loop macro to

not store bindings as vars.
This commit is contained in:
Calvin Rose 2018-07-11 22:18:24 -04:00
parent 79f84e52fc
commit abe7d592aa
3 changed files with 27 additions and 9 deletions

View File

@ -289,34 +289,40 @@
(error ("unexpected loop predicate: " verb)))
(case verb
:iterate (do
(def preds @['and (tuple ':= bindings object)])
(def $iter (gensym))
(def preds @['and (tuple ':= $iter object)])
(def subloop (doone (+ i 3) preds))
(tuple 'do
(tuple 'var bindings nil)
(tuple 'var $iter nil)
(tuple 'while (apply1 tuple preds)
(tuple 'def bindings $iter)
subloop)))
:range (do
(def [start end _inc] object)
(def inc (if _inc _inc 1))
(def endsym (gensym))
(def preds @['and (tuple < bindings endsym)])
(def $iter (gensym))
(def preds @['and (tuple < $iter endsym)])
(def subloop (doone (+ i 3) preds))
(tuple 'do
(tuple 'var bindings start)
(tuple 'var $iter start)
(tuple 'def endsym end)
(tuple 'while (apply1 tuple preds)
(tuple 'def bindings $iter)
subloop
(tuple ':= bindings (tuple + bindings inc)))))
(tuple ':= $iter (tuple + $iter inc)))))
:keys (do
(def $dict (gensym))
(def preds @['and (tuple not= nil bindings)])
(def $iter (gensym))
(def preds @['and (tuple not= nil $iter)])
(def subloop (doone (+ i 3) preds))
(tuple 'do
(tuple 'def $dict object)
(tuple 'var bindings (tuple next $dict nil))
(tuple 'var $iter (tuple next $dict nil))
(tuple 'while (apply1 tuple preds)
(tuple 'def bindings $iter)
subloop
(tuple ':= bindings (tuple next $dict bindings)))))
(tuple ':= $iter (tuple next $dict $iter)))))
:in (do
(def $len (gensym))
(def $i (gensym))

View File

@ -441,13 +441,14 @@ static DstSlot dstc_while(DstFopts opts, int32_t argn, const Dst *argv) {
dstc_emit(c, DOP_TAILCALL | (tempself << 8));
/* Compile function */
DstFuncDef *def = dstc_pop_funcdef(c);
def->name = dst_cstring("_while-iife");
def->name = dst_cstring("_while");
int32_t defindex = dstc_addfuncdef(c, def);
/* And then load the closure and call it. */
int32_t cloreg = dstc_regalloc_temp(&c->scope->ra, DSTC_REGTEMP_0);
dstc_emit(c, DOP_CLOSURE | (cloreg << 8) | (defindex << 16));
dstc_emit(c, DOP_CALL | (cloreg << 8) | (cloreg << 16));
dstc_regalloc_free(&c->scope->ra, cloreg);
c->scope->flags |= DST_SCOPE_CLOSURE;
return dstc_cslot(dst_wrap_nil());
}
@ -480,6 +481,7 @@ static DstSlot dstc_fn(DstFopts opts, int32_t argn, const Dst *argv) {
int selfref = 0;
/* Begin function */
c->scope->flags |= DST_SCOPE_CLOSURE;
dstc_scope(&fnscope, c, DST_SCOPE_FUNCTION, "function");
if (argn < 2) {

View File

@ -202,4 +202,14 @@
(assert (not= 1 1 0) "not= 1")
(assert (not= 0 1 1) "not= 2")
# Closure in while loop
(def closures @[])
(loop [i :range [0 5]]
(array.push closures (fn [] i)))
(assert (= 0 ((get closures 0))) "closure in loop 0")
(assert (= 1 ((get closures 1))) "closure in loop 1")
(assert (= 2 ((get closures 2))) "closure in loop 2")
(assert (= 3 ((get closures 3))) "closure in loop 3")
(assert (= 4 ((get closures 4))) "closure in loop 4")
(end-suite)