summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c127
-rw-r--r--main.c1
-rw-r--r--out.c28
-rw-r--r--test.toc7
4 files changed, 133 insertions, 30 deletions
diff --git a/cgen.c b/cgen.c
index 95dae48..0650ca2 100644
--- a/cgen.c
+++ b/cgen.c
@@ -3,12 +3,16 @@ typedef struct {
unsigned long ident_counter;
ParsedFile *file;
Block *block;
+ FnExpr *fn; /* which function are we in? (NULL for none) - not used during decls */
Evaluator *evalr;
Identifier main_ident;
} CGenerator;
static bool cgen_stmt(CGenerator *g, Statement *s);
static bool cgen_block(CGenerator *g, Block *b);
+static bool cgen_expr(CGenerator *g, Expression *e);
+static bool cgen_type_pre(CGenerator *g, Type *t, Location where);
+static bool cgen_type_post(CGenerator *g, Type *t, Location where);
static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) {
g->outc = out;
@@ -228,6 +232,77 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) {
return true;
}
+
+/*
+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
+*/
+static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr,
+ const char *to_str) {
+ Type *type;
+ Location where;
+ if (set_expr) {
+ type = &set_expr->type;
+ where = set_expr->where;
+ } else {
+ assert(to_expr);
+ type = &to_expr->type;
+ where = to_expr->where;
+ }
+ switch (type->kind) {
+ case TYPE_BUILTIN:
+ case TYPE_FN:
+ case TYPE_PTR:
+ case TYPE_UNKNOWN:
+ if (set_expr) {
+ if (!cgen_expr(g, set_expr)) return false;
+ } else {
+ cgen_write(g, set_str);
+ }
+ cgen_write(g, " = ");
+ if (to_expr) {
+ if (!cgen_expr(g, to_expr)) return false;
+ } else {
+ cgen_write(g, to_str);
+ }
+ cgen_write(g, ";");
+ break;
+ case TYPE_ARR:
+ cgen_write(g, "{");
+ cgen_nl(g);
+ cgen_write(g, "size_t i;");
+ if (!cgen_type_pre(g, type->arr.of, where)) return false;
+ cgen_write(g, "(*arr__in)");
+ if (!cgen_type_post(g, type->arr.of, where)) return false;
+ cgen_write(g, " = ");
+ if (set_expr) {
+ if (!cgen_expr(g, set_expr)) return false;
+ } else {
+ cgen_write(g, set_str);
+ }
+ cgen_write(g, "; ");
+ if (!cgen_type_pre(g, type->arr.of, where)) return false;
+ cgen_write(g, "(*arr__out)");
+ if (!cgen_type_post(g, type->arr.of, where)) return false;
+ cgen_write(g, " = ");
+ if (to_expr) {
+ if (!cgen_expr(g, to_expr)) return false;
+ } else {
+ cgen_write(g, to_str);
+ }
+ cgen_write(g, ";");
+ cgen_nl(g);
+ cgen_write(g, "for (i = 0; i < %lu; i++) arr__out[i] = arr__in[i];", (unsigned long)type->arr.n);
+ cgen_nl(g);
+ cgen_write(g, "}");
+ break;
+ case TYPE_VOID:
+ assert(0);
+ return false;
+ }
+ return true;
+}
+
static bool cgen_expr(CGenerator *g, Expression *e) {
switch (e->kind) {
case EXPR_LITERAL_FLOAT:
@@ -255,6 +330,10 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
break;
case EXPR_BINARY_OP: {
const char *s = "";
+ if (e->binary.op == BINARY_SET) {
+ if (!cgen_set(g, e->binary.lhs, NULL, e->binary.rhs, NULL)) return false;
+ break;
+ }
switch (e->binary.op) {
case BINARY_SUB:
s = "-"; break;
@@ -264,8 +343,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
s = "*"; break;
case BINARY_DIV:
s = "/"; break;
- case BINARY_SET:
- s = "="; break;
+ case BINARY_SET: assert(0); break;
case BINARY_GT:
s = ">"; break;
case BINARY_LT:
@@ -412,8 +490,11 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
if (!cgen_fn_header(g, &d->expr.fn, d->where))
return false;
cgen_write(g, " ");
+ FnExpr *prev_fn = g->fn;
+ g->fn = &d->expr.fn;
if (!cgen_block(g, &d->expr.fn.body))
return false;
+ g->fn = prev_fn;
cgen_nl(g);
cgen_nl(g);
} else if (d->flags & DECL_FLAG_CONST) {
@@ -426,7 +507,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
if (!cgen_type_post(g, &d->type, d->where)) return false;
if (g->block == NULL && (d->flags & DECL_FLAG_HAS_EXPR)) {
cgen_write(g, " = ");
- /* repeat expression for each ident iff we are in global scope */
+ /* directly initialize iff we are in global scope */
if (!cgen_expr(g, &d->expr))
return false;
} else if (!(d->flags & DECL_FLAG_HAS_EXPR)) {
@@ -436,14 +517,26 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
cgen_write(g, "; ");
}
+ /* TODO: tuples */
if (g->block != NULL && (d->flags & DECL_FLAG_HAS_EXPR)) {
+ cgen_write(g, "{");
+ cgen_nl(g);
+ if (!cgen_type_pre(g, &d->expr.type, d->expr.where)) return false;
+ cgen_write(g, "expr__");
+ if (!cgen_type_post(g, &d->expr.type, d->expr.where)) return false;
+ cgen_write(g, "; ");
+ if (!cgen_set(g, NULL, "expr__", &d->expr, NULL))
+ return false;
arr_foreach(d->idents, Identifier, i) {
- cgen_ident(g, *i);
- cgen_write(g, " = ");
- if (!cgen_expr(g, &d->expr))
+ Expression e;
+ e.flags = 0;
+ e.kind = EXPR_IDENT;
+ e.type = d->type;
+ e.ident = *i;
+ if (!cgen_set(g, &e, NULL, NULL, "expr__"))
return false;
- cgen_write(g, "; ");
}
+ cgen_write(g, "}");
}
cgen_nl(g);
}
@@ -462,19 +555,15 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
cgen_nl(g);
break;
case STMT_RET:
- /* TODO (this doesn't work -- add fn to CGenerator) */
- if (g->block->ret_expr) {
- if (cgen_uses_out_param(&g->block->ret_expr->type)) {
- cgen_write(g, "*ret__ = ");
- if (!cgen_expr(g, &s->ret.expr)) return false;
- cgen_write(g, ";");
- } else {
- cgen_write(g, "return ");
-
- if (!cgen_expr(g, &s->ret.expr)) return false;
- }
- } else {
+ if (g->fn->ret_type.kind == TYPE_VOID) {
+ cgen_write(g, "return");
+ } else if (cgen_uses_out_param(&g->fn->ret_type)) {
+ if (!cgen_set(g, NULL, "*ret__", &s->ret.expr, NULL)) return false;
cgen_write(g, "return");
+ } else {
+ cgen_write(g, "return ");
+
+ if (!cgen_expr(g, &s->ret.expr)) return false;
}
cgen_write(g, ";");
cgen_nl(g);
diff --git a/main.c b/main.c
index ad38881..00b95a7 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
/*
TODO:
re-do cgen
+arrs are pointers
make sure initializers for global variables are compile-time constants
any odd number of "s for a string
*/
diff --git a/out.c b/out.c
index 2426dd0..2bfb426 100644
--- a/out.c
+++ b/out.c
@@ -31,23 +31,33 @@ printf("%ld\n", i);
void asdf(i64 i, i64( (*ret__)[3])) {
i64( ret[3]) = {0};
-((ret[0])=(0*i));
-((ret[1])=(1*i));
-((ret[2])=(2*i));
-return;
+i64( asdf[3]) = {0};
+(ret[0]) = (0*i);;
+(ret[1]) = (1*i);;
+(ret[2]) = (2*i);;
+{
+size_t i;i64(*arr__in) = asdf; i64(*arr__out) = ret;
+for (i = 0; i < 3; i++) arr__out[i] = arr__in[i];
+};
+{
+size_t i;i64(*arr__in) = *ret__; i64(*arr__out) = asdf;
+for (i = 0; i < 3; i++) arr__out[i] = arr__in[i];
+}return;
}
void main__() {
-i64(* x); x = ((i64(*))calloc(1, sizeof(i64)));
-((*x)=17);
+i64(* x); {
+i64(*expr__); expr__ = ((i64(*))calloc(1, sizeof(i64)));x = expr__;}
+(*x) = 17;;
if (((*x)==0)) {
-((*x)=((1+2)+(3-(5/62))));
+(*x) = ((1+2)+(3-(5/62)));;
} else {
-((*x)=((4+5)+6));
+(*x) = ((4+5)+6);;
};
(puti((*x)));
(free(x));
-void (* fptr)(i64, i64((*)[3])); fptr = asdf;
+void (* fptr)(i64, i64((*)[3])); {
+void (*expr__)(i64, i64((*)[3])); expr__ = asdf;fptr = expr__;}
}
i64 foo = 5;
diff --git a/test.toc b/test.toc
index 6160362..1aeca39 100644
--- a/test.toc
+++ b/test.toc
@@ -1,13 +1,16 @@
+
puti @= fn(i: int) {
#C("printf(\"%ld\\n\", i)");
};
asdf @= fn(i: int) [3]int {
ret : [3]int;
+ asdf : [3]int;
ret[0] = 0*i;
ret[1] = 1*i;
ret[2] = 2*i;
- return ret;
+ asdf = ret;
+ return asdf;
};
main @= fn() {
@@ -27,4 +30,4 @@ foo := 5;
bar := "Hello";
a, b := 123;
x := 'a';
-sadkfj := -1293812; \ No newline at end of file
+sadkfj := -1293812;