summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c51
-rw-r--r--decls_cgen.c100
-rw-r--r--main.c3
-rwxr-xr-xrunv2
-rw-r--r--test.toc21
-rw-r--r--typedefs_cgen.c7
-rw-r--r--types.c16
-rw-r--r--types.h16
8 files changed, 105 insertions, 111 deletions
diff --git a/cgen.c b/cgen.c
index 803333b..6c6f0b4 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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;
diff --git a/main.c b/main.c
index a0bfcb7..6676157 100644
--- a/main.c
+++ b/main.c
@@ -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
diff --git a/runv b/runv
index cb14729..b636596 100755
--- a/runv
+++ b/runv
@@ -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
diff --git a/test.toc b/test.toc
index 1a4364b..02d60c6 100644
--- a/test.toc
+++ b/test.toc
@@ -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);
diff --git a/types.c b/types.c
index bafc786..c0d6544 100644
--- a/types.c
+++ b/types.c
@@ -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;
}
diff --git a/types.h b/types.h
index 3a00393..29471aa 100644
--- a/types.h
+++ b/types.h
@@ -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 {