mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	More work on closures in loops. Fix loop macro to
not store bindings as vars.
This commit is contained in:
		| @@ -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)) | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose