summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base_cgen.c40
-rw-r--r--cgen.c52
-rw-r--r--out.c17
-rw-r--r--out.h3
-rw-r--r--test.toc7
-rw-r--r--types_cgen.c2
6 files changed, 73 insertions, 48 deletions
diff --git a/base_cgen.c b/base_cgen.c
index a247e7c..dc793f8 100644
--- a/base_cgen.c
+++ b/base_cgen.c
@@ -177,11 +177,15 @@ static bool cgen_type_post(CGenerator *g, Type *t) {
assert(t->fn.types.len > 0);
size_t nparams = t->fn.types.len-1;
cgen_write(g, ")(");
- for (size_t i = 0; i < nparams; i++) {
- if (!cgen_type_pre(g, &param_types[i])) return true;
- if (!cgen_type_post(g, &param_types[i])) return true;
- cgen_write(g, ",");
- cgen_write_space(g);
+ if (nparams) {
+ for (size_t i = 0; i < nparams; i++) {
+ if (!cgen_type_pre(g, &param_types[i])) return true;
+ if (!cgen_type_post(g, &param_types[i])) return true;
+ cgen_write(g, ",");
+ cgen_write_space(g);
+ }
+ } else {
+ cgen_write(g, "void");
}
cgen_write(g, ")");
if (!cgen_type_post(g, ret_type)) return false;
@@ -205,8 +209,7 @@ static bool cgen_fn_name(CGenerator *g, FnExpr *f, Location *where) {
return true;
}
-static bool cgen_fn_header(CGenerator *g, FnExpr *f) {
- CGenWritingTo writing_to_before = g->writing_to;
+static bool cgen_fn_header(CGenerator *g, FnExpr *f) {
if (!f->name || g->block != NULL) {
cgen_write(g, "static "); /* anonymous functions only exist in this translation unit */
}
@@ -214,19 +217,22 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f) {
cgen_fn_name(g, f, NULL);
if (!cgen_type_post(g, &f->ret_type)) return false;
cgen_write(g, "(");
- arr_foreach(&f->params, Param, p) {
- if (p != f->params.data) {
- cgen_write(g, ",");
- cgen_write_space(g);
+ if (f->params.len) {
+ arr_foreach(&f->params, Param, p) {
+ if (p != f->params.data) {
+ cgen_write(g, ",");
+ cgen_write_space(g);
+ }
+ if (!cgen_type_pre(g, &p->type))
+ return false;
+ cgen_ident(g, p->name, NULL);
+ if (!cgen_type_post(g, &p->type))
+ return false;
}
- if (!cgen_type_pre(g, &p->type))
- return false;
- cgen_ident(g, p->name, NULL);
- if (!cgen_type_post(g, &p->type))
- return false;
+ } else {
+ cgen_write(g, "void");
}
cgen_write(g, ")");
- g->writing_to = writing_to_before;
return true;
}
diff --git a/cgen.c b/cgen.c
index e40ba1c..222d624 100644
--- a/cgen.c
+++ b/cgen.c
@@ -64,24 +64,6 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
static bool cgen_stmt(CGenerator *g, Statement *s);
-/* Generates the definition of a function, not just the identifier */
-static bool cgen_fn(CGenerator *g, FnExpr *f) {
- if (!cgen_fn_header(g, f)) return false;
- bool ret = true;
- cgen_write_space(g);
- cgen_writeln(g, "{");
- g->indent_level++;
- Block *prev_block = g->block;
- cgen_block_enter(g, &f->body);
- arr_foreach(&f->body.stmts, Statement, s) {
- if (!cgen_stmt(g, s))
- ret = false;
- }
- cgen_block_exit(g, prev_block);
- g->indent_level--;
- cgen_writeln(g, "}");
- return ret;
-}
static bool cgen_decl(CGenerator *g, Declaration *d) {
arr_foreach(&d->idents, Identifier, ident) {
@@ -121,15 +103,35 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
static bool cgen_fns_in_stmt(CGenerator *g, Statement *s);
+/* Generates function definition, and the definitions of all functions inside this */
+static bool cgen_fn(CGenerator *g, FnExpr *f) {
+ if (!cgen_fn_header(g, f)) return false;
+ Block *prev_block = g->block;
+ cgen_block_enter(g, &f->body);
+ bool ret = true;
+ cgen_write_space(g);
+ cgen_writeln(g, "{");
+ g->indent_level++;
+ arr_foreach(&f->body.stmts, Statement, s) {
+ if (!cgen_stmt(g, s))
+ ret = false;
+ }
+ g->indent_level--;
+ cgen_writeln(g, "}");
+ if (ret) {
+ arr_foreach(&f->body.stmts, Statement, stmt) {
+ if (!cgen_fns_in_stmt(g, stmt)) ret = false;
+ }
+ }
+ cgen_block_exit(g, prev_block);
+ return ret;
+}
+
static bool cgen_fns_in_expr(CGenerator *g, Expression *e) {
switch (e->kind) {
- case EXPR_FN:
- if (!cgen_fn(g, &e->fn)) return false;
- bool ret = true;
- arr_foreach(&e->fn.body.stmts, Statement, stmt) {
- ret = ret && cgen_fns_in_stmt(g, stmt);
- }
- return ret;
+ case EXPR_FN: {
+ return cgen_fn(g, &e->fn);
+ }
case EXPR_CALL:
return cgen_fns_in_expr(g, e->call.fn);
default: return true;
diff --git a/out.c b/out.c
index 0d58e0e..ca6858c 100644
--- a/out.c
+++ b/out.c
@@ -1,7 +1,20 @@
#include "out.h"
/* toc */
-void main__() {
+static void foo(void);
+static void a___(void);
+void main__(void) {
+ void (*bar)(void) = a___;
+ foo();
+ a___();
}
-void foo() {
+static void foo(void) {
+ void (*x)(void) = a___;
+}
+static void a___(void) {
+}
+
+int main(void) {
+ main__();
+ return 0;
}
diff --git a/out.h b/out.h
index a1fb857..4cc08ee 100644
--- a/out.h
+++ b/out.h
@@ -1,3 +1,2 @@
#include <stdint.h>
-void main__();
-static void foo();
+void main__(void);
diff --git a/test.toc b/test.toc
index 935bd1e..0adc8f2 100644
--- a/test.toc
+++ b/test.toc
@@ -1,5 +1,8 @@
main @= fn() {
- foo @ int = fn() {foo();};
-
+ foo @ fn() = fn() {x : fn() = bar;};
+ bar : fn() = fn( ){};
+
+ foo();
+ bar();
}; \ No newline at end of file
diff --git a/types_cgen.c b/types_cgen.c
index 541f1b5..28db722 100644
--- a/types_cgen.c
+++ b/types_cgen.c
@@ -26,6 +26,8 @@ static bool cgen_types_expr(CGenerator *g, Expression *e) {
case EXPR_FN: {
if (e->fn.name && g->block == NULL) { /* write named function prototypes in global scope to header file */
g->writing_to = CGEN_WRITING_TO_H;
+ } else {
+ g->writing_to = CGEN_WRITING_TO_C;
}
if (!cgen_types_fn(g, &e->fn, e->where))
return false;