From 429eeee4d194820890bcbd6010765f9f7eccb21e Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum <pommicket@gmail.com>
Date: Fri, 20 Mar 2020 11:48:32 -0400
Subject: compile time defer

---
 cgen.c               |  2 +-
 eval.c               |  9 ++++++++-
 main.c               |  1 +
 test.toc             | 34 ++++++++++++++++------------------
 tests/defer.toc      |  8 ++++----
 tests/defer_expected |  4 ++++
 6 files changed, 34 insertions(+), 24 deletions(-)

diff --git a/cgen.c b/cgen.c
index 2a469ea..5b430fc 100644
--- a/cgen.c
+++ b/cgen.c
@@ -673,7 +673,7 @@ static void cgen_fn_header(CGenerator *g, FnExpr *f, U64 which_are_const) {
 }
 
 static inline void cgen_deferred_from_block(CGenerator *g, Block *from) {
-	arr_foreach_reversed(from->deferred, StatementPtr, s) {
+	arr_foreach(from->deferred, StatementPtr, s) {
 		cgen_stmt(g, *s);
 	}
 }
diff --git a/eval.c b/eval.c
index 4dfb618..b4f1008 100644
--- a/eval.c
+++ b/eval.c
@@ -1708,7 +1708,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
 	case STMT_MESSAGE:
 		break;
 	case STMT_DEFER:
-		/* TODO */
+		*(Statement **)arr_add(&ev->typer->block->deferred) = stmt->defer;
 		break;
 	}
 	return true;
@@ -1717,6 +1717,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
 static Status eval_block(Evaluator *ev, Block *b, Value *v) {
 	Block *prev = ev->typer->block;
 	ev->typer->block = b;
+	b->deferred = NULL;
 	bool success = true;
 	Statement *last_reached = arr_last(b->stmts);
 	arr_foreach(b->stmts, Statement, stmt) {
@@ -1749,6 +1750,12 @@ static Status eval_block(Evaluator *ev, Block *b, Value *v) {
 			}
 		}
 	}
+	arr_foreach(b->deferred, StatementPtr, stmtp) {
+		Statement *stmt = *stmtp;
+		if (!eval_stmt(ev, stmt))
+			return false;
+	}
+	arr_clear(&b->deferred);
 	eval_exit_stmts(b->stmts, last_reached);
  ret:
 	ev->typer->block = prev;
diff --git a/main.c b/main.c
index e06e818..98daee8 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,7 @@
 
 /* 
 TODO:
+compile time defer
 use
  - use with a decl, e.g. use p : Point;
 &&, ||
diff --git a/test.toc b/test.toc
index b1d5e06..058d589 100644
--- a/test.toc
+++ b/test.toc
@@ -1,24 +1,22 @@
 #include "std/io.toc", io;
 
 
-s ::= struct (t :: Type, hasz ::= true) {
-	x, y: t;
-	#if hasz {
-		z: t;
-		a :: t = 3 as t;
-	}
-}
-
 main ::= fn() {
-	p: s(float);
-	p.x = 7;
-	p.y = 13;
-	p.z = 12;
-	io.puti(p.x as int);
-	io.puti(s(int).a as int);
-	q: s(int, false);
-	q.x = 13;
-	io.puti(q.x);
-	//io.puti(q.a);
+	defer io.puts("deferred from main");
+	for i := 0..10 {
+		defer io.puti(i);
+		if i == 7 {
+			defer io.puts("break!!!");
+			break;
+		}
+		if i % 2 == 0 {
+			defer io.puts("continue!!!");
+			continue;
+		}
+		io.puts("number...");
+	}
+	return;
+	io.puts("end of main");
 }
+main();
 
diff --git a/tests/defer.toc b/tests/defer.toc
index 6c2a304..578668d 100644
--- a/tests/defer.toc
+++ b/tests/defer.toc
@@ -26,10 +26,10 @@ main ::= fn() {
 	io.puti(same(3));
 	a, b := thing1();
 	c, d := thing2();
-	io.puti(a);
-	io.puti(b);
-	io.puti(c);
-	io.puti(d);
+	e, f ::= thing1();
+	g, h ::= thing2();
+	io.puti(a); io.puti(b); io.puti(c); io.puti(d);
+	io.puti(e); io.puti(f); io.puti(g); io.puti(h);
 	defer io.puts("deferred from main()");
 	for i := 1..10 {
 		defer io.puts("deferred from for");
diff --git a/tests/defer_expected b/tests/defer_expected
index e678115..1c13a6d 100644
--- a/tests/defer_expected
+++ b/tests/defer_expected
@@ -4,6 +4,10 @@
 6
 6
 6
+5
+6
+6
+6
 1
 deferred from for
 2
-- 
cgit v1.2.3