MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

preserve TCO behavior in semicolon-free style

+52 -4
+14 -4
src/ant.c
··· 5157 5157 static inline uint8_t lookahead(struct js *js) { 5158 5158 uint8_t old = js->tok, tok = 0; 5159 5159 uint8_t old_consumed = js->consumed; 5160 + 5160 5161 jsoff_t pos = js->pos; 5162 + jsoff_t toff = js->toff; 5163 + jsoff_t tlen = js->tlen; 5164 + 5165 + bool had_newline = js->had_newline; 5161 5166 int stream_pos = js->token_stream_pos; 5162 5167 5163 5168 js->consumed = 1; 5164 5169 tok = next(js); 5170 + 5165 5171 js->pos = pos; 5166 5172 js->tok = old; 5173 + js->toff = toff; 5174 + js->tlen = tlen; 5175 + 5176 + js->had_newline = had_newline; 5167 5177 js->consumed = old_consumed; 5168 5178 js->token_stream_pos = stream_pos; 5169 5179 ··· 10928 10938 uint8_t flags = js->flags; 10929 10939 js->consumed = 1; 10930 10940 if (js_truthy(js, resolveprop(js, res))) { 10931 - res = js_ternary(js); 10941 + res = js_assignment(js); 10932 10942 js->flags |= F_NOEXEC; 10933 10943 EXPECT(TOK_COLON, js->flags = flags); 10934 - js_ternary(js); 10944 + js_assignment(js); 10935 10945 js->flags = flags; 10936 10946 } else { 10937 10947 js->flags |= F_NOEXEC; 10938 - js_ternary(js); 10948 + js_assignment(js); 10939 10949 EXPECT(TOK_COLON, js->flags = flags); 10940 10950 js->flags = flags; 10941 - res = js_ternary(js); 10951 + res = js_assignment(js); 10942 10952 } 10943 10953 } 10944 10954 return res;
+38
tests/test_tco_asi.js
··· 1 + // Regression: verify TCO behavior is preserved with semicolon-free (ASI) style 2 + // and that newline-after-return keeps standard ASI semantics. 3 + 4 + function fail(msg) { 5 + console.log("FAIL:", msg) 6 + process.exit(1) 7 + } 8 + 9 + function assertEq(actual, expected, msg) { 10 + if (actual !== expected) fail(msg + " (got " + actual + ", expected " + expected + ")") 11 + } 12 + 13 + console.log("=== TCO + ASI Regression ===") 14 + 15 + // Semicolon-free style: this should still be optimized as a tail call. 16 + function countDownAsi(n) { 17 + if (n === 0) return 0 18 + return countDownAsi(n - 1) 19 + } 20 + 21 + assertEq(countDownAsi(100000), 0, "tail recursion with ASI should complete") 22 + 23 + // Tail recursion in ternary form with no trailing semicolons. 24 + function sumAsi(n, acc = 0) { 25 + return n === 0 ? acc : sumAsi(n - 1, acc + n) 26 + } 27 + 28 + assertEq(sumAsi(100000), 5000050000, "tail recursion in ternary should complete") 29 + 30 + // ASI rule check: newline after `return` ends the statement. 31 + function returnNewlineAsi() { 32 + return 33 + 42 34 + } 35 + 36 + if (returnNewlineAsi() !== undefined) fail("newline after return must produce undefined") 37 + 38 + console.log("PASS")