summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-12 18:53:44 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-12 18:53:44 -0400
commit1338c083d649ab15d4dee63a6f6d49e891f9cdfa (patch)
tree5a2610197820c7cd8c5e36e410e36ec82d298af7
parent2da3e68e563fd5c17223183d6d89d442c873a1cb (diff)
#foreign varargs
-rw-r--r--eval.c3
-rw-r--r--foreign.c14
-rw-r--r--main.c1
-rw-r--r--test.toc9
-rw-r--r--types.c15
5 files changed, 23 insertions, 19 deletions
diff --git a/eval.c b/eval.c
index 4a3e1a8..cefb4e6 100644
--- a/eval.c
+++ b/eval.c
@@ -1433,7 +1433,8 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (!eval_expr(ev, &e->call.arg_exprs[i], &args[i]))
return false;
}
- bool success = foreign_call(&ev->ffmgr, fn, &e->call.fn->type, args, e->where, v);
+ Type *ret_type = &e->call.fn->type.fn.types[0];
+ bool success = foreign_call(&ev->ffmgr, fn, ret_type, &e->call.arg_exprs[0].type, sizeof(Expression), args, nargs, e->where, v);
free(args);
if (!success)
return false;
diff --git a/foreign.c b/foreign.c
index 462195a..38758e9 100644
--- a/foreign.c
+++ b/foreign.c
@@ -288,7 +288,8 @@ static void ffmgr_create(ForeignFnManager *ffmgr, Allocator *allocr) {
str_hash_table_create(&ffmgr->libs_loaded, sizeof(Library), allocr);
}
-static bool foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *fn_type, Value *args, Location call_where, Value *ret) {
+/* args must be a dynamic array. */
+static bool foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *ret_type, Type *arg_types, size_t arg_types_stride, Value *args, size_t nargs, Location call_where, Value *ret) {
void (*fn_ptr)() = fn->foreign.fn_ptr;
if (!fn_ptr) {
assert(fn->flags & FN_EXPR_FOREIGN);
@@ -326,16 +327,15 @@ static bool foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *fn_type, Val
}
av_alist arg_list;
- if (!arg_list_start(&arg_list, fn_ptr, ret, &fn_type->fn.types[0], call_where))
+ if (!arg_list_start(&arg_list, fn_ptr, ret, ret_type, call_where))
return false;
- size_t nparams = arr_len(fn_type->fn.types)-1;
- for (size_t i = 0; i < nparams; ++i) {
- if (!arg_list_add(&arg_list, args[i], &fn_type->fn.types[i+1], call_where))
+ char *type = (char *)arg_types;
+ for (size_t i = 0; i < nargs; ++i) {
+ if (!arg_list_add(&arg_list, args[i], (Type *)type, call_where))
return false;
+ type += arg_types_stride;
}
av_call(arg_list);
-
- (void)fn_type; (void)args;
return true;
}
diff --git a/main.c b/main.c
index 256c5fb..c74e458 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
/*
TODO:
-#foreign variadic fns
EXPR_VALs don't always need temp variables
where
#returns_code (function/struct body is a block, to be evaluated at compile time, which returns the actual statements -- you can use this for implementation of printf)
diff --git a/test.toc b/test.toc
index f3da2c1..2f0a57c 100644
--- a/test.toc
+++ b/test.toc
@@ -1,5 +1,8 @@
-printf ::= #foreign("printf") fn(#C &"const char", #C ..);
+printf ::= #foreign("printf", "libc.so.6") fn(#C &"const char", #C ..) #C int;
main::=fn(){
- printf("Hello %d", 5);
-}; \ No newline at end of file
+ s := "Hello %d\n\0";
+ printf(&s[0], 5);
+
+};
+main(); \ No newline at end of file
diff --git a/types.c b/types.c
index 5480ec1..a4aac2a 100644
--- a/types.c
+++ b/types.c
@@ -2045,7 +2045,6 @@ static Status types_expr(Typer *tr, Expression *e) {
}
fn_decl = val.fn;
if (has_varargs) fn_decl->flags |= FN_EXPR_HAS_VARARGS;
-
}
Type *ret_type = f->type.fn.types;
@@ -2055,8 +2054,9 @@ static Status types_expr(Typer *tr, Expression *e) {
size_t nargs = arr_len(c->args);
Expression *arg_exprs = NULL;
size_t narg_exprs = 0;
+ bool is_foreign = (fn_decl->flags & FN_EXPR_FOREIGN) != 0;
I16 *order = NULL;
- if (fn_decl && !(fn_decl->flags & FN_EXPR_FOREIGN)) {
+ if (fn_decl && !is_foreign) {
if (!call_arg_param_order(fn_decl, &f->type, c->args, e->where, &order)) {
free(order);
return false;
@@ -2066,7 +2066,8 @@ static Status types_expr(Typer *tr, Expression *e) {
size_t nvarargs = 0;
if (has_varargs) {
assert(fn_decl);
- nvarargs = nargs - (size_t)order[nparams-1];
+ /* fn_decl could be foreign, so order could be NULL */
+ nvarargs = nargs - (order ? (size_t)order[nparams-1] : nparams-1);
narg_exprs = nparams-1 + nvarargs;
} else {
narg_exprs = nparams;
@@ -2075,7 +2076,7 @@ static Status types_expr(Typer *tr, Expression *e) {
arg_exprs = NULL;
arr_set_lena(&arg_exprs, narg_exprs, tr->allocr);
- if (fn_decl && !(fn_decl->flags & FN_EXPR_FOREIGN)) {
+ if (fn_decl && !is_foreign) {
size_t i = 0;
Declaration *last_param = arr_last(fn_decl->params);
arr_foreach(fn_decl->params, Declaration, param) {
@@ -2170,7 +2171,7 @@ static Status types_expr(Typer *tr, Expression *e) {
FnExpr *original_fn = NULL;
FnExpr *fn_copy = NULL;
- if (fn_type->constness || has_varargs) {
+ if (fn_type->constness || (has_varargs && !is_foreign)) {
/* eval function, create copy */
@@ -2328,7 +2329,7 @@ static Status types_expr(Typer *tr, Expression *e) {
}
}
}
- if (fn_type->constness || has_varargs) {
+ if (fn_type->constness || (has_varargs && !is_foreign)) {
/* type params, return declarations, etc */
if (!type_of_fn(tr, fn_copy, &f->type, TYPE_OF_FN_IS_INSTANCE))
return false;
@@ -2381,7 +2382,7 @@ static Status types_expr(Typer *tr, Expression *e) {
}
- if (fn_type->constness || has_varargs) {
+ if (fn_type->constness || (has_varargs && !is_foreign)) {
Type table_index_type = {0};
Value table_index = {0};