mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Add early returns via break.
Inside a while loop, the argument to break does nothing as while loops always return nil.
This commit is contained in:
		| @@ -479,11 +479,12 @@ static int32_t janetc_addfuncdef(JanetCompiler *c, JanetFuncDef *def) { | |||||||
| static JanetSlot janetc_break(JanetFopts opts, int32_t argn, const Janet *argv) { | static JanetSlot janetc_break(JanetFopts opts, int32_t argn, const Janet *argv) { | ||||||
|     JanetCompiler *c = opts.compiler; |     JanetCompiler *c = opts.compiler; | ||||||
|     JanetScope *scope = c->scope; |     JanetScope *scope = c->scope; | ||||||
|     (void) argv; |     if (argn > 1) { | ||||||
|     if (argn != 0) { |         janetc_cerror(c, "expected at most 1 argument"); | ||||||
|         janetc_cerror(c, "expected no arguments"); |  | ||||||
|         return janetc_cslot(janet_wrap_nil()); |         return janetc_cslot(janet_wrap_nil()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /* Find scope to break from */ | ||||||
|     while (scope) { |     while (scope) { | ||||||
|         if (scope->flags & (JANET_SCOPE_FUNCTION | JANET_SCOPE_WHILE)) |         if (scope->flags & (JANET_SCOPE_FUNCTION | JANET_SCOPE_WHILE)) | ||||||
|             break; |             break; | ||||||
| @@ -493,13 +494,32 @@ static JanetSlot janetc_break(JanetFopts opts, int32_t argn, const Janet *argv) | |||||||
|         janetc_cerror(c, "break must occur in while loop or closure"); |         janetc_cerror(c, "break must occur in while loop or closure"); | ||||||
|         return janetc_cslot(janet_wrap_nil()); |         return janetc_cslot(janet_wrap_nil()); | ||||||
|     } |     } | ||||||
|     if (scope->flags | JANET_SCOPE_FUNCTION) { |  | ||||||
|         /* Just return, either in IIFE or closure body */ |     /* Emit code to break from that scope */ | ||||||
|         janetc_emit(c, JOP_RETURN_NIL); |     JanetFopts subopts = janetc_fopts_default(c); | ||||||
|         JanetSlot s = janetc_cslot(janet_wrap_nil()); |     if (scope->flags & JANET_SCOPE_FUNCTION) { | ||||||
|         s.flags |= JANET_SLOT_RETURNED; |         if (!(scope->flags & JANET_SCOPE_WHILE) && argn) { | ||||||
|         return s; |             /* Closure body with return argument */ | ||||||
|  |             subopts.flags |= JANET_FOPTS_TAIL; | ||||||
|  |             JanetSlot ret = janetc_value(subopts, argv[0]); | ||||||
|  |             ret.flags |= JANET_SLOT_RETURNED; | ||||||
|  |             return ret; | ||||||
|  |         } else { | ||||||
|  |             /* while loop IIFE or no argument */ | ||||||
|  |             if (argn) { | ||||||
|  |                 subopts.flags |= JANET_FOPTS_DROP; | ||||||
|  |                 janetc_value(subopts, argv[0]); | ||||||
|  |             } | ||||||
|  |             janetc_emit(c, JOP_RETURN_NIL); | ||||||
|  |             JanetSlot s = janetc_cslot(janet_wrap_nil()); | ||||||
|  |             s.flags |= JANET_SLOT_RETURNED; | ||||||
|  |             return s; | ||||||
|  |         } | ||||||
|     } else { |     } else { | ||||||
|  |         if (argn) { | ||||||
|  |             subopts.flags |= JANET_FOPTS_DROP; | ||||||
|  |             janetc_value(subopts, argv[0]); | ||||||
|  |         } | ||||||
|         /* Tag the instruction so the while special can turn it into a proper jump */ |         /* Tag the instruction so the while special can turn it into a proper jump */ | ||||||
|         janetc_emit(c, 0x80 | JOP_JUMP); |         janetc_emit(c, 0x80 | JOP_JUMP); | ||||||
|         return janetc_cslot(janet_wrap_nil()); |         return janetc_cslot(janet_wrap_nil()); | ||||||
|   | |||||||
| @@ -74,4 +74,10 @@ | |||||||
|  |  | ||||||
| (assert (= nil ((fn [] (break) 4))) "break 2") | (assert (= nil ((fn [] (break) 4))) "break 2") | ||||||
|  |  | ||||||
|  | # Break with value | ||||||
|  |  | ||||||
|  | # Shouldn't error out | ||||||
|  | (assert-no-error "break 3" (for i 0 10 (if (> i 8) (break i)))) | ||||||
|  | (assert-no-error "break 4" ((fn [i] (if (> i 8) (break i))) 100)) | ||||||
|  |  | ||||||
| (end-suite) | (end-suite) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose