summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/eval.c b/eval.c
index c2efc5d..b024b8b 100644
--- a/eval.c
+++ b/eval.c
@@ -1062,6 +1062,7 @@ static Value *decl_add_val(Declaration *d) {
}
static void decl_remove_val(Declaration *d) {
+ assert(arr_len(d->val_stack));
Value **valpp = arr_last(d->val_stack);
Value *valp = *valpp;
if (arr_len(d->idents) == 1 || d->type.kind == TYPE_TUPLE) {
@@ -1642,6 +1643,19 @@ static Status eval_decl(Evaluator *ev, Declaration *d) {
return true;
}
+
+static void eval_exit_stmts(Statement *stmts, Statement *last_reached) {
+ if (stmts) {
+ for (Statement *s = stmts; s <= last_reached; ++s) {
+ if (s->kind == STMT_DECL && !(s->decl->flags & DECL_IS_CONST)) {
+ Declaration *d = s->decl;
+ decl_remove_val(d);
+ }
+ /* STMT_INCLUDEs are handled by eval_stmt; don't worry */
+ }
+ }
+}
+
static Status eval_stmt(Evaluator *ev, Statement *stmt) {
switch (stmt->kind) {
case STMT_DECL:
@@ -1661,25 +1675,20 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
}
ev->returning = true;
} break;
- case STMT_INCLUDE:
- arr_foreach(stmt->inc.stmts, Statement, sub)
+ case STMT_INCLUDE: {
+ Statement *last_reached = arr_last(stmt->inc.stmts);
+ arr_foreach(stmt->inc.stmts, Statement, sub) {
if (!eval_stmt(ev, sub))
return false;
- break;
- }
- return true;
-}
-
-static void eval_exit_stmts(Statement *stmts, Statement *last_reached) {
- for (Statement *s = stmts; s <= last_reached; ++s) {
- if (s->kind == STMT_DECL && !(s->decl->flags & DECL_IS_CONST)) {
- Declaration *d = s->decl;
- decl_remove_val(d);
- } else if (s->kind == STMT_INCLUDE) {
- /* TODO: this doesn't work!!! */
- eval_exit_stmts(s->inc.stmts, arr_last(s->inc.stmts));
+ if (ev->returning) {
+ last_reached = sub;
+ break;
+ }
}
+ eval_exit_stmts(stmt->inc.stmts, last_reached);
+ } break;
}
+ return true;
}
static Status eval_block(Evaluator *ev, Block *b, Value *v) {