diff options
-rw-r--r-- | cgen.c | 51 | ||||
-rw-r--r-- | decls_cgen.c | 100 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rwxr-xr-x | runv | 2 | ||||
-rw-r--r-- | test.toc | 21 | ||||
-rw-r--r-- | typedefs_cgen.c | 7 | ||||
-rw-r--r-- | types.c | 16 | ||||
-rw-r--r-- | types.h | 16 |
8 files changed, 105 insertions, 111 deletions
@@ -1079,18 +1079,6 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { return false; break; case EXPR_VAL: - if (!cgen_val_pre(g, e->val, &e->type, e->where)) - return false; - if (!cgen_type_pre(g, &e->type, e->where)) return false; - e->val_c_id = g->ident_counter++; - cgen_write(g, " "); - cgen_ident_id(g, e->val_c_id); - if (!cgen_type_post(g, &e->type, e->where)) return false; - cgen_write(g, " = "); - if (!cgen_val(g, e->val, &e->type, e->where)) - return false; - cgen_write(g, ";"); - cgen_nl(g); break; case EXPR_LITERAL_INT: case EXPR_LITERAL_FLOAT: @@ -1317,28 +1305,20 @@ static bool cgen_expr(CGenerator *g, Expression *e) { if (cgen_uses_ptr(&e->type)) { cgen_ident_id(g, e->call.c.id); } else if (e->call.c.instance) { - assert(e->call.fn->kind == EXPR_IDENT); - Identifier name = e->call.fn->ident; - cgen_write(g, "("); - cgen_ident(g, name); - cgen_write(g, "%"PRIu32, e->call.c.instance); cgen_write(g, "("); - FnExpr *f = &ident_decl(name)->decl->expr.fn; + if (!cgen_expr(g, e->call.fn)) + return false; + cgen_write(g, "%"PRId64"(", e->call.c.instance); Expression *args = e->call.arg_exprs; + FnType *fn_type = &e->call.fn->type.fn; bool first_arg = true; - int i = 0; - arr_foreach(f->params, Declaration, param) { - if (!(param->flags & DECL_IS_CONST)) { - arr_foreach(param->idents, Identifier, ident) { - if (!first_arg) - cgen_write(g, ", "); - first_arg = false; - if (!cgen_expr(g, &args[i])) - return false; - i++; - } - } else { - i += (int)arr_len(param->idents); + for (size_t i = 0; i < arr_len(fn_type->types)-1; i++) { + if (!fn_type->constant[i]) { + if (!first_arg) + cgen_write(g, ", "); + first_arg = false; + if (!cgen_expr(g, &args[i])) + return false; } } cgen_write(g, ")"); @@ -1410,7 +1390,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) { cgen_ident_id(g, e->slice.c.id); break; case EXPR_VAL: - cgen_ident_id(g, e->val_c_id); + assert(!*"Value expressions cannot be cgenerated!!!"); break; } return true; @@ -1423,12 +1403,13 @@ static bool cgen_expr(CGenerator *g, Expression *e) { */ static bool cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) { Block *prev = g->block; - if (!(flags & CGEN_BLOCK_NOBRACES)) + if (!(flags & CGEN_BLOCK_NOBRACES)) { cgen_write(g, "{"); + cgen_nl(g); + } if (!(flags & CGEN_BLOCK_NOENTER)) if (!cgen_block_enter(g, b)) return false; - cgen_nl(g); arr_foreach(b->stmts, Statement, s) if (!cgen_stmt(g, s)) return false; @@ -1650,8 +1631,6 @@ static bool cgen_val(CGenerator *g, Value v, Type *t, Location where) { return cgen_val_ptr(g, val_get_ptr(&v, t), t, where); } - - static bool cgen_decl(CGenerator *g, Declaration *d) { int has_expr = d->flags & DECL_HAS_EXPR; bool is_tuple = d->type.kind == TYPE_TUPLE; 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; @@ -1,6 +1,9 @@ /* TODO: +make compile time arguments part of type fix local functions +test direct calling of function with compile time arguments (kind of useless, but test it anyways) +compile time arguments + out parameters double check that val_get_ptr is being used everywhere it should be evaluate default arguments compile-time arguments for out parameter functions @@ -1,5 +1,5 @@ #!/bin/sh -valgrind -q --track-origins=yes ./toc test.toc || exit 1 +valgrind -q --track-origins=yes --error-exitcode=1 ./toc test.toc || exit -1 if [ "$1" = "c" ]; then gcc out.c && ./a.out elif [ "$1" = "pc" ]; then @@ -1,26 +1,19 @@ -puti @= fn(x: int) { - #C("printf(\"%ld\\n\", (long)x); -"); -}; +// puti @= fn(x: int) { +// #C("printf(\"%ld\\n\", (long)x); +// "); +// }; // putf @= fn(x: float) { // #C("printf(\"%f\\n\", (double)x); // "); // }; -add @= fn(x: int, y @int) int { - x + y -}; + +f @= fn(x: int, y @ int) int { x + y }; main @= fn() { - // f @= fn(x:int,y@int) int { x+y }; - // f(3,5); + f(3,5); -add(3,10); - puti(add(3, 10)); - x @= add(3, 7); - puti(add(4, x)); - puti(add(3, 5)); }; diff --git a/typedefs_cgen.c b/typedefs_cgen.c index e882419..08b582d 100644 --- a/typedefs_cgen.c +++ b/typedefs_cgen.c @@ -12,12 +12,19 @@ static bool typedefs_block(CGenerator *g, Block *b) { static bool typedefs_expr(CGenerator *g, Expression *e) { cgen_recurse_subexprs(g, e, typedefs_expr, typedefs_block); + if (e->kind == EXPR_FN) { + /* needs to go before decls_cgen.c... */ + e->fn.c.id = g->ident_counter++; + } return true; } static bool typedefs_decl(CGenerator *g, Declaration *d) { d->c.ids = NULL; + if (cgen_fn_is_direct(g, d)) { + d->expr.fn.c.name = d->idents[0]; + } for (int idx = 0; idx < (int)arr_len(d->idents); idx++) { Identifier i = d->idents[idx]; Type *type = decl_type_at_index(d, idx); @@ -234,19 +234,35 @@ static bool type_of_fn(Typer *tr, Expression *e, Type *t) { FnExpr *f = &e->fn; t->kind = TYPE_FN; t->fn.types = NULL; + t->fn.constant = NULL; /* OPTIM: constant doesn't need to be a dynamic array */ Type *ret_type = typer_arr_add(tr, &t->fn.types); if (!type_resolve(tr, &f->ret_type, e->where)) return false; *ret_type = f->ret_type; + size_t idx = 0; arr_foreach(f->params, Declaration, decl) { if (!types_decl(tr, decl)) return false; if (!type_resolve(tr, &decl->type, e->where)) return false; + unsigned is_const = decl->flags & DECL_IS_CONST; + if (is_const) { + if (!t->fn.constant) { + for (size_t i = 0; i < idx; i++) { + *(bool *)typer_arr_add(tr, &t->fn.constant) = false; + } + } + } for (size_t i = 0; i < arr_len(decl->idents); i++) { Type *param_type = typer_arr_add(tr, &t->fn.types); *param_type = decl->type; + if (t->fn.constant) { + *(bool *)typer_arr_add(tr, &t->fn.constant) = is_const != 0; + } + idx++; } } + + arr_foreach(f->ret_decls, Declaration, decl) { if (!types_decl(tr, decl)) return false; } @@ -303,15 +303,18 @@ typedef struct { #define TYPE_IS_RESOLVED 0x02 #define TYPE_STRUCT_FOUND_OFFSETS 0x04 +typedef struct { + struct Type *types; /* dynamic array [0] = ret_type, [1:] = param_types */ + bool *constant; /* [i] = is param #i constant? if NULL, none are constant. don't use it as a dynamic array, because eventually it might not be. */ +} FnType; + typedef struct Type { Location where; TypeKind kind; uint16_t flags; union { BuiltinType builtin; - struct { - struct Type *types; /* [0] = ret_type, [1..] = param_types */ - } fn; + FnType fn; struct Type *tuple; struct { struct Type *of; @@ -373,7 +376,12 @@ typedef enum { EXPR_DALIGNOF, EXPR_SLICE, EXPR_TYPE, - EXPR_VAL /* a value (it's useful to have this). for now, tuples are not supported. see cgen_set_tuple */ + /* a value (it's useful to have this). + USE WITH CAUTION + expression values are never to be cgenerated! if cgen encounters one, + it will assert(0)! + */ + EXPR_VAL } ExprKind; typedef enum { |