···128128static jsval_t js_stmt(struct js *js);
129129static jsval_t js_assignment(struct js *js);
130130static jsval_t js_arrow_func(struct js *js, jsoff_t params_start, jsoff_t params_end, bool is_async);
131131+static jsval_t js_while(struct js *js);
132132+static jsval_t js_do_while(struct js *js);
133133+static jsval_t js_block_or_stmt(struct js *js);
131134static jsval_t do_op(struct js *, uint8_t op, jsval_t l, jsval_t r);
132135static jsval_t do_instanceof(struct js *js, jsval_t l, jsval_t r);
133136static jsval_t resolveprop(struct js *js, jsval_t v);
···753756 uint8_t t = js->tok;
754757 res = js_stmt(js);
755758 if (!is_err(res) && t != TOK_LBRACE && t != TOK_IF && t != TOK_WHILE &&
756756- t != TOK_FUNC && js->tok != TOK_SEMICOLON) {
759759+ t != TOK_DO && t != TOK_FUNC && t != TOK_FOR && js->tok != TOK_SEMICOLON) {
757760 res = js_mkerr(js, "; expected");
758761 break;
759762 }
···28632866 return res;
28642867}
2865286828692869+static jsval_t js_while(struct js *js) {
28702870+ uint8_t flags = js->flags, exe = !(flags & F_NOEXEC);
28712871+ jsval_t res = js_mkundef(), v;
28722872+28732873+ js->consumed = 1;
28742874+ if (!expect(js, TOK_LPAREN, &res)) return res;
28752875+28762876+ jsoff_t cond_start = js->pos;
28772877+ js->flags |= F_NOEXEC;
28782878+ v = js_expr(js);
28792879+ if (is_err(v)) return v;
28802880+28812881+ if (!expect(js, TOK_RPAREN, &res)) return res;
28822882+28832883+ jsoff_t body_start = js->pos;
28842884+ v = js_block_or_stmt(js);
28852885+ if (is_err(v)) return v;
28862886+ jsoff_t body_end = js->pos;
28872887+28882888+ if (exe) {
28892889+ while (true) {
28902890+ js->flags = flags;
28912891+ js->pos = cond_start;
28922892+ js->consumed = 1;
28932893+28942894+ v = resolveprop(js, js_expr(js));
28952895+ if (is_err(v)) {
28962896+ res = v;
28972897+ break;
28982898+ }
28992899+29002900+ if (!js_truthy(js, v)) break;
29012901+29022902+ js->pos = body_start;
29032903+ js->consumed = 1;
29042904+ js->flags = (flags & ~F_NOEXEC) | F_LOOP;
29052905+29062906+ v = js_block_or_stmt(js);
29072907+ if (is_err(v)) {
29082908+ res = v;
29092909+ break;
29102910+ }
29112911+29122912+ if (js->flags & F_BREAK) {
29132913+ break;
29142914+ }
29152915+29162916+ if (js->flags & F_RETURN) {
29172917+ res = v;
29182918+ break;
29192919+ }
29202920+ }
29212921+ }
29222922+29232923+ js->pos = body_end;
29242924+ js->tok = TOK_SEMICOLON;
29252925+ js->consumed = 0;
29262926+29272927+ uint8_t preserve = 0;
29282928+ if (js->flags & F_RETURN) {
29292929+ preserve = js->flags & (F_RETURN | F_NOEXEC);
29302930+ }
29312931+ js->flags = flags | preserve;
29322932+29332933+ return res;
29342934+}
29352935+29362936+static jsval_t js_do_while(struct js *js) {
29372937+ uint8_t flags = js->flags, exe = !(flags & F_NOEXEC);
29382938+ jsval_t res = js_mkundef(), v;
29392939+29402940+ js->consumed = 1;
29412941+29422942+ jsoff_t body_start = js->pos;
29432943+ bool is_block = (next(js) == TOK_LBRACE);
29442944+ js->flags |= F_NOEXEC;
29452945+ v = js_block_or_stmt(js);
29462946+ if (is_err(v)) return v;
29472947+29482948+ if (is_block && next(js) == TOK_RBRACE) {
29492949+ js->consumed = 1;
29502950+ }
29512951+ (void) js->pos;
29522952+29532953+ if (!expect(js, TOK_WHILE, &res)) return res;
29542954+ if (!expect(js, TOK_LPAREN, &res)) return res;
29552955+29562956+ jsoff_t cond_start = js->pos;
29572957+ v = js_expr(js);
29582958+ if (is_err(v)) return v;
29592959+29602960+ if (!expect(js, TOK_RPAREN, &res)) return res;
29612961+ jsoff_t cond_end = js->pos;
29622962+29632963+ if (exe) {
29642964+ do {
29652965+ js->pos = body_start;
29662966+ js->consumed = 1;
29672967+ js->flags = (flags & ~F_NOEXEC) | F_LOOP;
29682968+29692969+ v = js_block_or_stmt(js);
29702970+ if (is_err(v)) {
29712971+ res = v;
29722972+ break;
29732973+ }
29742974+29752975+ if (js->flags & F_BREAK) {
29762976+ break;
29772977+ }
29782978+29792979+ if (js->flags & F_RETURN) {
29802980+ res = v;
29812981+ break;
29822982+ }
29832983+29842984+ js->flags = flags;
29852985+ js->pos = cond_start;
29862986+ js->consumed = 1;
29872987+29882988+ v = resolveprop(js, js_expr(js));
29892989+ if (is_err(v)) {
29902990+ res = v;
29912991+ break;
29922992+ }
29932993+ } while (js_truthy(js, v));
29942994+ }
29952995+29962996+ js->pos = cond_end;
29972997+ js->consumed = 1;
29982998+29992999+ uint8_t preserve = 0;
30003000+ if (js->flags & F_RETURN) {
30013001+ preserve = js->flags & (F_RETURN | F_NOEXEC);
30023002+ }
30033003+ js->flags = flags | preserve;
30043004+30053005+ return res;
30063006+}
30073007+28663008static jsval_t js_break(struct js *js) {
28673009 if (js->flags & F_NOEXEC) {
28683010 } else {
···3071321330723214 switch (next(js)) {
30733215 case TOK_CASE: case TOK_CATCH:
30743074- case TOK_DEFAULT: case TOK_DO: case TOK_FINALLY:
32163216+ case TOK_DEFAULT: case TOK_FINALLY:
30753217 case TOK_IN: case TOK_SWITCH:
30763218 case TOK_THROW: case TOK_TRY: case TOK_VAR:
30773077- case TOK_WITH: case TOK_WHILE: case TOK_YIELD:
32193219+ case TOK_WITH: case TOK_YIELD:
30783220 res = js_mkerr(js, "'%.*s' not implemented", (int) js->tlen, js->code + js->toff);
30793221 break;
32223222+ case TOK_WHILE: res = js_while(js); break;
32233223+ case TOK_DO: res = js_do_while(js); break;
30803224 case TOK_CONTINUE: res = js_continue(js); break;
30813225 case TOK_BREAK: res = js_break(js); break;
30823226 case TOK_LET: res = js_let(js); break;
+140
tests/test_async_loops.cjs
···11+// Test async/await with loops
22+Ant.println('=== Async/Await with Loops Tests ===');
33+44+// Test 1: Await in for loop
55+Ant.println('\nTest 1: Await in for loop');
66+async function test1() {
77+ let sum = 0;
88+ for (let i = 0; i < 3; i = i + 1) {
99+ const val = await Promise.resolve(i);
1010+ sum = sum + val;
1111+ }
1212+ return sum;
1313+}
1414+test1().then(v => Ant.println('Test 1: ' + v));
1515+1616+// Test 2: Await in while loop
1717+Ant.println('\nTest 2: Await in while loop');
1818+async function test2() {
1919+ let i = 0;
2020+ let sum = 0;
2121+ while (i < 3) {
2222+ const val = await Promise.resolve(i);
2323+ sum = sum + val;
2424+ i = i + 1;
2525+ }
2626+ return sum;
2727+}
2828+test2().then(v => Ant.println('Test 2: ' + v));
2929+3030+// Test 3: Await in do-while loop
3131+Ant.println('\nTest 3: Await in do-while loop');
3232+async function test3() {
3333+ let i = 0;
3434+ let sum = 0;
3535+ do {
3636+ const val = await Promise.resolve(i);
3737+ sum = sum + val;
3838+ i = i + 1;
3939+ } while (i < 3);
4040+ return sum;
4141+}
4242+test3().then(v => Ant.println('Test 3: ' + v));
4343+4444+// Test 4: Multiple awaits in loop
4545+Ant.println('\nTest 4: Multiple awaits in loop');
4646+async function test4() {
4747+ let result = 0;
4848+ for (let i = 0; i < 2; i = i + 1) {
4949+ const a = await Promise.resolve(i);
5050+ const b = await Promise.resolve(i + 10);
5151+ result = result + a + b;
5252+ }
5353+ return result;
5454+}
5555+test4().then(v => Ant.println('Test 4: ' + v));
5656+5757+// Test 5: Await with break
5858+Ant.println('\nTest 5: Await with break');
5959+async function test5() {
6060+ let i = 0;
6161+ while (i < 10) {
6262+ const val = await Promise.resolve(i);
6363+ if (val === 3) {
6464+ break;
6565+ }
6666+ i = i + 1;
6767+ }
6868+ return i;
6969+}
7070+test5().then(v => Ant.println('Test 5: ' + v));
7171+7272+// Test 6: Await with continue
7373+Ant.println('\nTest 6: Await with continue');
7474+async function test6() {
7575+ let sum = 0;
7676+ for (let i = 0; i < 5; i = i + 1) {
7777+ const val = await Promise.resolve(i);
7878+ if (val % 2 === 0) {
7979+ continue;
8080+ }
8181+ sum = sum + val;
8282+ }
8383+ return sum;
8484+}
8585+test6().then(v => Ant.println('Test 6: ' + v));
8686+8787+// Test 7: Nested loops with await
8888+Ant.println('\nTest 7: Nested loops with await');
8989+async function test7() {
9090+ let count = 0;
9191+ for (let i = 0; i < 2; i = i + 1) {
9292+ for (let j = 0; j < 2; j = j + 1) {
9393+ const val = await Promise.resolve(1);
9494+ count = count + val;
9595+ }
9696+ }
9797+ return count;
9898+}
9999+test7().then(v => Ant.println('Test 7: ' + v));
100100+101101+// Test 8: While loop with async condition check
102102+Ant.println('\nTest 8: While loop awaiting values');
103103+async function test8() {
104104+ let i = 0;
105105+ let product = 1;
106106+ while (i < 3) {
107107+ const multiplier = await Promise.resolve(2);
108108+ product = product * multiplier;
109109+ i = i + 1;
110110+ }
111111+ return product;
112112+}
113113+test8().then(v => Ant.println('Test 8: ' + v));
114114+115115+// Test 9: Do-while with await and condition
116116+Ant.println('\nTest 9: Do-while with await');
117117+async function test9() {
118118+ let count = 0;
119119+ let val;
120120+ do {
121121+ val = await Promise.resolve(count);
122122+ count = count + 1;
123123+ } while (val < 2);
124124+ return count;
125125+}
126126+test9().then(v => Ant.println('Test 9: ' + v));
127127+128128+// Test 10: For loop building array with await
129129+Ant.println('\nTest 10: Building array with await in loop');
130130+async function test10() {
131131+ const arr = [];
132132+ for (let i = 0; i < 3; i = i + 1) {
133133+ const val = await Promise.resolve(i * 2);
134134+ arr[i] = val;
135135+ }
136136+ return arr[0] + arr[1] + arr[2];
137137+}
138138+test10().then(v => Ant.println('Test 10: ' + v));
139139+140140+Ant.println('\n=== All async loop tests initiated ===');
+197
tests/test_loops.cjs
···11+// Test all loop types: for, while, do-while
22+Ant.println('=== Loop Tests ===');
33+44+// Test 1: Basic while loop
55+Ant.println('\nTest 1: Basic while loop');
66+let i = 0;
77+let sum = 0;
88+while (i < 5) {
99+ sum = sum + i;
1010+ i = i + 1;
1111+}
1212+Ant.println('While loop sum (0-4): ' + sum);
1313+1414+// Test 2: While loop with break
1515+Ant.println('\nTest 2: While loop with break');
1616+let count = 0;
1717+while (count < 10) {
1818+ if (count === 5) {
1919+ break;
2020+ }
2121+ count = count + 1;
2222+}
2323+Ant.println('While with break, count: ' + count);
2424+2525+// Test 3: While loop with continue
2626+Ant.println('\nTest 3: While loop with continue');
2727+let j = 0;
2828+let evenSum = 0;
2929+while (j < 10) {
3030+ j = j + 1;
3131+ if (j % 2 === 1) {
3232+ continue;
3333+ }
3434+ evenSum = evenSum + j;
3535+}
3636+Ant.println('Even sum (2,4,6,8,10): ' + evenSum);
3737+3838+// Test 4: Basic do-while loop
3939+Ant.println('\nTest 4: Basic do-while loop');
4040+let k = 0;
4141+let result = 0;
4242+do {
4343+ result = result + k;
4444+ k = k + 1;
4545+} while (k < 5);
4646+Ant.println('Do-while sum (0-4): ' + result);
4747+4848+// Test 5: Do-while executes at least once
4949+Ant.println('\nTest 5: Do-while executes at least once');
5050+let executed = false;
5151+do {
5252+ executed = true;
5353+ Ant.println('Do-while executed even when condition is false');
5454+} while (false);
5555+5656+// Test 6: Do-while with break
5757+Ant.println('\nTest 6: Do-while with break');
5858+let n = 0;
5959+do {
6060+ n = n + 1;
6161+ if (n === 3) {
6262+ break;
6363+ }
6464+} while (n < 10);
6565+Ant.println('Do-while with break, n: ' + n);
6666+6767+// Test 7: Do-while with continue
6868+Ant.println('\nTest 7: Do-while with continue');
6969+let m = 0;
7070+let oddSum = 0;
7171+do {
7272+ m = m + 1;
7373+ if (m % 2 === 0) {
7474+ continue;
7575+ }
7676+ oddSum = oddSum + m;
7777+} while (m < 9);
7878+Ant.println('Odd sum (1,3,5,7,9): ' + oddSum);
7979+8080+// Test 8: For loop basic
8181+Ant.println('\nTest 8: For loop basic');
8282+let forSum = 0;
8383+for (let x = 0; x < 5; x = x + 1) {
8484+ forSum = forSum + x;
8585+}
8686+Ant.println('For loop sum (0-4): ' + forSum);
8787+8888+// Test 9: For loop with break
8989+Ant.println('\nTest 9: For loop with break');
9090+let breakCount = 0;
9191+for (let y = 0; y < 10; y = y + 1) {
9292+ if (y === 5) {
9393+ break;
9494+ }
9595+ breakCount = breakCount + 1;
9696+}
9797+Ant.println('For loop with break, count: ' + breakCount);
9898+9999+// Test 10: For loop with continue
100100+Ant.println('\nTest 10: For loop with continue');
101101+let skipSum = 0;
102102+for (let z = 0; z < 10; z = z + 1) {
103103+ if (z % 2 === 0) {
104104+ continue;
105105+ }
106106+ skipSum = skipSum + z;
107107+}
108108+Ant.println('For loop skip evens (1+3+5+7+9): ' + skipSum);
109109+110110+// Test 11: Nested while loops
111111+Ant.println('\nTest 11: Nested while loops');
112112+let outer = 0;
113113+let nestedSum = 0;
114114+while (outer < 3) {
115115+ let inner = 0;
116116+ while (inner < 3) {
117117+ nestedSum = nestedSum + 1;
118118+ inner = inner + 1;
119119+ }
120120+ outer = outer + 1;
121121+}
122122+Ant.println('Nested while loops, count: ' + nestedSum);
123123+124124+// Test 12: Nested for loops
125125+Ant.println('\nTest 12: Nested for loops');
126126+let product = 0;
127127+for (let a = 1; a <= 3; a = a + 1) {
128128+ for (let b = 1; b <= 3; b = b + 1) {
129129+ product = a * b;
130130+ }
131131+}
132132+Ant.println('Last nested for product: ' + product);
133133+134134+// Test 13: While with complex condition
135135+Ant.println('\nTest 13: While with complex condition');
136136+let p = 0;
137137+let q = 10;
138138+while (p < 5 && q > 5) {
139139+ p = p + 1;
140140+ q = q - 1;
141141+}
142142+Ant.println('Complex while, p: ' + p + ', q: ' + q);
143143+144144+// Test 14: For loop with let declaration
145145+Ant.println('\nTest 14: For loop with let');
146146+for (let temp = 0; temp < 3; temp = temp + 1) {
147147+ Ant.println('For loop iteration: ' + temp);
148148+}
149149+150150+// Test 15: While loop with single statement
151151+Ant.println('\nTest 15: While with single statement');
152152+let single = 0;
153153+while (single < 3) single = single + 1;
154154+Ant.println('Single statement while: ' + single);
155155+156156+// Test 16: Do-while with single statement (in block)
157157+Ant.println('\nTest 16: Do-while with single statement');
158158+let singleDo = 0;
159159+do { singleDo = singleDo + 1; } while (singleDo < 3);
160160+Ant.println('Single statement do-while: ' + singleDo);
161161+162162+// Test 17: Empty while loop
163163+Ant.println('\nTest 17: Empty while loop');
164164+let empty = 5;
165165+while (empty < 5) {
166166+ Ant.println('Should not print');
167167+}
168168+Ant.println('Empty while executed: no output above');
169169+170170+// Test 18: For loop with const
171171+Ant.println('\nTest 18: For loop counting down');
172172+let countdown = 0;
173173+for (let val = 5; val > 0; val = val - 1) {
174174+ countdown = countdown + val;
175175+}
176176+Ant.println('Countdown sum (5+4+3+2+1): ' + countdown);
177177+178178+// Test 19: While loop with array
179179+Ant.println('\nTest 19: While loop with array');
180180+const arr = [10, 20, 30];
181181+let idx = 0;
182182+let arrSum = 0;
183183+while (idx < arr.length) {
184184+ arrSum = arrSum + arr[idx];
185185+ idx = idx + 1;
186186+}
187187+Ant.println('Array sum via while: ' + arrSum);
188188+189189+// Test 20: Do-while minimal
190190+Ant.println('\nTest 20: Do-while minimal');
191191+let minimal = 0;
192192+do {
193193+ minimal = minimal + 1;
194194+} while (minimal < 1);
195195+Ant.println('Minimal do-while: ' + minimal);
196196+197197+Ant.println('\n=== All loop tests completed ===');