1
0
mirror of https://github.com/janet-lang/janet synced 2025-03-31 12:36:56 +00:00

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))) (error ("unexpected loop predicate: " verb)))
(case verb (case verb
:iterate (do :iterate (do
(def preds @['and (tuple ':= bindings object)]) (def $iter (gensym))
(def preds @['and (tuple ':= $iter object)])
(def subloop (doone (+ i 3) preds)) (def subloop (doone (+ i 3) preds))
(tuple 'do (tuple 'do
(tuple 'var bindings nil) (tuple 'var $iter nil)
(tuple 'while (apply1 tuple preds) (tuple 'while (apply1 tuple preds)
(tuple 'def bindings $iter)
subloop))) subloop)))
:range (do :range (do
(def [start end _inc] object) (def [start end _inc] object)
(def inc (if _inc _inc 1)) (def inc (if _inc _inc 1))
(def endsym (gensym)) (def endsym (gensym))
(def preds @['and (tuple < bindings endsym)]) (def $iter (gensym))
(def preds @['and (tuple < $iter endsym)])
(def subloop (doone (+ i 3) preds)) (def subloop (doone (+ i 3) preds))
(tuple 'do (tuple 'do
(tuple 'var bindings start) (tuple 'var $iter start)
(tuple 'def endsym end) (tuple 'def endsym end)
(tuple 'while (apply1 tuple preds) (tuple 'while (apply1 tuple preds)
(tuple 'def bindings $iter)
subloop subloop
(tuple ':= bindings (tuple + bindings inc))))) (tuple ':= $iter (tuple + $iter inc)))))
:keys (do :keys (do
(def $dict (gensym)) (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)) (def subloop (doone (+ i 3) preds))
(tuple 'do (tuple 'do
(tuple 'def $dict object) (tuple 'def $dict object)
(tuple 'var bindings (tuple next $dict nil)) (tuple 'var $iter (tuple next $dict nil))
(tuple 'while (apply1 tuple preds) (tuple 'while (apply1 tuple preds)
(tuple 'def bindings $iter)
subloop subloop
(tuple ':= bindings (tuple next $dict bindings))))) (tuple ':= $iter (tuple next $dict $iter)))))
:in (do :in (do
(def $len (gensym)) (def $len (gensym))
(def $i (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)); dstc_emit(c, DOP_TAILCALL | (tempself << 8));
/* Compile function */ /* Compile function */
DstFuncDef *def = dstc_pop_funcdef(c); DstFuncDef *def = dstc_pop_funcdef(c);
def->name = dst_cstring("_while-iife"); def->name = dst_cstring("_while");
int32_t defindex = dstc_addfuncdef(c, def); int32_t defindex = dstc_addfuncdef(c, def);
/* And then load the closure and call it. */ /* And then load the closure and call it. */
int32_t cloreg = dstc_regalloc_temp(&c->scope->ra, DSTC_REGTEMP_0); 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_CLOSURE | (cloreg << 8) | (defindex << 16));
dstc_emit(c, DOP_CALL | (cloreg << 8) | (cloreg << 16)); dstc_emit(c, DOP_CALL | (cloreg << 8) | (cloreg << 16));
dstc_regalloc_free(&c->scope->ra, cloreg); dstc_regalloc_free(&c->scope->ra, cloreg);
c->scope->flags |= DST_SCOPE_CLOSURE;
return dstc_cslot(dst_wrap_nil()); 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; int selfref = 0;
/* Begin function */ /* Begin function */
c->scope->flags |= DST_SCOPE_CLOSURE;
dstc_scope(&fnscope, c, DST_SCOPE_FUNCTION, "function"); dstc_scope(&fnscope, c, DST_SCOPE_FUNCTION, "function");
if (argn < 2) { if (argn < 2) {

View File

@ -202,4 +202,14 @@
(assert (not= 1 1 0) "not= 1") (assert (not= 1 1 0) "not= 1")
(assert (not= 0 1 1) "not= 2") (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) (end-suite)