commit 43ca2ad80219e69f81495e95a89fbe7a15e4699b
parent 85f2044d9a18a4d10054b27509c368cfd36fa0c2
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 21 Sep 2022 10:52:08 -0400
cc: fix broken "break" when followed by another loop
Diffstat:
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/fs/cc/gen.fs b/fs/cc/gen.fs
@@ -60,8 +60,9 @@ create breaks MAXBREAKCNT CELLSZ * allot
: addbreak
vmjmp[, breaklvl 1+ dup MAXBREAKCNT < _assert to@! breaklvl ( 'jump lvl )
CELLSZ * breaks + ! ;
-: resolvebreaks
- 0 to@! breaklvl ?dup if >r breaks begin @+ ]vmjmp next drop then ;
+: resolvebreaks ( tgtlvl -- )
+ begin ( tgt ) breaklvl over > while
+ -1 to+ breaklvl breaklvl CELLSZ * breaks + @ ]vmjmp repeat drop ;
: nobreaks# 0 to@! breaklvl not _assert ;
alias noop gennode ( node -- ) \ forward declaration
@@ -232,6 +233,7 @@ ASTIDCNT wordtbl gentbl ( node -- )
\ call
vmop :pop vmcall, ( type ) if vmpspop, then ;
:w ( For )
+ breaklvl >r
Node firstchild dup _assert dup gennode ops$ ( exprnode ) \ initialization
here swap ( loop_addr node )
Node nextsibling dup _assert dup gennode ( loop' exprnode ) \ control
@@ -239,21 +241,21 @@ ASTIDCNT wordtbl gentbl ( node -- )
Node nextsibling dup _assert dup ( adjustment node ) >r
Node nextsibling dup _assert gennode ( loop' cond' ) \ body
r> gennode ops$ \ adjustment node
- swap vmjmp, ( cond' ) ]vmjmp resolvebreaks ;
+ swap vmjmp, ( cond' ) ]vmjmp r> resolvebreaks ;
:w ( PSPush ) Node firstchild dup _assert gennode vmpspush, ;
:w ( PSPop ) drop vmpspop, ;
:w ( Break ) drop addbreak ;
:w ( While )
- here swap ( loop_addr node )
+ breaklvl >r here swap ( loop_addr node )
Node firstchild dup _assert dup gennode \ control
vmjz[, swap ( loop' cond' node ) ops$
Node nextsibling ( loop' cond' stmtnode ) dup _assert gennode \ body
- ( loop' cond' ) swap vmjmp, ]vmjmp resolvebreaks ;
+ ( loop' cond' ) swap vmjmp, ]vmjmp r> resolvebreaks ;
:w ( Do )
- here swap ( loop_addr node )
+ breaklvl >r here swap ( loop_addr node )
Node firstchild dup _assert dup gennode \ body
Node nextsibling ( loop' node ) dup _assert gennode \ control
- vmjnz, ops$ resolvebreaks ;
+ vmjnz, ops$ r> resolvebreaks ;
: _ ( node -- ) gentbl over Node id wexec ;
current to gennode
diff --git a/fs/tests/cc/cc.fs b/fs/tests/cc/cc.fs
@@ -41,6 +41,7 @@ capture helloworld S" Hello World!" #s=
55 capture multretvoid S" Nope" #s=
42 capture multretvoid S" Answer to the universe" #s=
1234 #eq
+forbreak 10 #eq
-1 0 lts #
-1 0 ltu not #
0 boolnot 1 #eq
diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c
@@ -158,11 +158,13 @@ extern void multretvoid(unsigned int x) {
stype("Nope");
}
extern int forbreak() {
- int i;
+ int i, j;
for (i=0; i<100; i++) {
if (i==10) {
break;
}
+ // the presence of a for() after the break doesn't break "break".
+ for (j=0; j<1; j++) {}
}
return i;
}