diff options
| author | 2026-10-15 21:44:40 +0330 | |
|---|---|---|
| committer | 2026-10-15 21:44:40 +0330 | |
| commit | f3dcfd9805e1bd23b002f648d4391ec397122d9c (patch) | |
| tree | 91acab7da09c9225a2d838791d70e5c2e7db54b9 /src/tools/zc0.c | |
| parent | merge work/small-oob: bytes test out-of-bounds read (diff) | |
| parent | examples/actors_demo: print the fan-out replies in worker order, not arrival ... (diff) | |
merge work/known-bugs: constant-expression precedence, local const in constant expressions, duplicate case labels, unterminated strings, droppable cycles in one collection, js vm exit, docs, actors_demo orderHEADmain
Diffstat (limited to 'src/tools/zc0.c')
| -rw-r--r-- | src/tools/zc0.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/src/tools/zc0.c b/src/tools/zc0.c index 6c62abf..229734c 100644 --- a/src/tools/zc0.c +++ b/src/tools/zc0.c @@ -396,16 +396,42 @@ static int64_t cprim(void) if (tk == T_ID && (s = find(ts)) && (s->kind == K_CONST || (s->kind != K_GVAR && s->defd))) { next(); return s->val; } die("constant expected"); return 0; } -static int64_t cexpr(void) +/* c precedence (spec 3.14.1): * / % above + -, above << >>, above &, ^, | */ +static int cprec(void) { - int64_t v = cprim(); - for (;;) { - if (accept("+")) v += cprim(); else if (accept("-")) v -= cprim(); - else if (accept("*")) v *= cprim(); else if (accept("|")) v |= cprim(); - else if (accept("&")) v &= cprim(); else if (accept("<<")) v <<= cprim(); - else if (accept(">>")) v >>= cprim(); else return v; + if (is("*") || is("/") || is("%")) return 10; + if (is("+") || is("-")) return 9; + if (is("<<") || is(">>")) return 8; + if (is("&")) return 5; + if (is("^")) return 4; + if (is("|")) return 3; + return 0; +} +static int64_t cbin(int minp) +{ + int64_t v = cprim(), w; int p; char o[3]; + while ((p = cprec()) && p >= minp) { + o[0] = ts[0]; o[1] = ts[1]; o[2] = 0; + next(); w = cbin(p + 1); + switch (o[0]) { + case '*': v *= w; break; + case '/': case '%': + if (w == 0) { die("division by zero in a constant expression"); return 0; } + if (w == -1) v = o[0] == '/' ? (int64_t)(0 - (uint64_t)v) : 0; + else v = o[0] == '/' ? v / w : v % w; + break; + case '+': v += w; break; + case '-': v -= w; break; + case '<': v = (int64_t)((uint64_t)v << (w & 63)); break; + case '>': v >>= (w & 63); break; + case '&': v &= w; break; + case '^': v ^= w; break; + default: v |= w; break; + } } + return v; } +static int64_t cexpr(void) { return cbin(1); } /* ---- types ---- zc0 has no types: a type is read and thrown away. all it has to know is the |
