summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c170
-rw-r--r--main.c1
-rw-r--r--out.c10
-rw-r--r--parse.c5
-rwxr-xr-xrunv2
-rw-r--r--test.toc11
-rw-r--r--types.c6
7 files changed, 198 insertions, 7 deletions
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;
}
diff --git a/main.c b/main.c
index 8ce475d..ecbfe53 100644
--- a/main.c
+++ b/main.c
@@ -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"
diff --git a/out.c b/out.c
index 56b0d1d..9601d9c 100644
--- a/out.c
+++ b/out.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;
diff --git a/parse.c b/parse.c
index f0fe705..f949794 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
diff --git a/runv b/runv
index bf00c4f..fe4912a 100755
--- a/runv
+++ b/runv
@@ -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
diff --git a/test.toc b/test.toc
index 2bb900a..9de5527 100644
--- a/test.toc
+++ b/test.toc
@@ -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
diff --git a/types.c b/types.c
index 24f31bd..dfda38b 100644
--- a/types.c
+++ b/types.c
@@ -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;