diff options
Diffstat (limited to 'bootstrap/fold.c')
| -rw-r--r-- | bootstrap/fold.c | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/bootstrap/fold.c b/bootstrap/fold.c index dfd6509..f7962d4 100644 --- a/bootstrap/fold.c +++ b/bootstrap/fold.c @@ -12,8 +12,8 @@ numcast(struct expr *ex, const struct type *to) { const struct type *ufrom = unconstify(from); int size = to->size; bool sgn = to->int_signed; - assert(t0 == TYint || t0 == TYfloat || t0 == TYbool); - assert(t1 == TYint || t1 == TYfloat || t1 == TYbool); + assert(t0 == TYint || t0 == TYfloat || t0 == TYbool || t0 == TYenum); + assert(t1 == TYint || t1 == TYfloat || t1 == TYbool || t1 == TYenum); if (ufrom == uto) /* pass */; @@ -201,13 +201,50 @@ findex(struct expr *ex) { free(r); } +static void +trysetenumvname(struct expr *ex) { + const struct type *t = ex->ty; + for (int i = 0; i < t->enu.vals.n; ++i) + if (ex->enu.i == t->enu.vals.d[i].i) { + ex->enu.vname = t->enu.vals.d[i].name; + break; + } +} + +static void +fas(struct expr *ex) { + struct expr *child = ex->child; + const struct type *to = ex->ty, + *from = child->ty; + + if (!fold(child)) + return; + if (!isnumtype(to) && to->t != TYenum) + return; + ex->i = child->i; + if (from->t == TYenum) { + child->ty = child->ty->enu.intty; + } + ex->ty = child->ty; + ex->i = child->i; + if (to->t == TYenum) { + numcast(ex, to->enu.intty); + ex->ty = to; + ex->t = Eenumval; + trysetenumvname(ex); + } else { + numcast(ex, to); + } + free(child); +} + int fold(struct expr *ex) { switch (ex->t) { case Eintlit: case Eflolit: case Eboolit: numcast(ex, ex->ty); return 1; - case Estrlit:case Enullit: + case Estrlit:case Enullit: case Eenumval: return 1; case Eprefix: funary(ex); @@ -221,13 +258,16 @@ fold(struct expr *ex) { case Eindex: findex(ex); break; + case Eas: + fas(ex); + break; default: break; } switch (ex->t) { case Eintlit: case Eflolit: case Estrlit: - case Eboolit: case Enullit: + case Eboolit: case Enullit: case Eenumval: return 1; default: return 0; |