diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 135 |
1 files changed, 78 insertions, 57 deletions
@@ -1,74 +1,98 @@ -/* static bool eval_expr_as_float(Expression *e, FloatLiteral *f) { */ -/* switch (e->kind) { */ -/* case EXPR_FLOAT_LITERAL: */ -/* *f = e->floatl; */ -/* return true; */ -/* case EXPR_INT_LITERAL: */ -/* *f = (FloatLiteral)e->intl; */ -/* return true; */ -/* } */ -/* err_print(e->where, "Not implemented yet"); */ -/* return false; */ -/* } */ +typedef struct Value { + union { + Integer intv; + Floating floatv; + struct Value *points_to; + FnExpr fn; + }; +} Value; -static bool eval_expr_as_int(Expression *e, Integer *i) { - /* OPTIM: cache eval'd expression values? (probably only for declarations) */ +/* NOTE: expr must be typed before it can be evaluated */ +static bool eval_expr(Expression *e, Value *v) { + /* TODO: cache eval'd expression values (probably only needed for declarations) */ switch (e->kind) { case EXPR_LITERAL_FLOAT: - err_print(e->where, "Expected integer, but found floating-point literal."); + v->floatv = e->floatl; return false; case EXPR_LITERAL_INT: if (e->intl > (UInteger)INTEGER_MAX) { /* TODO: FIXME */ err_print(e->where, "Overflow when evaluating integer."); return false; } - *i = (Integer)e->intl; + v->intv = (Integer)e->intl; return true; case EXPR_LITERAL_STR: - err_print(e->where, "Expected integer, but found string literal."); + err_print(e->where, "not implemented yet"); /* TODO */ return false; - case EXPR_UNARY_OP: + case EXPR_UNARY_OP: { + Expression *of_expr = e->unary.of; switch (e->unary.op) { case UNARY_MINUS: { - Integer of; - if (!eval_expr_as_int(e->unary.of, &of)) return false; - *i = -of; + Value of; + if (!eval_expr(of_expr, &of)) return false; + assert(e->type.kind != TYPE_BUILTIN); + if (type_builtin_is_integer(e->type.builtin)) { + v->intv = -of.intv; + } else if (type_builtin_is_floating(e->type.builtin)) { + v->floatv = -of.floatv; + } else { + err_print(e->where, "negation of non-numerical types not supported in evaluator yet."); + return false; + } return true; } case UNARY_ADDRESS: - err_print(e->where, "Use of pointer as integer constant."); - return false; + v->points_to = malloc(sizeof *v->points_to); /* OPTIM */ + return eval_expr(e->unary.of, v->points_to); + case UNARY_DEREF: { + Value ptr; + if (!eval_expr(of_expr, &ptr)) return false; + *v = *ptr.points_to; + return true; + } break; } - break; + } break; case EXPR_BINARY_OP: { - + Value lhs, rhs; + /* NOTE: this will need to change for short-circuiting */ + if (!eval_expr(e->binary.lhs, &lhs)) return false; + if (!eval_expr(e->binary.rhs, &rhs)) return false; + bool is_int = type_builtin_is_integer(e->type.builtin); + bool is_float = type_builtin_is_floating(e->type.builtin); switch (e->binary.op) { case BINARY_PLUS: + if (is_int) { + v->intv = lhs.intv + rhs.intv; + } else if (is_float) { + v->floatv = lhs.floatv + rhs.floatv; + } else assert(0); + return true; case BINARY_MINUS: + if (is_int) { + v->intv = lhs.intv - rhs.intv; + } else if (is_float) { + v->floatv = lhs.floatv - rhs.floatv; + } else assert(0); + return true; case BINARY_MUL: - case BINARY_DIV: { - Integer lhs, rhs; - if (!eval_expr_as_int(e->binary.lhs, &lhs)) return false; - if (!eval_expr_as_int(e->binary.rhs, &rhs)) return false; - switch (e->binary.op) { - case BINARY_PLUS: - *i = lhs + rhs; - return true; - case BINARY_MINUS: - *i = lhs - rhs; - return true; - case BINARY_MUL: - *i = lhs * rhs; - return true; - case BINARY_DIV: - *i = lhs / rhs; - return true; - default: assert(0); return false; - } - } + if (is_int) { + v->intv = lhs.intv * rhs.intv; + } else if (is_float) { + v->floatv = lhs.floatv * rhs.floatv; + } else assert(0); + return true; + case BINARY_DIV: + /* TODO(eventually): check div by 0 */ + if (is_int) { + v->intv = lhs.intv / rhs.intv; + } else if (is_float) { + v->floatv = lhs.floatv / rhs.floatv; + } else assert(0); + return true; case BINARY_SET: + return true; case BINARY_COMMA: - err_print(e->where, "Expected operator which returns an integer, but got %s", binary_op_to_str(e->binary.op)); + err_print(e->where, "tuples not supported at compile time yet."); return false; case BINARY_AT_INDEX: err_print(e->where, "Cannot get index of array at compile time yet."); @@ -95,21 +119,18 @@ static bool eval_expr_as_int(Expression *e, Integer *i) { info_print(d->where, "Declaration was here."); return false; } - if (d->type.kind != TYPE_BUILTIN || !type_builtin_is_integer(d->type.builtin)) { - char *type_str = type_to_str(&d->type); - err_print(e->where, "Expected integer, but identifier has type %s.", type_str); - info_print(d->where, "Declaration was here."); - free(type_str); - return false; - } /* TODO: tuples */ - eval_expr_as_int(&d->expr, i); - + if (!d->val) { + d->val = err_malloc(sizeof *d->val); /* OPTIM */ + if (!eval_expr(&d->expr, d->val)) + return false; + } + *v = *d->val; return true; } break; case EXPR_FN: - err_print(e->where, "Expected integer, but found function."); - return false; + v->fn = *e->fn; + return true; case EXPR_CALL: err_print(e->where, "Compile time function calling not supported yet."); /* TODO */ break; |