From 3c31cd066fb761f7fc1f7f98918ae96a55dedc4d Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sat, 9 Nov 2019 15:48:01 -0500 Subject: fixed local functions --- cgen.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- decls_cgen.c | 94 ++++---------------------------- main.c | 3 + test.toc | 32 +++-------- typedefs_cgen.c | 92 +------------------------------ types.c | 25 +++++++++ 6 files changed, 206 insertions(+), 206 deletions(-) diff --git a/cgen.c b/cgen.c index 78b706e..9bae62d 100644 --- a/cgen.c +++ b/cgen.c @@ -11,6 +11,104 @@ static bool cgen_decl(CGenerator *g, Declaration *d); static bool cgen_ret(CGenerator *g, Expression *ret); static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where); static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where); +static bool cgen_defs_block(CGenerator *g, Block *b); + +/* calls f on every sub-expression of e, and block_f on every sub-block. */ +#define cgen_recurse_subexprs(g, e, f, block_f) \ + switch (e->kind) { \ + case EXPR_TYPE: \ + case EXPR_VAL: \ + case EXPR_C: \ + case EXPR_DSIZEOF: \ + case EXPR_DALIGNOF: \ + case EXPR_IDENT: \ + case EXPR_LITERAL_BOOL: \ + case EXPR_LITERAL_INT: \ + case EXPR_LITERAL_STR: \ + case EXPR_LITERAL_CHAR: \ + case EXPR_LITERAL_FLOAT: \ + break; \ + case EXPR_UNARY_OP: \ + if (!f(g, e->unary.of)) return false; \ + break; \ + case EXPR_BINARY_OP: \ + if (!f(g, e->binary.lhs)) return false; \ + if (e->binary.op != BINARY_DOT) \ + if (!f(g, e->binary.rhs)) \ + return false; \ + break; \ + case EXPR_CAST: \ + if (!f(g, e->cast.expr)) \ + return false; \ + break; \ + case EXPR_CALL: \ + if (!f(g, e->call.fn)) \ + return false; \ + arr_foreach(e->call.arg_exprs, Expression, arg) \ + if (!f(g, arg)) \ + return false; \ + break; \ + case EXPR_BLOCK: \ + if (!block_f(g, &e->block)) \ + return false; \ + break; \ + case EXPR_IF: \ + if (e->if_.cond) \ + if (!f(g, e->if_.cond)) \ + return false; \ + if (!block_f(g, &e->if_.body)) \ + return false; \ + if (e->if_.next_elif) \ + if (!f(g, e->if_.next_elif)) \ + return false; \ + break; \ + case EXPR_WHILE: \ + if (e->while_.cond) \ + if (!f(g, e->while_.cond)) \ + return false; \ + if (!block_f(g, &e->while_.body)) \ + return false; \ + break; \ + case EXPR_EACH: { \ + EachExpr *ea = &e->each; \ + if (!each_enter(e, 0)) return false; \ + if (ea->flags & EACH_IS_RANGE) { \ + if (!f(g, ea->range.from)) \ + return false; \ + if (ea->range.to && !f(g, ea->range.to)) \ + return false; \ + /* step is a value, not an expression */ \ + } else { \ + if (!f(g, ea->of)) \ + return false; \ + } \ + if (!block_f(g, &ea->body)) return false; \ + each_exit(e); \ + } break; \ + case EXPR_TUPLE: \ + arr_foreach(e->tuple, Expression, x) \ + if (!f(g, x)) \ + return false; \ + break; \ + case EXPR_SLICE: \ + if (!f(g, e->slice.of)) return false; \ + if (e->slice.from && !f(g, e->slice.from)) \ + return false; \ + if (e->slice.to && !f(g, e->slice.to)) \ + return false; \ + break; \ + case EXPR_FN: \ + if (!fn_enter(&e->fn, 0)) return false; \ + if (!block_f(g, &e->fn.body)) \ + return false; \ + fn_exit(&e->fn); \ + break; \ + case EXPR_NEW: \ + if (e->new.n && !f(g, e->new.n)) \ + return false; \ + break; \ + } + static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) { g->outc = out; @@ -365,9 +463,9 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) { /* -Either set_expr or set_str should be NULL and either to_expr or to_str should be NULL -Also, set_str and/or to_str should be NULL -this will call cgen_expr_pre for set_expr and to_expr + Either set_expr or set_str should be NULL and either to_expr or to_str should be NULL + Also, set_str and/or to_str should be NULL + this will call cgen_expr_pre for set_expr and to_expr */ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr, const char *to_str) { @@ -1476,17 +1574,17 @@ static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) { /* Because Value is a union, a pointer to v works as a pointer to any member. As a result, this function is only needed for type checking. - */ + */ return cgen_val_ptr(g, v, t, where); } + static bool cgen_decl(CGenerator *g, Declaration *d) { int has_expr = d->flags & DECL_FLAG_HAS_EXPR; bool is_tuple = d->type.kind == TYPE_TUPLE; if (cgen_fn_is_direct(g, d)) { - if (!cgen_fn(g, &d->expr.fn, d->where)) - return false; + /* definition already generated by cgen_defs_decl */ } else if ((d->flags & DECL_FLAG_CONST) || g->block == NULL) { /* declarations where we use a value */ for (size_t idx = 0; idx < arr_len(d->idents); idx++) { @@ -1629,6 +1727,58 @@ static bool cgen_stmt(CGenerator *g, Statement *s) { return true; } +static bool cgen_defs_expr(CGenerator *g, Expression *e) { + if (e->kind == EXPR_FN) { + if (!cgen_fn(g, &e->fn, e->where)) + return false; + } + cgen_recurse_subexprs(g, e, cgen_defs_expr, cgen_defs_block); + return true; +} + +static bool cgen_defs_decl(CGenerator *g, Declaration *d) { + if (cgen_fn_is_direct(g, d)) { + if (!cgen_fn(g, &d->expr.fn, d->where)) + return false; + if (!cgen_defs_block(g, &d->expr.fn.body)) + return false; + } else { + if (d->flags & DECL_FLAG_HAS_EXPR) { + if (!cgen_defs_expr(g, &d->expr)) + return false; + } + } + return true; +} + + +static bool cgen_defs_stmt(CGenerator *g, Statement *s) { + switch (s->kind) { + case STMT_DECL: + if (!cgen_defs_decl(g, &s->decl)) + return false; + break; + case STMT_EXPR: + if (!cgen_defs_expr(g, &s->expr)) + return false; + break; + case STMT_RET: + if (s->ret.flags & RET_HAS_EXPR) + if (!cgen_defs_expr(g, &s->ret.expr)) + return false; + break; + } + return true; +} + +static bool cgen_defs_block(CGenerator *g, Block *b) { + arr_foreach(b->stmts, Statement, s) { + if (!cgen_defs_stmt(g, s)) + return false; + } + return true; +} + static bool cgen_file(CGenerator *g, ParsedFile *f) { g->block = NULL; g->file = f; @@ -1657,6 +1807,10 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) { return false; cgen_write(g, "/* code */\n"); cgen_write(g, "int main() {\n\tmain__();\n\treturn 0;\n}\n\n"); + arr_foreach(f->stmts, Statement, s) { + if (!cgen_defs_stmt(g, s)) + return false; + } arr_foreach(f->stmts, Statement, s) { if (!cgen_stmt(g, s)) diff --git a/decls_cgen.c b/decls_cgen.c index ad0c552..7ac286d 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -3,72 +3,15 @@ static bool cgen_decls_block(CGenerator *g, Block *b); static bool cgen_decls_expr(CGenerator *g, Expression *e) { switch (e->kind) { - case EXPR_UNARY_OP: - if (!cgen_decls_expr(g, e->unary.of)) - return false; - break; - case EXPR_BINARY_OP: - if (!cgen_decls_expr(g, e->binary.lhs)) - return false; - - if (e->binary.op != BINARY_DOT) - if (!cgen_decls_expr(g, e->binary.rhs)) - return false; - break; - case EXPR_CAST: - if (!cgen_decls_expr(g, e->cast.expr)) - return false; - break; case EXPR_CALL: - if (!cgen_decls_expr(g, e->call.fn)) - return false; - arr_foreach(e->call.arg_exprs, Expression, a) - if (!cgen_decls_expr(g, a)) - return false; - break; - case EXPR_BLOCK: - if (!cgen_decls_block(g, &e->block)) - return false; - break; - case EXPR_IF: - if (e->if_.cond) - if (!cgen_decls_expr(g, e->if_.cond)) - return false; - if (!cgen_decls_block(g, &e->if_.body)) - return false; - if (e->if_.next_elif) - if (!cgen_decls_expr(g, e->if_.next_elif)) - return false; - break; - case EXPR_WHILE: - if (e->while_.cond) - if (!cgen_decls_expr(g, e->while_.cond)) - return false; - if (!cgen_decls_block(g, &e->while_.body)) - return false; - break; - case EXPR_EACH: { - EachExpr *ea = &e->each; - if (ea->flags & EACH_IS_RANGE) { - if (!cgen_decls_expr(g, ea->range.from)) - return false; - if (ea->range.to && !cgen_decls_expr(g, ea->range.to)) - return false; - /* step is a value, not an expression */ - } else { - if (!cgen_decls_expr(g, ea->of)) - return false; + if (e->call.fn->kind == EXPR_IDENT) { + IdentDecl *idecl = ident_decl(e->call.fn->ident); + if (idecl->kind == IDECL_DECL && + idecl->decl->expr.kind == EXPR_FN) { + /* directly calling a function; might need to generate a copy of this function */ + /* TODO ASDF */ + } } - } break; - case EXPR_TUPLE: - arr_foreach(e->tuple, Expression, x) - if (!cgen_decls_expr(g, x)) - return false; - break; - case EXPR_SLICE: - if (!cgen_decls_expr(g, e->slice.of)) return false; - if (e->slice.from && !cgen_decls_expr(g, e->slice.from)) return false; - if (e->slice.to && !cgen_decls_expr(g, e->slice.to)) return false; break; case EXPR_FN: e->fn.c.name = NULL; @@ -78,24 +21,13 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) { return false; cgen_write(g, ";"); cgen_nl(g); - if (!cgen_decls_block(g, &e->fn.body)) - return false; fn_exit(&e->fn); break; - case EXPR_TYPE: - case EXPR_VAL: - case EXPR_C: - case EXPR_DSIZEOF: - case EXPR_DALIGNOF: - case EXPR_NEW: - case EXPR_IDENT: - case EXPR_LITERAL_BOOL: - case EXPR_LITERAL_INT: - case EXPR_LITERAL_STR: - case EXPR_LITERAL_CHAR: - case EXPR_LITERAL_FLOAT: + default: break; } + cgen_recurse_subexprs(g, e, cgen_decls_expr, cgen_decls_block); + return true; } @@ -148,12 +80,6 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s) { static bool cgen_decls_file(CGenerator *g, ParsedFile *f) { cgen_write(g, "/* declarations */\n"); - arr_foreach(f->stmts, Statement, s) { - /* if only (you need to recurse!) */ - /* OPTIM?? */ - if (s->kind == STMT_DECL) { - } - } arr_foreach(f->stmts, Statement, s) { if (!cgen_decls_stmt(g, s)) return false; diff --git a/main.c b/main.c index 3c0c0b5..6c413f7 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,9 @@ /* TODO: compile-time arguments +evaluate default arguments +compile-time arguments for out parameter functions +compile-time arguments for functions returning tuples don't allow pointers to functions with compile-time arguments don't allow while {3; 5} (once break is added) any odd number of "s for a string diff --git a/test.toc b/test.toc index 65f9f30..ddd4c04 100644 --- a/test.toc +++ b/test.toc @@ -4,31 +4,13 @@ puti @= fn(x: int) { "); }; -putf @= fn(x: float) { - #C("printf(\"%f\\n\", (double)x); -"); -}; - -sum @= fn(x: []int) int { - total := 0; - p := &x[0]; - while p < &x[0] + x.len { - total += *p; - p += 1; - } - total -}; - -some_sum @= fn() int { - foo := new(int, 10); - each _, i := foo { - foo[i] = i; - } - sum(foo) -}; +// putf @= fn(x: float) { +// #C("printf(\"%f\\n\", (double)x); +// "); +// }; main @= fn() { - puti(some_sum()); - X @= some_sum(); - puti(X); + b @= fn(x: int) int { 2*x }; + puti(b(10)); }; + diff --git a/typedefs_cgen.c b/typedefs_cgen.c index 8756298..46c629b 100644 --- a/typedefs_cgen.c +++ b/typedefs_cgen.c @@ -11,97 +11,7 @@ static bool typedefs_block(CGenerator *g, Block *b) { } static bool typedefs_expr(CGenerator *g, Expression *e) { - switch (e->kind) { - case EXPR_UNARY_OP: - if (!typedefs_expr(g, e->unary.of)) - return false; - break; - case EXPR_BINARY_OP: - if (!typedefs_expr(g, e->binary.lhs)) - return false; - - if (e->binary.op != BINARY_DOT) - if (!typedefs_expr(g, e->binary.rhs)) - return false; - break; - case EXPR_CAST: - if (!typedefs_expr(g, e->cast.expr)) - return false; - break; - case EXPR_CALL: - if (!typedefs_expr(g, e->call.fn)) - return false; - arr_foreach(e->call.arg_exprs, Expression, a) - if (!typedefs_expr(g, a)) - return false; - break; - case EXPR_BLOCK: - if (!typedefs_block(g, &e->block)) - return false; - break; - case EXPR_IF: - if (e->if_.cond) - if (!typedefs_expr(g, e->if_.cond)) - return false; - if (!typedefs_block(g, &e->if_.body)) - return false; - if (e->if_.next_elif) - if (!typedefs_expr(g, e->if_.next_elif)) - return false; - break; - case EXPR_WHILE: - if (e->while_.cond) - if (!typedefs_expr(g, e->while_.cond)) - return false; - if (!typedefs_block(g, &e->while_.body)) - return false; - break; - case EXPR_EACH: { - EachExpr *ea = &e->each; - if (ea->flags & EACH_IS_RANGE) { - if (!typedefs_expr(g, ea->range.from)) - return false; - if (ea->range.to && !typedefs_expr(g, ea->range.to)) - return false; - /* step is a value, not an expression */ - } else { - if (!typedefs_expr(g, ea->of)) - return false; - } - } break; - case EXPR_TUPLE: - arr_foreach(e->tuple, Expression, x) - if (!typedefs_expr(g, x)) - return false; - break; - case EXPR_SLICE: - if (!typedefs_expr(g, e->slice.of)) return false; - if (e->slice.from && !typedefs_expr(g, e->slice.from)) return false; - if (e->slice.to && !typedefs_expr(g, e->slice.to)) return false; - break; - case EXPR_FN: - fn_enter(&e->fn, 0); - if (!typedefs_block(g, &e->fn.body)) - return false; - fn_exit(&e->fn); - break; - case EXPR_NEW: - if (e->new.n && !typedefs_expr(g, e->new.n)) - return false; - break; - case EXPR_VAL: - case EXPR_TYPE: - case EXPR_C: - case EXPR_DSIZEOF: - case EXPR_DALIGNOF: - case EXPR_IDENT: - case EXPR_LITERAL_BOOL: - case EXPR_LITERAL_INT: - case EXPR_LITERAL_STR: - case EXPR_LITERAL_CHAR: - case EXPR_LITERAL_FLOAT: - break; - } + cgen_recurse_subexprs(g, e, typedefs_expr, typedefs_block); return true; } diff --git a/types.c b/types.c index a635956..f84d9a8 100644 --- a/types.c +++ b/types.c @@ -1042,6 +1042,31 @@ static bool types_expr(Typer *tr, Expression *e) { } } } + if (fn_decl) { + /* evaluate compile-time arguments */ + size_t i = 0; + arr_foreach(fn_decl->params, Declaration, param) { + if (param->flags & DECL_FLAG_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; + } + new_args[i].kind = EXPR_VAL; + new_args[i].val = arg_val; + i++; + } + } else { + i += arr_len(param->idents); + } + } + } *t = *ret_type; c->arg_exprs = new_args; break; -- cgit v1.2.3