summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-04-04 18:58:21 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-04-04 18:58:21 -0400
commitaa8ae1c36663709befeff5693d5d6c0b2bcc450f (patch)
tree347efd02ffbf9f2936dbba0bde1554077d2220e6
parent149f2e9fa65a77be9021f5197c21d8fd70102984 (diff)
improved the way ident lookup works
-rw-r--r--main.c1
-rw-r--r--test.toc17
-rw-r--r--types.c117
3 files changed, 67 insertions, 68 deletions
diff --git a/main.c b/main.c
index e636f16..4244664 100644
--- a/main.c
+++ b/main.c
@@ -9,7 +9,6 @@
/*
TODO:
use
- - note: just keep an array of useds on the block
- use with a decl, e.g. use p : Point;
- make sure use works with functions and for, e.g. for use p := points
- exceptions (so that if you accidentally use something but have a function with the same
diff --git a/test.toc b/test.toc
index 4c54b2c..a1c28b1 100644
--- a/test.toc
+++ b/test.toc
@@ -1,11 +1,16 @@
+/*
#include "std/io.toc";
+*/
+Point ::= struct {
+ x, y: int;
+}
-x ::= 3;
-
+f ::= fn() p: Point {
+ p.x = 13;
+}
main ::= fn() {
- p ::= nms {
- y := 5;
- }
- puti(p["y"]);
+ p := f();
+ use p;
}
+
diff --git a/types.c b/types.c
index 782e31e..c75356f 100644
--- a/types.c
+++ b/types.c
@@ -583,64 +583,11 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
return success;
}
-/* may modify ident */
-enum {
- TYPE_OF_IDENT_BLOCK_IS_CORRECT = 0x01 /* *ident is already from the right block (it doesn't need translation) */
-};
-static Status type_of_ident(Typer *tr, Location where, Identifier *ident, Type *t, U16 flags) {
- t->flags = 0;
- Identifier i = *ident;
- Block *b = tr->block;
- bool undeclared = true;
- if (flags & TYPE_OF_IDENT_BLOCK_IS_CORRECT) {
- undeclared = !ident_is_declared(*ident);
- } else {
- while (1) { /* for each block we are inside... */
- /* OPTIM: only hash once */
- Identifier translated = ident_translate(i, b ? &b->idents : tr->globals);
- if (ident_is_declared(translated)) {
-#if 0
- printf("translated %s from\n", ident_to_str(i));
- print_block_location(i->idents->body);
- printf(" to \n");
- print_block_location(translated->idents->body);
-#endif
- i = *ident = translated;
- undeclared = false;
- }
- Use **uses = b ? b->uses : tr->uses;
-
- Use *previous_use_which_uses_i = NULL;
- (void)previous_use_which_uses_i;
- arr_foreach(uses, UsePtr, usep) {
- Use *use = *usep;
- Expression *e = &use->expr;
- if (type_is_builtin(&e->type, BUILTIN_NMS)) {
-
- } else {
- /* it's a struct */
- Type *struct_type = &e->type;
- if (struct_type->kind == TYPE_PTR)
- struct_type = struct_type->ptr;
- assert(struct_type->kind == TYPE_STRUCT);
- }
- }
- if (!undeclared) break;
- if (b) {
- b = b->parent;
- } else {
- break;
- }
- }
- }
- if (undeclared) {
- char *s = ident_to_str(i);
- err_print(where, "Undeclared identifier: %s", s);
- free(s);
- return false;
- }
+/* doesn't do any translation on ident or anything, so make sure it's in the right scope */
+static Status type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
switch (i->decl_kind) {
- case IDECL_DECL: {
+ case IDECL_DECL:
+ top: {
Declaration *d = i->decl;
/* check for trying to capture a variable into a function */
bool captured = false;
@@ -713,7 +660,7 @@ static Status type_of_ident(Typer *tr, Location where, Identifier *ident, Type *
}
/* 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, ident, t, flags);
+ goto top;
}
}
}
@@ -1839,7 +1786,55 @@ static Status types_expr(Typer *tr, Expression *e) {
return false;
};
case EXPR_IDENT: {
- if (!type_of_ident(tr, e->where, &e->ident, t, 0)) return false;
+ Block *b = tr->block;
+ Identifier i = e->ident;
+ bool undeclared = true;
+ while (1) { /* for each block we are inside... */
+ /* OPTIM: only hash once */
+ Identifier translated = ident_translate(i, b ? &b->idents : tr->globals);
+ if (ident_is_declared(translated)) {
+#if 0
+ printf("translated %s from\n", ident_to_str(i));
+ print_block_location(i->idents->body);
+ printf(" to \n");
+ print_block_location(translated->idents->body);
+#endif
+ i = e->ident = translated;
+ undeclared = false;
+ }
+ Use **uses = b ? b->uses : tr->uses;
+
+ Use *previous_use_which_uses_i = NULL;
+ (void)previous_use_which_uses_i;
+ arr_foreach(uses, UsePtr, usep) {
+ Use *use = *usep;
+ Expression *used = &use->expr;
+ if (type_is_builtin(&used->type, BUILTIN_NMS)) {
+
+ } else {
+ /* it's a struct */
+ Type *struct_type = &used->type;
+ if (struct_type->kind == TYPE_PTR)
+ struct_type = struct_type->ptr;
+ assert(struct_type->kind == TYPE_STRUCT);
+ }
+ }
+ if (!undeclared) break;
+ if (b) {
+ b = b->parent;
+ } else {
+ break;
+ }
+ }
+ if (undeclared) {
+ char *s = ident_to_str(e->ident);
+ err_print(e->where, "Undeclared identifier \"%s\".", s);
+ free(s);
+ return false;
+ }
+ if (!type_of_ident(tr, e->where, e->ident, t)) {
+ return false;
+ }
} break;
case EXPR_CAST: {
CastExpr *c = &e->cast;
@@ -2939,7 +2934,7 @@ static Status types_expr(Typer *tr, Expression *e) {
free(s);
return false;
}
- if (!type_of_ident(tr, rhs->where, &e->binary.rhs->ident, t, TYPE_OF_IDENT_BLOCK_IS_CORRECT)) {
+ if (!type_of_ident(tr, rhs->where, e->binary.rhs->ident, t)) {
return false;
}
break;
@@ -3074,7 +3069,7 @@ static Status types_expr(Typer *tr, Expression *e) {
free(s);
return false;
}
- if (!type_of_ident(tr, rhs->where, &rhs->ident, t, TYPE_OF_IDENT_BLOCK_IS_CORRECT)) {
+ if (!type_of_ident(tr, rhs->where, rhs->ident, t)) {
return false;
}
} else {