diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/compiler/builtins.zc | 8 | ||||
| -rw-r--r-- | src/compiler/expr.zc | 4 |
2 files changed, 10 insertions, 2 deletions
diff --git a/src/compiler/builtins.zc b/src/compiler/builtins.zc index 214d493..6dc586a 100644 --- a/src/compiler/builtins.zc +++ b/src/compiler/builtins.zc @@ -71,8 +71,10 @@ int ptagged(word t) { // enum name { A, B = 5 } is a plain enum: each member is a constant, plain (A) // and scoped (name.A). a member with a block of fields makes it a tagged enum // (see enum_tagged): enum name { circle { int r; }, dot }. +// the first member of the enum being read, so a member's value can name the members before it; -1 outside +int enum_open = 0 - 1; int kw_enum() { - char* n; char* en = 0; int first = npm, cnt = 0, tagged = 0, gi, nf, v = 0, et = 0, sk, ft; char* fname; + char* n; char* en = 0; int first = npm, cnt = 0, tagged = 0, gi, nf, v = 0, et = 0, sk, ft, rv = 0; char* fname; stmtonly(); next(); if (tk == T_ID) { en = tv; next(); } @@ -97,7 +99,9 @@ int kw_enum() { expect(s_semi); } expect(s_rb); - } else if (accept(s_eq)) { pm_val[gi] = cexpr(); pm_exp[gi] = 1; } + } else { enum_open = first; if (accept(s_eq)) { pm_val[gi] = cexpr(); pm_exp[gi] = 1; } enum_open = 0 - 1; } + if (pm_exp[gi]) rv = pm_val[gi]; else if (!pm_nf[gi]) pm_val[gi] = rv; // the running value, read by cprim + rv++; cnt++; if (!accept(s_comma)) break; if (is_op(s_rb)) break; diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc index 230a2d3..e449508 100644 --- a/src/compiler/expr.zc +++ b/src/compiler/expr.zc @@ -1959,6 +1959,10 @@ word cprim() { } } } + if (tk == T_ID && enum_open >= 0) { // an earlier member of the enum being read (spec 2.8.1) + mc = npm - 1; + while (mc > enum_open) { mc--; if (pm_name[mc] == tv && !pm_nf[mc]) { next(); return pm_val[mc]; } } + } die("expected a constant"); return 0; } |
