diff options
-rw-r--r-- | cgen.c | 170 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | out.c | 10 | ||||
-rw-r--r-- | parse.c | 5 | ||||
-rwxr-xr-x | runv | 2 | ||||
-rw-r--r-- | test.toc | 11 | ||||
-rw-r--r-- | types.c | 6 |
7 files changed, 198 insertions, 7 deletions
@@ -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; } @@ -1,6 +1,7 @@ /* TODO: re-do cgen +make sure initializers for global variables are compile-time constants any odd number of "s for a string */ #include "toc.c" @@ -21,3 +21,13 @@ int main() { main__(); return 0; } + +void main__() { +} + +i64 foo = 5; +char( bar[5]) = "\x48\x65\x6c\x6c\x6f"; +i64 a = 123; i64 b = 123; +char x = ((char)97); +i64 sadkfj = -1293812; +char kjdshaf = *&*&*&*&*&x; @@ -327,11 +327,12 @@ static bool parse_type(Parser *p, Type *type) { } t->token++; /* move past ) */ Type *ret_type = type->fn.types; - /* if there's a symbol that isn't [ or (, that can't be the start of a type */ + /* if there's a symbol that isn't [, (, or &, that can't be the start of a type */ if ((t->token->kind == TOKEN_KW && t->token->kw <= KW_LAST_SYMBOL && t->token->kw != KW_LSQUARE - && t->token->kw != KW_LPAREN) + && t->token->kw != KW_LPAREN + && t->token->kw != KW_AMPERSAND) || t->token->kw == KW_AS) { ret_type->kind = TYPE_VOID; ret_type->flags = 0; @@ -1,2 +1,2 @@ #!/bin/bash -valgrind -q --track-origins=yes ./toc test.toc +valgrind -q --track-origins=yes ./toc test.toc && cat out.c @@ -1,3 +1,10 @@ main @= fn() { - x := 5; -};
\ No newline at end of file + +}; + +foo := 5; +bar := "Hello"; +a, b := 123; +x := 'a'; +sadkfj := -1293812; +kjdshaf := *&*&*&*&*&x;
\ No newline at end of file @@ -250,6 +250,8 @@ static bool type_resolve(Evaluator *ev, Type *t) { size = val_to_u64(&val, n_expr->type.builtin); } t->arr.n = (UInteger)size; + if (!type_resolve(ev, t->arr.of)) + return false; } break; case TYPE_FN: arr_foreach(t->fn.types, Type, child_type) { @@ -277,6 +279,7 @@ static bool type_resolve(Evaluator *ev, Type *t) { } static bool types_type(Typer *tr, Type *t) { + if (t->flags & TYPE_FLAG_RESOLVED) return true; switch (t->kind) { case TYPE_ARR: if (!types_expr(tr, t->arr.n_expr)) return false; @@ -1065,7 +1068,8 @@ static void typer_create(Typer *tr, Evaluator *ev) { static bool types_file(Typer *tr, ParsedFile *f) { bool ret = true; - block_enter(NULL, f->stmts); /* enter global scope */ + if (!block_enter(NULL, f->stmts)) /* enter global scope */ + return false; arr_foreach(f->stmts, Statement, s) { if (!types_stmt(tr, s)) { ret = false; |