From 272d8bfd9c7b04b32f32b327833057469e8de05a Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 10 Oct 2019 23:47:46 -0400 Subject: cgen more types, unary, etc. --- cgen.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 1 deletion(-) (limited to 'cgen.c') diff --git a/cgen.c b/cgen.c index 1eed991..297bada 100644 --- a/cgen.c +++ b/cgen.c @@ -46,6 +46,15 @@ static void cgen_write(CGenerator *g, const char *fmt, ...) { va_end(args); } +static void cgen_nl(CGenerator *g) { + fprintf(cgen_writing_to(g), "\n"); +} + +/* should declaration be a direct function declaration C (as opposed to using a function pointer or not being a function) */ +static bool cgen_is_fn_direct(CGenerator *g, Declaration *d) { + return g->block == NULL && (d->flags & DECL_FLAG_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1; +} + static void cgen_ident(CGenerator *g, Identifier i) { if (i == g->main_ident) { /* don't conflict with C's main! */ @@ -73,15 +82,65 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) { case BUILTIN_F32: cgen_write(g, "f32"); break; case BUILTIN_F64: cgen_write(g, "f64"); break; } break; + case TYPE_PTR: + if (!cgen_type_pre(g, t->ptr.of, where)) + return false; + cgen_write(g, "(*"); + break; + case TYPE_ARR: + if (!cgen_type_pre(g, t->arr.of, where)) + return false; + cgen_write(g, "("); + break; + case TYPE_FN: + if (!cgen_type_pre(g, &t->fn.types[0], where)) + return false; + cgen_write(g, " (*"); + break; case TYPE_VOID: cgen_write(g, "void"); break; case TYPE_UNKNOWN: err_print(t->where, "Can't determine type."); return false; + case TYPE_TUPLE: + /* We should never try to generate a tuple */ + assert(0); + return false; } return true; } static bool cgen_type_post(CGenerator *g, Type *t, Location where) { + switch (t->kind) { + case TYPE_PTR: + cgen_write(g, ")"); + if (!cgen_type_post(g, t->ptr.of, where)) + return false; + break; + case TYPE_ARR: + cgen_write(g, "[%lu])", (unsigned long)t->arr.n); + if (!cgen_type_post(g, t->arr.of, where)) + return false; + break; + case TYPE_FN: { + cgen_write(g, ")("); + for (size_t i = 1; i < arr_len(t->fn.types); i++) { + if (i != 1) + cgen_write(g, ", "); + if (!cgen_type_pre(g, &t->fn.types[i], where)) + return false; + if (!cgen_type_post(g, &t->fn.types[i], where)) + return false; + } + cgen_write(g, ")"); + if (!cgen_type_post(g, &t->fn.types[0], where)) + return false; + } break; + case TYPE_BUILTIN: + case TYPE_VOID: + case TYPE_UNKNOWN: + case TYPE_TUPLE: + break; + } return true; } @@ -99,6 +158,7 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) { arr_foreach(d->idents, Identifier, i) { if (!cgen_type_pre(g, &d->type, where)) return false; + cgen_write(g, " "); cgen_ident(g, *i); if (!cgen_type_post(g, &d->type, where)) return false; @@ -108,6 +168,109 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) { return true; } +static bool cgen_expr(CGenerator *g, Expression *e) { + switch (e->kind) { + case EXPR_LITERAL_FLOAT: + cgen_write(g, "%f", e->floatl); /* TODO(eventually): better precision? */ + break; + case EXPR_LITERAL_INT: + cgen_write(g, UINTEGER_FMT, e->intl); + break; + case EXPR_LITERAL_STR: { + size_t c; + cgen_write(g, "\""); + for (c = 0; c < e->strl.len; c++) { + cgen_write(g, "\\x%x", e->strl.str[c]); + } + cgen_write(g, "\""); + } break; + case EXPR_LITERAL_BOOL: + cgen_write(g, e->booll ? "true" : "false"); + break; + case EXPR_LITERAL_CHAR: + cgen_write(g, "((char)%d)", e->charl); + break; + case EXPR_IDENT: + cgen_ident(g, e->ident); + break; + case EXPR_UNARY_OP: { + const char *s = ""; + switch (e->unary.op) { + case UNARY_MINUS: + s = "-"; break; + case UNARY_DEREF: + s = "*"; break; + case UNARY_ADDRESS: + s = "&"; break; + case UNARY_NOT: + s = "!"; break; + case UNARY_DEL: + s = "free("; break; + } + cgen_write(g, s); + if (!cgen_expr(g, e->unary.of)) + return false; + if (e->unary.op == UNARY_DEL) + cgen_write(g, ")"); + } break; + } + return true; +} + +static bool cgen_decl(CGenerator *g, Declaration *d) { + if (cgen_is_fn_direct(g, d)) { + if (!cgen_fn_header(g, &d->expr.fn, d->where)) + return false; + cgen_write(g, " {"); + cgen_nl(g); + cgen_write(g, "}"); + cgen_nl(g); + cgen_nl(g); + } else if (d->flags & DECL_FLAG_CONST) { + /* TODO */ + } else { + arr_foreach(d->idents, Identifier, i) { + if (!cgen_type_pre(g, &d->type, d->where)) return false; + cgen_write(g, " "); + cgen_ident(g, *i); + if (!cgen_type_post(g, &d->type, d->where)) return false; + if (g->block == NULL) { + /* repeat expression for each ident iff we are in global scope */ + cgen_write(g, " = "); + if (!cgen_expr(g, &d->expr)) + return false; + } + cgen_write(g, "; "); + } + if (g->block != NULL) { + arr_foreach(d->idents, Identifier, i) { + cgen_ident(g, *i); + cgen_write(g, " = "); + if (!cgen_expr(g, &d->expr)) + return false; + } + } + cgen_nl(g); + } + return true; +} + + +static bool cgen_stmt(CGenerator *g, Statement *s) { + switch (s->kind) { + case STMT_DECL: + if (!cgen_decl(g, &s->decl)) return false; + break; + case STMT_EXPR: + if (!cgen_expr(g, &s->expr)) return false; + break; + case STMT_RET: + /* TODO */ + break; + } + return true; +} + static bool cgen_decls_file(CGenerator *g, ParsedFile *f); static bool cgen_file(CGenerator *g, ParsedFile *f) { @@ -131,6 +294,11 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) { return false; cgen_write(g, "/* code */\n"); cgen_block_exit(g, NULL); - cgen_write(g, "int main() {\n\tmain__();\n\treturn 0;\n}\n"); + cgen_write(g, "int main() {\n\tmain__();\n\treturn 0;\n}\n\n"); + + arr_foreach(f->stmts, Statement, s) + if (!cgen_stmt(g, s)) + return false; + return true; } -- cgit v1.2.3