summaryrefslogtreecommitdiff
path: root/types.c
diff options
context:
space:
mode:
Diffstat (limited to 'types.c')
-rw-r--r--types.c36
1 files changed, 25 insertions, 11 deletions
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;