summaryrefslogtreecommitdiff
path: root/decls_cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'decls_cgen.c')
-rw-r--r--decls_cgen.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/decls_cgen.c b/decls_cgen.c
index 190c004..92b0f3c 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -6,18 +6,63 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
case EXPR_CALL:
if (e->call.fn->kind == EXPR_IDENT) {
IdentDecl *idecl = ident_decl(e->call.fn->ident);
+ Block *prev = g->block;
+ /* temporarily set g->block so that cgen_fn_is_direct works */
+ g->block = idecl->scope;
if (idecl->kind == IDECL_DECL &&
- idecl->decl->expr.kind == EXPR_FN) {
+ cgen_fn_is_direct(g, idecl->decl)) {
+ g->block = prev;
+ FnExpr *f = &idecl->decl->expr.fn;
+ f->c.name = idecl->decl->idents[0];
/* directly calling a function; might need to generate a copy of this function */
- /* TODO ASDF */
+
+ /* OPTIM should we really be constructing a tuple & type every time? */
+ Value *compile_time_args = NULL;
+ Type *tuple_types = NULL;
+ size_t i = 0;
+ arr_foreach(f->params, Declaration, param) {
+ if (param->flags & DECL_IS_CONST) {
+ arr_foreach(param->idents, Identifier, ident) {
+ Expression *arg = &e->call.arg_exprs[i];
+ assert(arg->kind == EXPR_VAL); /* should have been evaluated by types.c */
+ *(Value *)arr_adda(&compile_time_args, g->allocr) = arg->val;
+ *(Type *)arr_add(&tuple_types) = arg->type;
+ i++;
+ }
+ } else {
+ i += arr_len(param->idents);
+ }
+ }
+ if (compile_time_args) {
+ Value tuple;
+ Type tuple_type;
+ tuple.tuple = compile_time_args;
+ tuple_type.kind = TYPE_TUPLE;
+ tuple_type.flags = TYPE_IS_RESOLVED;
+ tuple_type.tuple = tuple_types;
+ if (!f->c.instances) {
+ f->c.instances = allocr_calloc(g->allocr, 1, sizeof *f->c.instances);
+ }
+ /* lookup compile time arguments */
+ I64 instance_number = (I64)f->c.instances->n + 1;
+ bool already_generated_decl = val_hash_table_adda(g->allocr, f->c.instances, tuple, &tuple_type, &instance_number);
+ if (!already_generated_decl) {
+ /* generate a copy of this function */
+ if (!cgen_fn_header(g, f, e->where, instance_number))
+ return false;
+ cgen_write(g, ";");
+ cgen_nl(g);
+ }
+ arr_clear(&tuple_types);
+ } /* else, there are no compile time arguments; we don't need to generate a separate declaration for this call */
}
}
break;
case EXPR_FN:
e->fn.c.name = NULL;
- e->fn.c.id = g->ident_counter++;
+ e->fn.c.id = g->ident_counter++;
fn_enter(&e->fn, 0);
- if (!cgen_fn_header(g, &e->fn, e->where))
+ if (!cgen_fn_header(g, &e->fn, e->where, 0))
return false;
cgen_write(g, ";");
cgen_nl(g);
@@ -46,7 +91,7 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
if (!fn_has_any_const_params(&d->expr.fn)) {
d->expr.fn.c.name = d->idents[0];
fn_enter(&d->expr.fn, 0);
- if (!cgen_fn_header(g, &d->expr.fn, d->where))
+ if (!cgen_fn_header(g, &d->expr.fn, d->where, 0))
return false;
cgen_write(g, ";");
cgen_nl(g);