summaryrefslogtreecommitdiff
path: root/decls_cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'decls_cgen.c')
-rw-r--r--decls_cgen.c100
1 files changed, 44 insertions, 56 deletions
diff --git a/decls_cgen.c b/decls_cgen.c
index 1e85883..a484e24 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -5,70 +5,58 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
switch (e->kind) {
case EXPR_CALL:
e->call.c.instance = 0;
+ assert(e->call.fn->type.kind == TYPE_FN);
+ FnType *fn_type = &e->call.fn->type.fn;
+ if (fn_type->constant) {
+ Value fval;
+ /* e->call.fn had better be a compile-time constant if it has compile-time arguments */
+ if (!eval_expr(g->evalr, e->call.fn, &fval))
+ return false;
+ FnExpr *f = fval.fn;
+ /* directly calling a function; might need to generate a copy of this function */
-
- 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->flags & DECL_IS_CONST) &&
- (idecl->decl->flags & DECL_HAS_EXPR) &&
- (idecl->decl->expr.kind == EXPR_FN)) {
- 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 */
-
- /* 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);
- }
+ /* OPTIM should we really be constructing a tuple & type every time? */
+ Value *compile_time_args = NULL;
+ Type *tuple_types = NULL;
+ size_t nparams = arr_len(fn_type->types)-1;
+ for (size_t i = 0; i < nparams; i++) {
+ if (fn_type->constant[i]) {
+ 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++;
+ }
+ }
+ 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);
}
- 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);
- e->call.c.instance = (U32)instance_number;
+ /* 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);
+ e->call.c.instance = (U32)instance_number;
}
}
break;
case EXPR_FN:
e->fn.c.name = NULL;
- e->fn.c.id = g->ident_counter++;
+ if (!e->fn.c.id)
+ e->fn.c.id = g->ident_counter++;
fn_enter(&e->fn, 0);
if (!cgen_fn_header(g, &e->fn, e->where, 0))
return false;