summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c27
-rw-r--r--main.c3
-rw-r--r--parse.c5
-rw-r--r--scope.c15
-rw-r--r--test.toc13
-rw-r--r--types.c10
6 files changed, 59 insertions, 14 deletions
diff --git a/eval.c b/eval.c
index 7754f57..2613c28 100644
--- a/eval.c
+++ b/eval.c
@@ -771,6 +771,31 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
else
v->ptr = err_calloc(1, compiler_sizeof(&e->new.type));
break;
+ case EXPR_CALL: {
+ Value fnv;
+ if (!eval_expr(ev, e->call.fn, &fnv))
+ return false;
+ FnExpr *fn = fnv.fn;
+ /* set parameter declaration values */
+ long arg = 0;
+ Declaration *params = fn->params;
+ fn_enter(fn);
+ arr_foreach(params, Declaration, p) {
+ arr_foreach(p->idents, Identifier, i) {
+ IdentDecl *id = ident_decl(*i);
+ Value *paramval = &id->val;
+ if (!eval_expr(ev, &e->call.arg_exprs[arg], paramval))
+ return false;
+ id->flags |= IDECL_FLAG_HAS_VAL;
+ arg++;
+ }
+ }
+ if (!eval_block(ev, &fn->body, v)) {
+ fn_exit(fn);
+ return false;
+ }
+ fn_exit(fn);
+ } break;
}
return true;
}
@@ -786,7 +811,6 @@ static bool eval_decl(Evaluator *ev, Declaration *d) {
long index = 0;
arr_foreach(d->idents, Identifier, i) {
IdentDecl *id = ident_decl(*i);
- id->flags |= IDECL_FLAG_HAS_VAL;
if (has_expr && d->expr.kind == EXPR_TUPLE) {
id->val = val.tuple[index++];
} else if (!has_expr && d->type.kind == TYPE_ARR) {
@@ -795,6 +819,7 @@ static bool eval_decl(Evaluator *ev, Declaration *d) {
} else {
id->val = val;
}
+ id->flags |= IDECL_FLAG_HAS_VAL;
}
return true;
}
diff --git a/main.c b/main.c
index 9024d1d..fef518a 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,5 @@
/*
TODO:
-fix double eval_expr problem
-call fns at compile time
-finish evaluator
improve casting: do you really need "as"?
fix void fn type
re-do cgen
diff --git a/parse.c b/parse.c
index 0ee8b8a..a4a5b2b 100644
--- a/parse.c
+++ b/parse.c
@@ -670,7 +670,10 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
return false;
if (t->token != end) {
- tokr_err(t, "Direct function calling in an expression is not supported.\nYou can wrap the function in parentheses.");
+ if (token_is_kw(t->token, KW_LPAREN))
+ tokr_err(t, "Direct function calling in an expression is not supported.\nYou can wrap the function in parentheses.");
+ else
+ tokr_err(t, "Expected end of expression.");
return false;
}
return true;
diff --git a/scope.c b/scope.c
index 5d01c6f..8ecda21 100644
--- a/scope.c
+++ b/scope.c
@@ -54,3 +54,18 @@ static void block_exit(Block *b, Statement *stmts) {
}
}
}
+
+/* does NOT enter function's block body */
+static void fn_enter(FnExpr *f) {
+ arr_foreach(f->params, Declaration, decl)
+ add_ident_decls(&f->body, decl);
+ arr_foreach(f->ret_decls, Declaration, decl)
+ add_ident_decls(&f->body, decl);
+}
+
+static void fn_exit(FnExpr *f) {
+ arr_foreach(f->params, Declaration, decl)
+ remove_ident_decls(&f->body, decl);
+ arr_foreach(f->ret_decls, Declaration, decl)
+ remove_ident_decls(&f->body, decl);
+}
diff --git a/test.toc b/test.toc
index 81dbee0..83f01d3 100644
--- a/test.toc
+++ b/test.toc
@@ -1,3 +1,14 @@
main @= fn() {
- ASDF : [{x:[3]int; p, q := &x[0], &x[2]; *q = 3412; *q}]f32;
+ add3 @= fn(x : int, y : int, z : int) int {
+ x + y + z
+ };
+ add2 @= fn(x : int, y : int) int {
+ x + y
+ };
+ id @= fn(x : int) int { x };
+
+ a1 : [id(7)]int;
+ a2 : [add2(53, 3)]int;
+ a3 : [add3(3,1,2)]f32;
+ GHJK : [{x := 5; x}]f32;
}; \ No newline at end of file
diff --git a/types.c b/types.c
index b23fbcd..98a47dd 100644
--- a/types.c
+++ b/types.c
@@ -423,16 +423,10 @@ static bool types_expr(Typer *tr, Expression *e) {
tr->ret_type = t->fn.types[0];
}
tr->can_ret = true;
- arr_foreach(f->params, Declaration, decl)
- add_ident_decls(&f->body, decl);
- arr_foreach(f->ret_decls, Declaration, decl)
- add_ident_decls(&f->body, decl);
+ fn_enter(f);
bool block_success = true;
block_success = types_block(tr, &e->fn.body);
- arr_foreach(f->params, Declaration, decl)
- remove_ident_decls(&f->body, decl);
- arr_foreach(f->ret_decls, Declaration, decl)
- remove_ident_decls(&f->body, decl);
+ fn_exit(f);
if (!block_success) {
success = false;
goto fn_ret;