From 147153bf6aadd52d32f6beffc17f610c837ce17f Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Thu, 19 Feb 2026 00:33:17 +0200 Subject: Implement break and next for while/until loops TT_BREAK and TT_NEXT were already tokenised; this wires them up: - _program(): guard statement loop with ct == CONTROL_NONE so a break/next flag set inside a loop body stops block execution and propagates upward - _control(): add TT_BREAK and TT_NEXT cases that set CONTROL_BREAK / CONTROL_NEXT on p_interpret->ct and return immediately - while/until loop: replace the commented-out switch with active if/else logic that clears the flag and either stops iteration (break) or lets the loop re-evaluate its condition (next) Add examples/break_next.fy to exercise both keywords in while and until loops; expected output: 5 / 12 / 7. Co-Authored-By: Claude Sonnet 4.6 --- docs/help.txt | 2 +- docs/stats.txt | 6 +++--- docs/version.txt | 2 +- examples/all-examples.txt | 26 ++++++++++++++++++++++++++ examples/break_next.fy | 25 +++++++++++++++++++++++++ fype | Bin 471287 -> 265440 bytes src/build.h | 2 +- src/core/interpret.c | 36 ++++++++++++++++++++++++------------ 8 files changed, 81 insertions(+), 18 deletions(-) create mode 100644 examples/break_next.fy diff --git a/docs/help.txt b/docs/help.txt index 3921ea2..4ccd7a7 100644 --- a/docs/help.txt +++ b/docs/help.txt @@ -1,4 +1,4 @@ -Fype Superalpha Build 9669 +Fype Superalpha Build 9671 (c) Paul C. Buetow (2005 - 2008) -e Executes given code string (see synopses) -h Prints this help diff --git a/docs/stats.txt b/docs/stats.txt index 81214dc..583ddf1 100644 --- a/docs/stats.txt +++ b/docs/stats.txt @@ -1,6 +1,6 @@ make[1]: Entering directory '/home/paul/git/fype' ===> Num of C source files : 46 -===> Num of C source lines : 8225 -===> Num of Fype source examples : 14 -===> Num of Fype source lines : 362 +===> Num of C source lines : 8237 +===> Num of Fype source examples : 15 +===> Num of Fype source lines : 387 make[1]: Leaving directory '/home/paul/git/fype' diff --git a/docs/version.txt b/docs/version.txt index 1a4849f..ea87c13 100644 --- a/docs/version.txt +++ b/docs/version.txt @@ -1 +1 @@ -Fype Superalpha Build 9669 +Fype Superalpha Build 9671 diff --git a/examples/all-examples.txt b/examples/all-examples.txt index f71e8a2..5e0f13e 100644 --- a/examples/all-examples.txt +++ b/examples/all-examples.txt @@ -32,6 +32,32 @@ assert 1 == (say 1 :< 5 :> 5 or 2 and (5 xor 8)); assert (neg 1) == (say neg not 0); +# break exits the while loop early when i reaches 5 +my i = 0; +while i < 10 { + i = i + 1; + if i == 5 { break; } +} +say i; # expected: 5 + +# next skips adding j when j == 3, so sum = 1+2+4+5 = 12 +my sum = 0; +my j = 0; +while j < 5 { + j = j + 1; + if j == 3 { next; } + sum = sum + j; +} +say sum; # expected: 12 + +# break inside an until loop stops when k reaches 7 +my k = 0; +until k == 10 { + k = k + 1; + if k == 7 { break; } +} +say k; # expected: 7 + #* * Simple examples how to write comments *# diff --git a/examples/break_next.fy b/examples/break_next.fy new file mode 100644 index 0000000..bd060f8 --- /dev/null +++ b/examples/break_next.fy @@ -0,0 +1,25 @@ +# break exits the while loop early when i reaches 5 +my i = 0; +while i < 10 { + i = i + 1; + if i == 5 { break; } +} +say i; # expected: 5 + +# next skips adding j when j == 3, so sum = 1+2+4+5 = 12 +my sum = 0; +my j = 0; +while j < 5 { + j = j + 1; + if j == 3 { next; } + sum = sum + j; +} +say sum; # expected: 12 + +# break inside an until loop stops when k reaches 7 +my k = 0; +until k == 10 { + k = k + 1; + if k == 7 { break; } +} +say k; # expected: 7 diff --git a/fype b/fype index 356c7b0..3f150ce 100755 Binary files a/fype and b/fype differ diff --git a/src/build.h b/src/build.h index 794ac65..c3808f5 100644 --- a/src/build.h +++ b/src/build.h @@ -36,7 +36,7 @@ #ifndef BUILD_H #define BUILD_H -#define BUILDNR 9670 +#define BUILDNR 9672 #define OS_LINUX #endif diff --git a/src/core/interpret.c b/src/core/interpret.c index 5b5e80b..0667148 100644 --- a/src/core/interpret.c +++ b/src/core/interpret.c @@ -168,7 +168,9 @@ int _program(Interpret *p_interpret) { _CHECK TRACK - while (_statement(p_interpret) == 1) + /* Stop executing statements as soon as break/next is active so the + * control flag propagates cleanly up to the enclosing loop. */ + while (_statement(p_interpret) == 1 && p_interpret->ct == CONTROL_NONE) garbage_collect(); return (1); @@ -496,6 +498,18 @@ _control(Interpret *p_interpret) { Token *p_token = p_interpret->p_token; switch (p_interpret->tt) { + /* break; — set the break flag; the statement loop in _program() will + * stop and the flag propagates up to the enclosing while/until. */ + case TT_BREAK: + p_interpret->ct = CONTROL_BREAK; + _NEXT + return (1); + /* next; — set the next flag to skip the rest of the loop body and + * let the loop re-evaluate its condition on the next iteration. */ + case TT_NEXT: + p_interpret->ct = CONTROL_NEXT; + _NEXT + return (1); case TT_IF: case TT_IFNOT: { @@ -584,18 +598,16 @@ _control(Interpret *p_interpret) { } } - /* - switch (p_interpret->ct) { - case CONTROL_BREAK: - p_interpret->ct = CONTROL_NONE; - b_flag = false; - break; - case CONTROL_NEXT: - p_interpret->ct = CONTROL_NONE; - break; - NO_DEFAULT; + /* Act on any break/next flag set during loop body execution. + * break clears the flag and stops iteration; next clears it + * and lets the loop re-evaluate the condition naturally. */ + if (p_interpret->ct == CONTROL_BREAK) { + p_interpret->ct = CONTROL_NONE; + b_flag = false; + } else if (p_interpret->ct == CONTROL_NEXT) { + p_interpret->ct = CONTROL_NONE; + /* b_flag stays true; condition re-evaluated next iteration */ } - */ } else { _INTERPRET_ERROR("Expected expression after control keyword", -- cgit v1.2.3