summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c4
-rw-r--r--identifiers.c16
-rw-r--r--main.c2
-rw-r--r--parse.c12
-rw-r--r--test.toc8
-rw-r--r--types.c27
-rw-r--r--types.h3
7 files changed, 54 insertions, 18 deletions
diff --git a/cgen.c b/cgen.c
index fa1fa2a..80507ee 100644
--- a/cgen.c
+++ b/cgen.c
@@ -242,11 +242,11 @@ static void cgen_ident(CGenerator *g, Identifier i) {
cgen_write(g, "%s", g->nms_prefix);
} else {
/* do prefix for references to siblings */
- if (g->nms && i->scope == &g->nms->body) {
+ if (g->nms && ident_scope(i) == &g->nms->body) {
cgen_write(g, "%s", g->nms_prefix);
}
}
- if (i == g->main_ident && i->decl_kind == IDECL_DECL && i->scope == NULL) {
+ if (i == g->main_ident && i->decl_kind == IDECL_DECL && ident_scope(i) == NULL) {
/* don't conflict with C's main! */
cgen_write(g, "main__");
} else {
diff --git a/identifiers.c b/identifiers.c
index 1ad239a..60ab30e 100644
--- a/identifiers.c
+++ b/identifiers.c
@@ -27,9 +27,10 @@ static int is_ident(int c) {
}
/* Initialize Identifiers. */
-static void idents_create(Identifiers *ids, Allocator *allocr) {
+static void idents_create(Identifiers *ids, Allocator *allocr, Block *scope) {
str_hash_table_create(&ids->table, sizeof(IdentSlot) - sizeof(StrHashTableSlot), allocr);
ids->rseed = 0x27182818;
+ ids->scope = scope;
}
/* advances s until a non-identifier character is reached, then returns the number of characters advanced */
@@ -85,6 +86,7 @@ static Identifier ident_insert(Identifiers *ids, char **s) {
char *original = *s;
size_t len = ident_str_len_advance(s);
IdentSlot *slot = (IdentSlot *)str_hash_table_insert_(&ids->table, original, len);
+ slot->idents = ids;
return slot;
}
@@ -148,21 +150,25 @@ static Identifier ident_get(Identifiers *ids, char *s) {
}
/* translate and insert if not already there */
-static Identifier ident_translate_forced(Identifier i, Identifiers *to_idents) {
+static inline Identifier ident_translate_forced(Identifier i, Identifiers *to_idents) {
char *p = i->str;
return ident_insert(to_idents, &p);
}
/* translate but don't add it if it's not there */
-static Identifier ident_translate(Identifier i, Identifiers *to_idents) {
+static inline Identifier ident_translate(Identifier i, Identifiers *to_idents) {
return ident_get(to_idents, i->str);
}
/* returns true if i and j are equal, even if they're not in the same table */
-static bool ident_eq(Identifier i, Identifier j) {
+static inline bool ident_eq(Identifier i, Identifier j) {
return i->len == j->len && memcmp(i->str, j->str, i->len) == 0;
}
+static inline Block *ident_scope(Identifier i) {
+ return i->idents->scope;
+}
+
#ifdef TOC_DEBUG
static void idents_test(void) {
Identifiers ids;
@@ -170,7 +176,7 @@ static void idents_test(void) {
char *s = b;
Allocator a;
allocr_create(&a);
- idents_create(&ids, &a);
+ idents_create(&ids, &a, NULL);
Identifier i1 = ident_insert(&ids, &s);
assert(strs_equal(s, " bar"));
char b2[] = "foo_variable+6";
diff --git a/main.c b/main.c
index 6563a0d..4975b99 100644
--- a/main.c
+++ b/main.c
@@ -81,7 +81,7 @@ int main(int argc, char **argv) {
if (!contents) return EXIT_FAILURE;
Identifiers globals;
- idents_create(&globals, &main_allocr);
+ idents_create(&globals, &main_allocr, NULL);
Tokenizer t;
file.contents = contents;
tokr_create(&t, &err_ctx, &main_allocr);
diff --git a/parse.c b/parse.c
index db2dbec..0d4100d 100644
--- a/parse.c
+++ b/parse.c
@@ -784,7 +784,7 @@ static bool parse_block(Parser *p, Block *b) {
Block *prev_block = p->block;
b->flags = 0;
b->ret_expr = NULL;
- idents_create(&b->idents, p->allocr);
+ idents_create(&b->idents, p->allocr, p->block);
if (!token_is_kw(t->token, KW_LBRACE)) {
tokr_err(t, "Expected '{' to open block.");
return false;
@@ -957,7 +957,8 @@ static int op_precedence(Keyword op) {
static Identifier parser_ident_insert(Parser *p, char *str) {
Identifiers *idents = p->block ? &p->block->idents : p->globals;
- return ident_insert(idents, &str);
+ Identifier i = ident_insert(idents, &str);
+ return i;
}
static bool parse_expr(Parser *p, Expression *e, Token *end) {
@@ -1065,7 +1066,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
}
case KW_NMS: {
Namespace *n = &e->nms;
- idents_create(&n->idents, p->allocr);
+ idents_create(&n->idents, p->allocr, p->block);
e->kind = EXPR_NMS;
++t->token;
@@ -1836,6 +1837,11 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
goto ret_false;
}
*ident = parser_ident_insert(p, t->token->ident);
+ {
+ Identifier i = *ident;
+ i->decl_kind = IDECL_DECL;
+ i->decl = d;
+ }
++t->token;
if (token_is_kw(t->token, KW_COMMA)) {
++t->token;
diff --git a/test.toc b/test.toc
index b1aefcf..fa9a336 100644
--- a/test.toc
+++ b/test.toc
@@ -1,3 +1,4 @@
+/*
io ::= nms {
#include "std/io.toc";
};
@@ -17,3 +18,10 @@ main ::= fn() {
io.puti(b);
io.puti(c);
};
+*/
+
+x := 5;
+main ::= fn() {
+
+ x;
+}; \ No newline at end of file
diff --git a/types.c b/types.c
index 07d9cf8..0daf0ca 100644
--- a/types.c
+++ b/types.c
@@ -365,14 +365,24 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
return success;
}
-static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
+/* may modify ident */
+static bool type_of_ident(Typer *tr, Location where, Identifier *ident, Type *t) {
t->flags = 0;
+ Identifier i = *ident;
+ assert(i->idents->scope == tr->block);
+ if (i->decl_kind == IDECL_NONE) {
+ long nblocks = (long)arr_len(tr->blocks);
+ for (long idx = nblocks - 1; idx >= 0; --idx) {
+ int x;
+ }
+ }
+
switch (i->decl_kind) {
case IDECL_DECL: {
Declaration *d = i->decl;
bool captured = false;
- if (i->scope != NULL && !(i->scope->flags & BLOCK_IS_NMS)) {
- Block *decl_scope = i->scope;
+ if (ident_scope(i) != NULL && !(ident_scope(i)->flags & BLOCK_IS_NMS)) {
+ Block *decl_scope = ident_scope(i);
if (!(decl_scope->flags & BLOCK_IS_NMS)) {
/* go back through scopes */
for (Block **block = arr_last(tr->blocks); *block && *block != decl_scope; --block) {
@@ -433,7 +443,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
} else {
/* let's type the declaration, and redo this (for evaling future functions) */
if (!types_decl(tr, d)) return false;
- return type_of_ident(tr, where, i, t);
+ return type_of_ident(tr, where, ident, t);
}
return false;
}
@@ -1230,7 +1240,7 @@ static bool types_expr(Typer *tr, Expression *e) {
}
} break;
case EXPR_IDENT: {
- if (!type_of_ident(tr, e->where, e->ident, t)) return false;
+ if (!type_of_ident(tr, e->where, &e->ident, t)) return false;
} break;
case EXPR_CAST: {
CastExpr *c = &e->cast;
@@ -2087,9 +2097,11 @@ static bool types_expr(Typer *tr, Expression *e) {
err_print(rhs->where, "%s is not a member of this namespace.", s);
return false;
}
- if (!type_of_ident(tr, rhs->where, translated, t)) {
+ if (!type_of_ident(tr, rhs->where, &translated, t)) {
return false;
}
+ e->kind = EXPR_IDENT;
+ e->ident = translated;
} else {
char *s = type_to_str(lhs_type);
err_print(e->where, "Operator . applied to type %s, which is not a structure or pointer to structure.", s);
@@ -2159,8 +2171,10 @@ static bool types_expr(Typer *tr, Expression *e) {
}
static bool types_block(Typer *tr, Block *b) {
+ *(Block **)arr_add(&tr->blocks) = b;
if (b->flags & BLOCK_FOUND_TYPES)
return true;
+
bool success = true;
arr_foreach(b->stmts, Statement, s) {
if (!types_stmt(tr, s)) {
@@ -2193,6 +2207,7 @@ static bool types_block(Typer *tr, Block *b) {
}
ret:
+ arr_remove_last(&tr->blocks);
b->flags |= BLOCK_FOUND_TYPES;
return success;
}
diff --git a/types.h b/types.h
index 67c0645..f7b524a 100644
--- a/types.h
+++ b/types.h
@@ -187,7 +187,7 @@ typedef struct IdentSlot {
struct Declaration *decl;
struct Expression *expr; /* for example, this identifier is declared in a for expression */
};
- struct Block *scope; /* NULL for file scope */
+ struct Identifiers *idents;
Value val;
SOURCE_LOCATION
U16 flags;
@@ -215,6 +215,7 @@ typedef IdentSlot *IdentSlotPtr;
typedef struct Identifiers {
StrHashTable table;
U32 rseed;
+ struct Block *scope; /* NULL for file scope */
} Identifiers;
typedef enum {