From 3605284a46ae8b0f43b441d1d3d4bbbdbe2e40f3 Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum <pommicket@gmail.com>
Date: Tue, 23 Jun 2020 20:00:15 -0400
Subject: fixed some problems with globals

---
 main.c   |  3 +--
 test.toc | 10 ++++------
 types.c  | 36 +++++++++++++++++++++++++-----------
 3 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/main.c b/main.c
index cd61f6d..e54659d 100644
--- a/main.c
+++ b/main.c
@@ -8,8 +8,7 @@
 
 /* 
 @TODO:
-i think what we need to do is put all of the standalone statements (like main();) and all of the constant decls into an array,
-	and iterate over all of them after everything is typed, and after all the initializations are run.
+#includes during parsing
 initialization statements (maybe #init(-50), where -50 is the priority and <0 is reserved for standard library)
 if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared)
 improve type_to_str:
diff --git a/test.toc b/test.toc
index 532cc56..438efc3 100644
--- a/test.toc
+++ b/test.toc
@@ -1,21 +1,19 @@
-init(3);
 
 #include "tests/std/io.toc";
 
-/*
 #init(-50) init(1);
 #init(30) init(2);
 #init(-7) init(3);
 #init(-42) init(4);
-*/
 
-x: int;
 init ::= fn(a: int) {
-	writes("Initializing... #");
-	writei(a);
+	//writes("Initializing... #");
+	//writei(a);
 	x = 5;
 }
 
+x: int;
+
 main ::= fn() {
 	writes("Main's value of x is: ");
 	puti(x);
diff --git a/types.c b/types.c
index c30e9df..1ceec1b 100644
--- a/types.c
+++ b/types.c
@@ -36,6 +36,17 @@ static inline void typer_block_enter(Typer *tr, Block *b) {
 	tr->block = b;
 }
 
+static inline bool block_is_at_top_level(Block *b) {
+	for (Block *bb = b; bb; bb = bb->parent)
+		if (bb->kind != BLOCK_NMS)
+			return false;
+	return true;
+}
+
+static bool is_at_top_level(Typer *tr) {
+	return block_is_at_top_level(tr->block);
+}
+
 static size_t compiler_sizeof_builtin(BuiltinType b) {
 	switch (b) {
 	case BUILTIN_I8: return sizeof(I8);
@@ -834,9 +845,21 @@ top:;
 				free(s);
 				return false;
 			}
-			if ((d->flags & DECL_IS_CONST) && (tr->block == NULL)) {
-				/* let's type the declaration, and redo this (for evaling future constants) */
+			Block *decl_block = i->idents->scope;
+			if (block_is_at_top_level(decl_block)) {
+				/* 
+					let's type the declaration, and redo this (for calling future functions at compile time)
+					this makes sure the error is right for:
+					foo();
+					bar : int;
+					foo ::= fn() { bar = 6; }
+					(it should be that you can't access non-constant bar at compile time, not that you're using before declaring)
+					This isn't needed if bar's block is non-NULL because functions can't capture variables
+				*/
+				Block *prev_block = tr->block;
+				tr->block = decl_block;
 				if (!types_decl(tr, d)) return false;
+				tr->block = prev_block;
 				goto top;
 			} else {
 				char *s = ident_to_str(i);
@@ -2982,15 +3005,6 @@ static Status types_block(Typer *tr, Block *b) {
 	return success;
 }
 
-static bool is_at_top_level(Typer *tr) {
-	for (Block *b = tr->block; b; b = b->parent) {
-		if (b && b->kind != BLOCK_NMS) {
-			return false;
-		}
-	}
-	return true;
-}
-
 static Status types_decl(Typer *tr, Declaration *d) {
 	Type *dtype = &d->type;
 	if (d->flags & DECL_FOUND_TYPE) return true;
-- 
cgit v1.2.3