summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c58
-rw-r--r--main.c1
-rw-r--r--parse.c1
-rw-r--r--test.toc6
-rw-r--r--types.c10
5 files changed, 44 insertions, 32 deletions
diff --git a/eval.c b/eval.c
index 7951f70..517d180 100644
--- a/eval.c
+++ b/eval.c
@@ -1,4 +1,4 @@
-static void eval_block(Evaluator *ev, Block *b, Value *v);
+static bool eval_block(Evaluator *ev, Block *b, Value *v);
static void evalr_create(Evaluator *ev) {
allocr_create(&ev->allocr);
@@ -276,7 +276,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
}
-static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
+static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
/* WARNING: macros ahead */
#define eval_unary_op_one(low, up, op) \
case BUILTIN_##up: \
@@ -349,7 +349,7 @@ static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
switch (e->kind) {
case EXPR_UNARY_OP: {
Value of;
- eval_expr(ev, e->unary.of, &of);
+ if (!eval_expr(ev, e->unary.of, &of)) return false;
switch (e->unary.op) {
case UNARY_MINUS: {
BuiltinType builtin = e->type.builtin;
@@ -364,8 +364,8 @@ static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
case EXPR_BINARY_OP: {
Value lhs, rhs;
/* TODO(eventually): short-circuiting */
- eval_expr(ev, e->binary.lhs, &lhs);
- eval_expr(ev, e->binary.rhs, &rhs);
+ if (!eval_expr(ev, e->binary.lhs, &lhs)) return false;
+ if (!eval_expr(ev, e->binary.rhs, &rhs)) return false;
/* OPTIM: this is not ideal, but 5+3.7 will be 5:int+3.7:f32 right now */
val_cast(&lhs, &e->binary.lhs->type, &lhs, &e->type);
val_cast(&rhs, &e->binary.rhs->type, &rhs, &e->type);
@@ -412,15 +412,14 @@ static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
IfExpr *i = &e->if_;
if (i->cond) {
Value cond;
- eval_expr(ev, i->cond, &cond);
+ if (!eval_expr(ev, i->cond, &cond)) return false;
if (val_truthiness(&cond, &i->cond->type)) {
- eval_block(ev, &i->body, v);
+ if (!eval_block(ev, &i->body, v)) return false;
} else if (i->next_elif) {
- eval_expr(ev, i->next_elif, v);
- return;
+ if (!eval_expr(ev, i->next_elif, v)) return false;
}
} else {
- eval_block(ev, &i->body, v);
+ if (!eval_block(ev, &i->body, v)) return false;
}
} break;
case EXPR_WHILE: {
@@ -428,15 +427,15 @@ static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
WhileExpr *w = &e->while_;
while (1) {
if (w->cond) {
- eval_expr(ev, w->cond, &cond);
+ if (!eval_expr(ev, w->cond, &cond)) return false;
if (!val_truthiness(&cond, &w->cond->type))
break;
}
- eval_block(ev, &w->body, v);
+ if (!eval_block(ev, &w->body, v)) return false;
}
} break;
case EXPR_BLOCK:
- eval_block(ev, &e->block, v);
+ if (!eval_block(ev, &e->block, v)) return false;
break;
case EXPR_LITERAL_BOOL:
v->boolv = e->booll;
@@ -449,7 +448,7 @@ static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
break;
case EXPR_CAST: {
Value casted;
- eval_expr(ev, e->cast.expr, &casted);
+ if (!eval_expr(ev, e->cast.expr, &casted)) return false;
val_cast(&casted, &e->cast.expr->type, v, &e->cast.type);
} break;
case EXPR_FN:
@@ -460,7 +459,7 @@ static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
Declaration *d = idecl->decl;
if (d->flags & DECL_FLAG_CONST) {
if (!(d->flags & DECL_FLAG_FOUND_VAL)) {
- eval_expr(ev, &d->expr, &d->val);
+ if (!eval_expr(ev, &d->expr, &d->val)) return false;
d->flags |= DECL_FLAG_FOUND_VAL;
}
if (d->type.kind == TYPE_TUPLE) {
@@ -476,46 +475,59 @@ static void eval_expr(Evaluator *ev, Expression *e, Value *v) {
} else {
*v = d->val;
}
+ } else {
+ char *s = ident_to_str(e->ident);
+ err_print(e->where, "Cannot evaluate non-constant '%s' at compile time.", s);
+ free(s);
+ return false;
}
} break;
case EXPR_TUPLE: {
size_t i, n = arr_len(e->tuple);
v->tuple = evalr_malloc(ev, n * sizeof *v->tuple);
for (i = 0; i < n; i++) {
- eval_expr(ev, &e->tuple[i], &v->tuple[i]);
+ if (!eval_expr(ev, &e->tuple[i], &v->tuple[i]))
+ return false;
}
} break;
case EXPR_DIRECT: {
DirectExpr *d = &e->direct;
switch (d->which) {
case DIRECT_C:
- /* TODO: return error? */
- break;
+ err_print(e->where, "Cannot run C code at compile time.");
+ return false;
+ case DIRECT_COUNT: assert(0); return false;
}
}
}
+ return true;
}
-static void eval_stmt(Evaluator *ev, Statement *stmt) {
+static bool eval_stmt(Evaluator *ev, Statement *stmt) {
switch (stmt->kind) {
case STMT_DECL:
/* TODO */
break;
case STMT_EXPR: {
Value unused;
- eval_expr(ev, &stmt->expr, &unused);
+ if (!eval_expr(ev, &stmt->expr, &unused))
+ return false;
} break;
case STMT_RET:
/* TODO */
break;
}
+ return true;
}
-static void eval_block(Evaluator *ev, Block *b, Value *v) {
+static bool eval_block(Evaluator *ev, Block *b, Value *v) {
arr_foreach(b->stmts, Statement, stmt) {
- eval_stmt(ev, stmt);
+ if (!eval_stmt(ev, stmt))
+ return false;
}
if (b->ret_expr) {
- eval_expr(ev, b->ret_expr, v);
+ if (!eval_expr(ev, b->ret_expr, v))
+ return false;
}
+ return true;
}
diff --git a/main.c b/main.c
index 34e44b0..e77b6cb 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,5 @@
/*
TODO:
-compile-time tuples
call fns at compile time
finish evaluator
improve casting: do you really need "as"?
diff --git a/parse.c b/parse.c
index 6db62d1..0ee8b8a 100644
--- a/parse.c
+++ b/parse.c
@@ -1115,7 +1115,6 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
}
*(Expression *)arr_add(&e->direct.args) = arg->val;
}
- arr_clear(&args);
return true;
} else {
/* no args */
diff --git a/test.toc b/test.toc
index c608fc8..795a695 100644
--- a/test.toc
+++ b/test.toc
@@ -1,5 +1,5 @@
main @= fn() {
- foo @= true;
- N, M @= 8 * if foo { 8 } else { 3} - 3, 894;
- x : [N + M]int;
+ // foo @= true;
+ // N, M @= 8 * if foo { 8 } else { 3} - 3, 894;
+ x : [#C("3")]int;
}; \ No newline at end of file
diff --git a/types.c b/types.c
index e619225..66a6e6f 100644
--- a/types.c
+++ b/types.c
@@ -290,8 +290,8 @@ static bool type_resolve(Typer *tr, Type *t) {
Expression *n_expr = t->arr.n_expr;
if (!types_expr(tr, n_expr)) return false;
if (n_expr->type.kind == TYPE_UNKNOWN) {
- t->arr.n = 0;
- break;
+ err_print(n_expr->where, "Cannot determine type of array size at compile time.");
+ return false;
}
if (n_expr->type.kind != TYPE_BUILTIN || !type_builtin_is_int(n_expr->type.builtin)) {
char *s = type_to_str(&n_expr->type);
@@ -299,7 +299,8 @@ static bool type_resolve(Typer *tr, Type *t) {
free(s);
return false;
}
- eval_expr(tr->evalr, n_expr, &val);
+ if (!eval_expr(tr->evalr, n_expr, &val))
+ return false;
U64 size;
if (type_builtin_is_signed(n_expr->type.builtin)) {
@@ -1029,7 +1030,8 @@ static bool types_decl(Typer *tr, Declaration *d) {
}
if (d->flags & DECL_FLAG_CONST) {
if (!(d->flags & DECL_FLAG_FOUND_VAL)) {
- eval_expr(tr->evalr, &d->expr, &d->val);
+ if (!eval_expr(tr->evalr, &d->expr, &d->val))
+ return false;
d->flags |= DECL_FLAG_FOUND_VAL;
}
}