summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c41
-rw-r--r--decls_cgen.c18
-rwxr-xr-xrunv2
-rw-r--r--test.toc17
-rw-r--r--types.c35
-rw-r--r--types.h1
6 files changed, 60 insertions, 54 deletions
diff --git a/cgen.c b/cgen.c
index 6c6f0b4..2dc187d 100644
--- a/cgen.c
+++ b/cgen.c
@@ -6,7 +6,6 @@ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *e
g->evalr = ev;
g->will_indent = true;
g->indent_lvl = 0;
- g->anon_fns = NULL;
g->idents = ids;
g->allocr = allocr;
}
@@ -1121,9 +1120,23 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case EXPR_LITERAL_CHAR:
cgen_write(g, "((char)%d)", e->charl);
break;
- case EXPR_IDENT:
- cgen_ident(g, e->ident);
- break;
+ case EXPR_IDENT: {
+ bool handled = false;
+ if (e->type.kind == TYPE_FN) {
+ /* generate the right function name, because it might be anonymous */
+ IdentDecl *idecl = ident_decl(e->ident);
+ if (idecl && idecl->kind == IDECL_DECL) {
+ Declaration *d = idecl->decl;
+ Value fn_val = d->val;
+ FnExpr *fn = fn_val.fn;
+ cgen_fn_name(g, fn);
+ handled = true;
+ }
+ }
+ if (!handled) {
+ cgen_ident(g, e->ident);
+ }
+ } break;
case EXPR_BINARY_OP: {
const char *s = "";
bool handled = false;
@@ -1379,13 +1392,9 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case EXPR_TYPE:
assert(0);
break;
- case EXPR_FN: {
- if (g->block != NULL) {
- Expression **eptr = arr_add(&g->anon_fns);
- *eptr = e;
- }
+ case EXPR_FN:
cgen_fn_name(g, &e->fn);
- } break;
+ break;
case EXPR_SLICE:
cgen_ident_id(g, e->slice.c.id);
break;
@@ -1634,9 +1643,7 @@ static bool cgen_val(CGenerator *g, Value v, Type *t, Location 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;
- if (cgen_fn_is_direct(g, d)) {
- /* definition already generated by cgen_defs_decl */
- } else if ((d->flags & DECL_IS_CONST) || g->block == NULL) {
+ if ((d->flags & DECL_IS_CONST) || g->block == NULL) {
/* declarations where we use a value */
for (size_t idx = 0; idx < arr_len(d->idents); idx++) {
Identifier i = d->idents[idx];
@@ -1666,6 +1673,9 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
cgen_nl(g);
}
continue;
+ } else if (type->kind == TYPE_FN && (d->flags & DECL_IS_CONST)) {
+ /* don't generate function pointer declaration for constant fns */
+ continue;
}
if (!cgen_val_pre(g, *val, type, d->where))
return false;
@@ -1881,11 +1891,6 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
if (!cgen_stmt(g, s))
return false;
}
- typedef Expression *ExprPtr;
- arr_foreach(g->anon_fns, ExprPtr, eptr) {
- Expression *e = *eptr;
- if (!cgen_fn(g, &e->fn, e->where, 0, NULL)) return false;
- }
return true;
}
diff --git a/decls_cgen.c b/decls_cgen.c
index a484e24..1a23a90 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -2,6 +2,7 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s);
static bool cgen_decls_block(CGenerator *g, Block *b);
static bool cgen_decls_expr(CGenerator *g, Expression *e) {
+ cgen_recurse_subexprs(g, e, cgen_decls_expr, cgen_decls_block);
switch (e->kind) {
case EXPR_CALL:
e->call.c.instance = 0;
@@ -57,17 +58,18 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
e->fn.c.name = NULL;
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;
- cgen_write(g, ";");
- cgen_nl(g);
- fn_exit(&e->fn);
- break;
+ if (!e->type.fn.constant) {
+ fn_enter(&e->fn, 0);
+ if (!cgen_fn_header(g, &e->fn, e->where, 0))
+ return false;
+ cgen_write(g, ";");
+ cgen_nl(g);
+ fn_exit(&e->fn);
+ }
+ break;
default:
break;
}
- cgen_recurse_subexprs(g, e, cgen_decls_expr, cgen_decls_block);
return true;
}
diff --git a/runv b/runv
index b636596..c9e5a58 100755
--- a/runv
+++ b/runv
@@ -1,5 +1,5 @@
#!/bin/sh
-valgrind -q --track-origins=yes --error-exitcode=1 ./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 02d60c6..80e1326 100644
--- a/test.toc
+++ b/test.toc
@@ -1,8 +1,8 @@
-// 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);
@@ -10,10 +10,13 @@
// };
-f @= fn(x: int, y @ int) int { x + y };
main @= fn() {
- f(3,5);
-
+f @= fn(x: int, y @ int) int { x + y };
+ puti(f(3,5));
+
+ puti(f(4, 5));
+ puti(f(3, 6));
+puti((fn(x: int, y @ int) int { x + y })(1,2));
};
diff --git a/types.c b/types.c
index c0d6544..c39510c 100644
--- a/types.c
+++ b/types.c
@@ -1036,7 +1036,12 @@ static bool types_expr(Typer *tr, Expression *e) {
params_set[p] = true;
}
if (!ret) return false;
+
+ bool any_const = false;
+ FnType *fn_type = &f->type.fn;
for (size_t i = 0; i < nparams; i++) {
+ if (fn_type->constant && fn_type->constant[i])
+ any_const = true;
if (!params_set[i]) {
size_t index = 0;
assert(fn_decl); /* we can only miss an arg if we're using named/optional args */
@@ -1059,28 +1064,20 @@ static bool types_expr(Typer *tr, Expression *e) {
}
}
}
- if (fn_decl) {
+ if (any_const) {
/* evaluate compile-time arguments */
- size_t i = 0;
- arr_foreach(fn_decl->params, Declaration, param) {
- if (param->flags & DECL_IS_CONST) {
- arr_foreach(param->idents, Identifier, ident) {
- Value arg_val;
- if (!eval_expr(tr->evalr, &new_args[i], &arg_val)) {
- if (tr->evalr->enabled) {
- char *s = ident_to_str(*ident);
- info_print(new_args[i].where, "(error occured while trying to evaluate compile-time argument, %s)", s);
- info_print(param->where, "(%s was declared constant here)", s);
- free(s);
- }
- return false;
+ for (size_t i = 0; i < arr_len(fn_type->types)-1; i++) {
+ if (fn_type->constant[i]) {
+ Value arg_val;
+ if (!eval_expr(tr->evalr, &new_args[i], &arg_val)) {
+ if (tr->evalr->enabled) {
+ info_print(new_args[i].where, "(error occured while trying to evaluate compile-time argument, argument #%lu)", (unsigned long)i);
}
- new_args[i].kind = EXPR_VAL;
- new_args[i].val = arg_val;
- i++;
+ return false;
}
- } else {
- i += arr_len(param->idents);
+ new_args[i].kind = EXPR_VAL;
+ new_args[i].val = arg_val;
+ i++;
}
}
}
diff --git a/types.h b/types.h
index 29471aa..152021a 100644
--- a/types.h
+++ b/types.h
@@ -667,7 +667,6 @@ typedef struct {
ParsedFile *file;
Block *block;
FnExpr *fn; /* which function are we in? (NULL for none) - not used during decls */
- Expression **anon_fns; /* array of pointers to expressions of anonymous functions */
Evaluator *evalr;
Identifier main_ident;
Identifiers *idents;