aboutsummaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/eval.c b/eval.c
index 70febb1..908ce8d 100644
--- a/eval.c
+++ b/eval.c
@@ -27,6 +27,21 @@ cast(struct expr *expr)
}
static void
+unary(struct expr *expr, enum tokenkind op, struct expr *l)
+{
+ expr->kind = EXPRCONST;
+ if (l->type->prop & PROPFLOAT)
+ op |= F;
+ switch (op) {
+ case TSUB: expr->u.constant.u = -l->u.constant.u; break;
+ case TSUB|F: expr->u.constant.f = -l->u.constant.f; break;
+ default:
+ fatal("internal error; unknown unary expression");
+ }
+ cast(expr);
+}
+
+static void
binary(struct expr *expr, enum tokenkind op, struct expr *l, struct expr *r)
{
expr->kind = EXPRCONST;
@@ -111,19 +126,28 @@ eval(struct expr *expr, enum evalkind kind)
break;
case EXPRUNARY:
l = eval(expr->base, kind);
- if (expr->op != TBAND)
+ switch (expr->op) {
+ case TBAND:
+ switch (l->kind) {
+ case EXPRUNARY:
+ if (l->op == TMUL)
+ expr = eval(l->base, kind);
+ break;
+ case EXPRSTRING:
+ if (kind != EVALINIT)
+ break;
+ l->u.ident.decl = stringdecl(l);
+ l->kind = EXPRIDENT;
+ expr->base = l;
+ break;
+ }
break;
- switch (l->kind) {
- case EXPRUNARY:
- if (l->op == TMUL)
- expr = eval(l->base, kind);
+ case TMUL:
break;
- case EXPRSTRING:
- if (kind != EVALINIT)
+ default:
+ if (l->kind != EXPRCONST)
break;
- l->u.ident.decl = stringdecl(l);
- l->kind = EXPRIDENT;
- expr->base = l;
+ unary(expr, expr->op, l);
break;
}
break;