summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c29
-rw-r--r--foreign.c13
-rw-r--r--toc.c1
3 files changed, 33 insertions, 10 deletions
diff --git a/eval.c b/eval.c
index 07607f2..3fc414e 100644
--- a/eval.c
+++ b/eval.c
@@ -1428,26 +1428,36 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
return false;
fn = fnv.fn;
}
+ if (fn->flags & FN_EXPR_FOREIGN) {
+ size_t nargs = arr_len(e->call.arg_exprs);
+ Value *args = err_malloc(nargs * sizeof *args);
+ for (size_t i = 0; i < nargs; ++i) {
+ if (!eval_expr(ev, &e->call.arg_exprs[i], &args[i]))
+ return false;
+ }
+ bool success = foreign_call(fn, &e->call.fn->type, args, e->where);
+ free(args);
+ if (!success)
+ return false;
+ break;
+ }
+
/* make sure function body is typed before calling it */
if (!types_block(ev->typer, &fn->body))
return false;
- /* set parameter declaration values */
+ /* set parameter values */
Declaration *params = fn->params;
- /* OPTIM (NOTE: currently needed for recursion) */
- Value *args = NULL;
- arr_resv(&args, arr_len(e->call.arg_exprs));
- for (size_t i = 0; i < arr_len(e->call.arg_exprs); ++i) {
- if (!eval_expr(ev, &e->call.arg_exprs[i], &args[i]))
- return false;
- }
fn_enter(fn, 0);
long arg = 0;
arr_foreach(params, Declaration, p) {
int idx = 0;
arr_foreach(p->idents, Identifier, i) {
+ Value arg_val;
+ if (!eval_expr(ev, &e->call.arg_exprs[arg], &arg_val))
+ return false;
Type *type = p->type.kind == TYPE_TUPLE ? &p->type.tuple[idx++] : &p->type;
IdentDecl *id = ident_decl(*i);
- copy_val(NULL, &id->val, &args[arg], type);
+ copy_val(NULL, &id->val, &arg_val, type);
id->flags |= IDECL_HAS_VAL;
++arg;
}
@@ -1472,7 +1482,6 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
++idx;
}
}
- arr_clear(&args);
if (!eval_block(ev, &fn->body, &e->type, v)) {
fn_exit(fn);
return false;
diff --git a/foreign.c b/foreign.c
new file mode 100644
index 0000000..7d441be
--- /dev/null
+++ b/foreign.c
@@ -0,0 +1,13 @@
+#if COMPILE_TIME_FOREIGN_FN_SUPPORT
+static bool foreign_call(FnExpr *fn, Type *fn_type, Value *args, Location call_where) {
+ assert(fn->flags & FN_EXPR_FOREIGN);
+ /* TODO */
+ return true;
+}
+#else
+static bool foreign_call(FnExpr *fn, Type *fn_type, Value *args, Location call_where) {
+ (void)fn; (void)fn_type; (void)args;
+ err_print(call_where, "You have not compiled toc with compile time foreign function support.");
+ return false;
+}
+#endif
diff --git a/toc.c b/toc.c
index 153a19f..155e04f 100644
--- a/toc.c
+++ b/toc.c
@@ -79,6 +79,7 @@ static inline bool type_is_slicechar(Type *t) {
#include "tokenizer.c"
#include "parse.c"
#include "scope.c"
+#include "foreign.c"
#include "eval.c"
#include "infer.c"
#include "package.c"