From 1338c083d649ab15d4dee63a6f6d49e891f9cdfa Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 12 Mar 2020 18:53:44 -0400 Subject: #foreign varargs --- eval.c | 3 ++- foreign.c | 14 +++++++------- main.c | 1 - test.toc | 9 ++++++--- types.c | 15 ++++++++------- 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}; -- cgit v1.2.3