From a4ee519c30cf2790347872eb8f78292f40e300a4 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sat, 28 Sep 2019 15:42:46 -0400 Subject: some work on eval --- eval.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++------------- test.toc | 8 ++++--- types.c | 30 ++++++++++++++++++++------ 3 files changed, 89 insertions(+), 24 deletions(-) diff --git a/eval.c b/eval.c index 68b0d02..7fbb37c 100644 --- a/eval.c +++ b/eval.c @@ -1,27 +1,56 @@ +typedef enum { + VAL_VOID, + VAL_INT, + VAL_FLOAT, + VAL_PTR, + VAL_FN, + VAL_BOOL +} ValueKind; + +#define VAL_FLAG_FN_NULL 0x01 /* is this function null? */ + +typedef double FloatVal; + typedef struct Value { + ValueKind kind; union { Integer intv; - Floating floatv; + FloatVal floatv; struct Value *points_to; - FnExpr fn; + FnExpr *fn; bool boolv; }; } Value; -static bool eval_truthiness(Expression *e, Value *v) { - /* TODO */ - (void)e,(void)v; - return true; +static bool eval_truthiness(Value *v) { + switch (v->kind) { + case VAL_VOID: + assert(0); + return false; + case VAL_INT: + return v->intv != 0; + case VAL_FLOAT: + return v->floatv != 0; + case VAL_PTR: + return v->points_to != NULL; + case VAL_FN: + return v->fn != NULL; + case VAL_BOOL: + return v->boolv; + } + assert(0); + return false; } /* 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) */ +static bool eval_expr(Expression *e, Value *v) { switch (e->kind) { case EXPR_LITERAL_FLOAT: - v->floatv = e->floatl; - return false; + v->kind = VAL_FLOAT; + v->floatv = (FloatVal)e->floatl; + return true; case EXPR_LITERAL_INT: + v->kind = VAL_INT; if (e->intl > (UInteger)INTEGER_MAX) { /* TODO: FIXME */ err_print(e->where, "Overflow when evaluating integer."); return false; @@ -29,6 +58,7 @@ static bool eval_expr(Expression *e, Value *v) { v->intv = (Integer)e->intl; return true; case EXPR_LITERAL_BOOL: + v->kind = VAL_BOOL; v->boolv = e->booll; return true; case EXPR_UNARY_OP: { @@ -38,20 +68,23 @@ static bool eval_expr(Expression *e, Value *v) { 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->kind = of.kind; + if (v->kind == VAL_INT) { v->intv = -of.intv; - } else if (type_builtin_is_floating(e->type.builtin)) { + } else if (v->kind == VAL_FLOAT) { v->floatv = -of.floatv; } else { - err_print(e->where, "negation of non-numerical types not supported in evaluator yet."); + assert(0); return false; } return true; } case UNARY_NOT: - v->boolv = !eval_truthiness(e, v); + v->kind = VAL_BOOL; + v->boolv = !eval_truthiness(v); return true; case UNARY_ADDRESS: + v->kind = VAL_PTR; v->points_to = err_malloc(sizeof *v->points_to); /* OPTIM */ return eval_expr(e->unary.of, v->points_to); case UNARY_DEREF: { @@ -79,6 +112,7 @@ static bool eval_expr(Expression *e, Value *v) { bool is_bool = e->type.builtin == BUILTIN_BOOL; switch (e->binary.op) { case BINARY_PLUS: + v->kind = lhs.kind; if (is_int) { v->intv = lhs.intv + rhs.intv; } else if (is_float) { @@ -86,6 +120,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_MINUS: + v->kind = lhs.kind; if (is_int) { v->intv = lhs.intv - rhs.intv; } else if (is_float) { @@ -93,6 +128,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_MUL: + v->kind = lhs.kind; if (is_int) { v->intv = lhs.intv * rhs.intv; } else if (is_float) { @@ -100,6 +136,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_DIV: + v->kind = lhs.kind; /* TODO(eventually): check div by 0 */ if (is_int) { v->intv = lhs.intv / rhs.intv; @@ -108,6 +145,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_EQ: + v->kind = VAL_BOOL; if (is_int) { v->boolv = lhs.intv == rhs.intv; } else if (is_float) { @@ -117,6 +155,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_NE: + v->kind = VAL_BOOL; if (is_int) { v->boolv = lhs.intv != rhs.intv; } else if (is_float) { @@ -126,6 +165,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_GT: + v->kind = VAL_BOOL; if (is_int) { v->boolv = lhs.intv > rhs.intv; } else if (is_float) { @@ -133,6 +173,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_GE: + v->kind = VAL_BOOL; if (is_int) { v->boolv = lhs.intv >= rhs.intv; } else if (is_float) { @@ -140,6 +181,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_LT: + v->kind = VAL_BOOL; if (is_int) { v->boolv = lhs.intv < rhs.intv; } else if (is_float) { @@ -147,6 +189,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_LE: + v->kind = VAL_BOOL; if (is_int) { v->boolv = lhs.intv <= rhs.intv; } else if (is_float) { @@ -154,6 +197,7 @@ static bool eval_expr(Expression *e, Value *v) { } else assert(0); return true; case BINARY_SET: + v->kind = VAL_VOID; return true; case BINARY_COMMA: err_print(e->where, "tuples not supported at compile time yet."); @@ -192,7 +236,8 @@ static bool eval_expr(Expression *e, Value *v) { return true; } break; case EXPR_FN: - v->fn = e->fn; + v->kind = VAL_FN; + v->fn = &e->fn; return true; case EXPR_CAST: case EXPR_IF: diff --git a/test.toc b/test.toc index d3d1891..1812bb4 100644 --- a/test.toc +++ b/test.toc @@ -1,5 +1,7 @@ main @= fn() { - asdf := new &[3]&char; - del new int; - del asdf; + foo @= 5.3 + 6; + // x @= fn(i: f32) i64 { + // 0 + // }; + bar := foo+-foo; }; diff --git a/types.c b/types.c index dd724c3..dcfa7aa 100644 --- a/types.c +++ b/types.c @@ -628,7 +628,7 @@ static bool types_expr(Typer *tr, Expression *e) { } } break; case EXPR_DIRECT: - t->kind = TYPE_UNKNOWN; + /* type automatically set to unknown */ arr_foreach(&e->direct.args, Argument, arg) { if (arg->name) { err_print(arg->where, "Directives should not have named arguments."); @@ -653,6 +653,9 @@ static bool types_expr(Typer *tr, Expression *e) { Expression *of = e->unary.of; Type *of_type = &of->type; if (!types_expr(tr, e->unary.of)) return false; + if (of_type->kind == TYPE_UNKNOWN) { + return true; + } switch (e->unary.op) { case UNARY_MINUS: if (of_type->kind != TYPE_BUILTIN || !type_builtin_is_numerical(of_type->builtin)) { @@ -707,6 +710,9 @@ static bool types_expr(Typer *tr, Expression *e) { if (!types_expr(tr, e->binary.lhs) || !types_expr(tr, e->binary.rhs)) return false; + if (lhs_type->kind == TYPE_UNKNOWN || rhs_type->kind == TYPE_UNKNOWN) { + return true; + } switch (e->binary.op) { case BINARY_SET: if (!expr_must_lval(e->binary.lhs)) { @@ -755,15 +761,21 @@ static bool types_expr(Typer *tr, Expression *e) { int lhs_is_flexible = lhs_type->flags & TYPE_FLAG_FLEXIBLE; int rhs_is_flexible = rhs_type->flags & TYPE_FLAG_FLEXIBLE; if (lhs_is_flexible && rhs_is_flexible) { - *t = *lhs_type; + /* both flexible */ if (rhs_type->builtin == BUILTIN_F32) { /* promote to float */ - t->builtin = BUILTIN_F32; + lhs_type->builtin = BUILTIN_F32; } - } else if (!lhs_is_flexible) + if (lhs_type->builtin == BUILTIN_F32) + rhs_type->builtin = BUILTIN_F32; *t = *lhs_type; - else + } else if (!lhs_is_flexible) { + /* lhs inflexible, rhs ? */ + *t = *lhs_type; + } else { + /* lhs flexible, rhs ? */ *t = *rhs_type; + } } break; } } @@ -883,13 +895,19 @@ static bool types_decl(Typer *tr, Declaration *d) { } } } - d->flags |= DECL_FLAG_FOUND_TYPE; if (d->type.kind == TYPE_TUPLE) { /* TODO(eventually): Should this be allowed? */ err_print(d->where, "Declaring a tuple is not allowed."); return false; } ret: + /* pretend we found the type even if we didn't to prevent too many errors */ + d->flags |= DECL_FLAG_FOUND_TYPE; + if (!success) { + /* use unknown type if we didn't get the type */ + d->type.flags = 0; + d->type.kind = TYPE_UNKNOWN; + } arr_remove_last(&tr->in_decls); return success; } -- cgit v1.2.3