summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c75
-rw-r--r--test.toc8
-rw-r--r--types.c30
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;
}