From abe7d592aa195137c866410ea481a3398dd79ccb Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Wed, 11 Jul 2018 22:18:24 -0400 Subject: [PATCH] More work on closures in loops. Fix loop macro to not store bindings as vars. --- src/core/core.dst | 22 ++++++++++++++-------- src/core/specials.c | 4 +++- test/suite1.dst | 10 ++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/core/core.dst b/src/core/core.dst index c072b78a..5a1f6004 100644 --- a/src/core/core.dst +++ b/src/core/core.dst @@ -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)) diff --git a/src/core/specials.c b/src/core/specials.c index 4fc2a35e..86cdb190 100644 --- a/src/core/specials.c +++ b/src/core/specials.c @@ -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) { diff --git a/test/suite1.dst b/test/suite1.dst index 98045538..811c9470 100644 --- a/test/suite1.dst +++ b/test/suite1.dst @@ -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)