From df10470f1f10f1f1f2f5cad792976de8d734bf27 Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum <pommicket@gmail.com>
Date: Tue, 27 Aug 2019 15:21:06 -0400
Subject: fixed functions

---
 base_cgen.c  | 40 +++++++++++++++++++++++-----------------
 cgen.c       | 52 +++++++++++++++++++++++++++-------------------------
 out.c        | 17 +++++++++++++++--
 out.h        |  3 +--
 test.toc     |  7 +++++--
 types_cgen.c |  2 ++
 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;
-- 
cgit v1.2.3