diff options
Diffstat (limited to 'archive/decls_cgen.c')
-rw-r--r-- | archive/decls_cgen.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/archive/decls_cgen.c b/archive/decls_cgen.c new file mode 100644 index 0000000..a596f53 --- /dev/null +++ b/archive/decls_cgen.c @@ -0,0 +1,106 @@ +/* C declarations of functions and global variables. e must be a function expression */ +static bool cgen_decl_fn(CGenerator *g, FnExpr *f) { + /* assign an ID to the function */ + if (f->name && g->block == NULL) { + f->id = f->name->c_fn_reps++; + } else { + f->id = g->anon_fn_count++; + } + + if (!cgen_fn_header(g, f)) return false; + cgen_writeln(g, ";"); + return true; +} + +static bool cgen_decls_stmt(CGenerator *g, Statement *s); + +static bool cgen_decls_expr(CGenerator *g, Expression *e) { + switch (e->kind) { + case EXPR_FN: { + FnExpr *f = &e->fn; + if (f->name && g->block == NULL) { /* write named function prototypes in global scope to header file */ + g->writing_to = CGEN_WRITING_TO_H; + } else { + g->writing_to = CGEN_WRITING_TO_C; + } + if (!cgen_decl_fn(g, f)) + return false; + g->writing_to = CGEN_WRITING_TO_C; + + + bool ret = true; + Block *prev_block = g->block; + cgen_block_enter(g, &f->body); + arr_foreach(&f->body.stmts, Statement, s) { + if (!cgen_decls_stmt(g, s)) + ret = false; + } + cgen_block_exit(g, prev_block); + return ret; + } + case EXPR_CALL: + if (!cgen_decls_expr(g, e->call.fn)) + return false; + arr_foreach(&e->call.args, Expression, arg) { + if (!cgen_decls_expr(g, arg)) + return false; + } + break; + default: break; + } + return true; +} + + +static bool cgen_expr(CGenerator *g, Expression *e); +static bool cgen_decls_stmt(CGenerator *g, Statement *s) { + switch (s->kind) { + case STMT_EXPR: + return cgen_decls_expr(g, &s->expr); + case STMT_DECL: { + Declaration *d = &s->decl; + bool is_const_fn = (d->flags & DECL_FLAG_HAS_EXPR) && (d->flags & DECL_FLAG_CONST) + && d->expr.kind == EXPR_FN; + + if (is_const_fn) { + /* e.g. foo @= fn() {}; (we want to set the function's name to "foo") */ + d->expr.fn.name = *(Identifier*)d->idents.data; + } + + if (d->flags & DECL_FLAG_HAS_EXPR) { + cgen_decls_expr(g, &d->expr); + } + + if (!is_const_fn) { + if (g->block == NULL) { + /* declare this/these global variable(s) */ + arr_foreach(&d->idents, Identifier, i) { + cgen_type_pre(g, &d->type); + cgen_ident(g, *i, NULL); + cgen_type_post(g, &d->type); + if (d->flags & DECL_FLAG_HAS_EXPR) { /* TODO: check if expr is const */ + cgen_space(g); + cgen_write(g, "="); + cgen_space(g); + if (!cgen_expr(g, &d->expr)) + return false; + } + cgen_write(g, ";"); + cgen_space(g); + } + cgen_writeln(g, ""); + } + } + + } break; + } + return true; +} + +static bool cgen_decls_file(CGenerator *g, ParsedFile *f) { + arr_foreach(&f->stmts, Statement, s) { + if (!cgen_decls_stmt(g, s)) + return false; + } + return true; +} |