From 36d01481e735d40df558ef90eadd3c705f8173c7 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Wed, 13 Nov 2019 12:07:12 -0500 Subject: local & anonymous fns with const params --- cgen.c | 41 +++++++++++++++++++++++------------------ decls_cgen.c | 18 ++++++++++-------- runv | 2 +- test.toc | 17 ++++++++++------- types.c | 35 ++++++++++++++++------------------- types.h | 1 - 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; -- cgit v1.2.3