summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c135
1 files changed, 78 insertions, 57 deletions
diff --git a/eval.c b/eval.c
index 7033367..8a78dd0 100644
--- a/eval.c
+++ b/eval.c
@@ -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;