diff options
Diffstat (limited to 'decls_cgen.c')
-rw-r--r-- | decls_cgen.c | 55 |
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); |