summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--abbrevs.txt1
-rw-r--r--cgen.c94
-rw-r--r--out.c26
-rw-r--r--test.toc5
-rw-r--r--types.h1
5 files changed, 108 insertions, 19 deletions
diff --git a/abbrevs.txt b/abbrevs.txt
index 49d29ce..d694268 100644
--- a/abbrevs.txt
+++ b/abbrevs.txt
@@ -1,4 +1,5 @@
allocr - allocator
+anon - anonymous
arg - argument
decl - declaration
del - delete
diff --git a/cgen.c b/cgen.c
index 8bd9964..4b4b3c7 100644
--- a/cgen.c
+++ b/cgen.c
@@ -3,6 +3,7 @@ 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 bool cgen_decl(CGenerator *g, Declaration *d);
static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) {
g->outc = out;
@@ -11,6 +12,7 @@ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *e
g->evalr = ev;
g->will_indent = true;
g->indent_lvl = 0;
+ g->anon_fns = NULL;
}
static void cgen_block_enter(CGenerator *g, Block *b) {
@@ -64,6 +66,15 @@ static inline void cgen_nl(CGenerator *g) {
g->will_indent = true;
}
+static inline void cgen_writeln(CGenerator *g, const char *fmt, ...) {
+ va_list args;
+ cgen_indent(g);
+ va_start(args, fmt);
+ vfprintf(cgen_writing_to(g), fmt, args);
+ va_end(args);
+ cgen_nl(g);
+}
+
/* should declaration be a direct function declaration C (as opposed to using a function pointer or not being a function) */
static bool cgen_fn_is_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;
@@ -196,6 +207,14 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
return true;
}
+static inline void cgen_fn_name(CGenerator *g, FnExpr *f) {
+ if (f->c.name) {
+ cgen_ident(g, f->c.name);
+ } else {
+ cgen_ident_id(g, f->c.id);
+ }
+}
+
static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) {
bool out_param = cgen_uses_ptr(&f->ret_type);
bool any_params = false;
@@ -205,11 +224,7 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) {
if (!cgen_type_pre(g, &f->ret_type, where)) return false;
cgen_write(g, " ");
}
- if (f->c.name) {
- cgen_ident(g, f->c.name);
- } else {
- cgen_ident_id(g, f->c.id);
- }
+ cgen_fn_name(g, f);
if (!out_param) {
if (!cgen_type_post(g, &f->ret_type, where)) return false;
}
@@ -306,6 +321,22 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
cgen_nl(g);
cgen_write(g, "}");
break;
+ case TYPE_TUPLE:
+ assert(set_expr);
+ assert(to_expr);
+ switch (to_expr->kind) {
+ case EXPR_TUPLE:
+ for (size_t i = 0; i < arr_len(to_expr->tuple); i++) {
+ cgen_set(g, &set_expr->tuple[i], NULL, &to_expr->tuple[i], NULL);
+ }
+ break;
+ case EXPR_CALL:
+ /* TODO */
+ break;
+ default:
+ assert(0); break;
+ }
+ break;
case TYPE_VOID:
assert(0);
return false;
@@ -456,6 +487,13 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case DIRECT_COUNT: assert(0); break;
}
break;
+ case EXPR_FN: {
+ if (g->block != NULL) {
+ Expression **eptr = arr_add(&g->anon_fns);
+ *eptr = e;
+ }
+ cgen_fn_name(g, &e->fn);
+ } break;
}
return true;
}
@@ -496,18 +534,38 @@ static void cgen_zero_value(CGenerator *g, Type *t) {
}
}
+static bool cgen_fn(CGenerator *g, FnExpr *f, Location where) {
+ if (!cgen_fn_header(g, f, where))
+ return false;
+ cgen_write(g, " ");
+ FnExpr *prev_fn = g->fn;
+ g->fn = f;
+ cgen_write(g, "{");
+ cgen_nl(g);
+ arr_foreach(f->ret_decls, Declaration, d) {
+ cgen_decl(g, d);
+ }
+ if (!cgen_block(g, &f->body))
+ return false;
+ if (f->ret_decls) {
+ if (cgen_uses_ptr(&f->ret_type)) {
+ } else {
+ cgen_write(g, "return ");
+ cgen_ident(g, f->ret_decls[0].idents[0]);
+ cgen_writeln(g, ";");
+ }
+ }
+ cgen_write(g, "}");
+ cgen_nl(g);
+ g->fn = prev_fn;
+ cgen_nl(g);
+ cgen_nl(g);
+ return true;
+}
+
static bool cgen_decl(CGenerator *g, Declaration *d) {
if (cgen_fn_is_direct(g, 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);
+ cgen_fn(g, &d->expr.fn, d->where);
} else if (d->flags & DECL_FLAG_CONST) {
/* TODO */
} else {
@@ -613,5 +671,11 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
if (!cgen_stmt(g, s))
return false;
+ typedef Expression *ExprPtr;
+ arr_foreach(g->anon_fns, ExprPtr, eptr) {
+ Expression *e = *eptr;
+ cgen_fn(g, &e->fn, e->where);
+ }
+
return true;
}
diff --git a/out.c b/out.c
index 45a817b..1c14262 100644
--- a/out.c
+++ b/out.c
@@ -20,6 +20,7 @@ i64 puti(i64 i);
void dbl(i64((* x)[3]));
i64 foo(void);
void main__(void);
+ void a0_(void);
/* code */
int main() {
main__();
@@ -27,28 +28,47 @@ int main() {
}
i64 puti(i64 i) {
+ {
printf("%ld\n", i);
-}
+}}
+
void dbl(i64((* x)[3])) {
+ {
((*x)[0]) = (((*x)[0])*2);;
((*x)[1]) = (((*x)[1])*2);;
((*x)[2]) = (((*x)[2])*2);;
-}
+}}
+
i64 foo(void) {
+i64 a = 0;
+ {
a = 3;;
if (true) {
a = 4;;
} else if (false) {
a = (17+(1/0));;
};
+}return a;
}
+
void main__(void) {
+ {
i64( a[3]) = {0};
(a[0]) = 1;;
+ (a[0]) = 5;(a[1]) = (8+(a[0]));;
(dbl((&a)));
+ void (* asdfnahsdf)(void); {
+ void (* expr__)(void); expr__ = a0_;asdfnahsdf = expr__;}
(puti((a[0])));
-}
+ (puti((foo())));
+}}
+
+
+void a0_(void) {
+ {
+}}
+
diff --git a/test.toc b/test.toc
index c0ba997..ffe245d 100644
--- a/test.toc
+++ b/test.toc
@@ -22,6 +22,9 @@ foo @= fn() a: int {
main @= fn() {
a : [3]int;
a[0] = 1;
- dbl(&a);
+ a[0], a[1] = 5, 8+a[0];
+ dbl(&a);
+ asdfnahsdf:=fn() {};
puti(a[0]);
+ puti(foo());
}; \ No newline at end of file
diff --git a/types.h b/types.h
index 9a375bd..ea7fc23 100644
--- a/types.h
+++ b/types.h
@@ -504,6 +504,7 @@ typedef struct {
ParsedFile *file;
Block *block;
FnExpr *fn; /* which function are we in? (NULL for none) - not used during decls */
+ Expression **anon_fns; /* array of pointers to expressions of anonymous functions */
Evaluator *evalr;
Identifier main_ident;
} CGenerator;