summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-01-10 10:51:06 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-01-10 10:51:06 -0500
commite3ea08d51db496336ff99d9af2691363edcd8502 (patch)
treed6ee92c3d4bd2f917cdbb9cf1dc651d8a63e2317
parentf65fa40de3223ca12fa750d89e2db1f2e6dbba8d (diff)
problematic circular dependency tracker
-rw-r--r--test.toc5
-rw-r--r--types.c31
-rw-r--r--types.h2
3 files changed, 26 insertions, 12 deletions
diff --git a/test.toc b/test.toc
index 3170b55..1139416 100644
--- a/test.toc
+++ b/test.toc
@@ -16,7 +16,10 @@ putf ::= fn(x: float) {
// f: Foo;
// };
-Foo ::= struct { p: &Foo; };
+
+Bar ::= struct { f: &Foo; };
+
+Foo ::= struct { b: Bar; };
main ::= fn() {
f::=fn(t::Type)Type {t};
diff --git a/types.c b/types.c
index 5abba99..78aa183 100644
--- a/types.c
+++ b/types.c
@@ -414,7 +414,9 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
err_print(where, "Variables cannot be captured into inner functions (but constants can).");
return false;
}
- if ((d->flags & DECL_HAS_EXPR) && (d->expr.kind == EXPR_TYPE)) {
+ if (arr_len(tr->is_reference_stack)
+ && *(bool *)arr_last(tr->is_reference_stack)
+ && (d->flags & DECL_HAS_EXPR) && (d->expr.kind == EXPR_TYPE)) {
/* allow using a type before declaring it */
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_TYPE;
@@ -494,8 +496,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
return true;
}
-/* fixes the type (replaces [5+3]int with [8]int, etc.) */
-static bool type_resolve(Typer *tr, Type *t, Location where) {
+static bool type_resolve_(Typer *tr, Type *t, Location where, bool is_reference) {
Evaluator *ev = tr->evalr;
if (t->flags & TYPE_IS_RESOLVED) return true;
t->was_expr = NULL;
@@ -530,39 +531,41 @@ static bool type_resolve(Typer *tr, Type *t, Location where) {
size = val_to_u64(&val, n_expr->type.builtin);
}
t->arr.n = (U64)size;
- if (!type_resolve(tr, t->arr.of, where))
+ if (!type_resolve_(tr, t->arr.of, where, is_reference))
return false;
} break;
case TYPE_FN:
arr_foreach(t->fn.types, Type, child_type) {
- if (!type_resolve(tr, child_type, where))
+ if (!type_resolve_(tr, child_type, where, true))
return false;
}
break;
case TYPE_TUPLE:
arr_foreach(t->tuple, Type, child_type) {
- if (!type_resolve(tr, child_type, where))
+ if (!type_resolve_(tr, child_type, where, is_reference))
return false;
}
break;
case TYPE_PTR:
- if (!type_resolve(tr, t->ptr, where))
+ if (!type_resolve_(tr, t->ptr, where, true))
return false;
break;
case TYPE_SLICE:
- if (!type_resolve(tr, t->slice, where))
+ if (!type_resolve_(tr, t->slice, where, true))
return false;
break;
case TYPE_STRUCT:
arr_foreach(t->struc->fields, Field, f) {
- if (!type_resolve(tr, f->type, where))
+ if (!type_resolve_(tr, f->type, where, is_reference))
return false;
}
break;
case TYPE_EXPR: {
Value typeval;
- if (!types_expr(tr, t->expr))
- return false;
+ *(bool *)arr_add(&tr->is_reference_stack) = is_reference;
+ bool success = types_expr(tr, t->expr);
+ arr_remove_last(&tr->is_reference_stack);
+ if (!success) return false;
if (t->expr->type.kind == TYPE_UNKNOWN && tr->err_ctx->have_errored)
return false; /* silently fail (e.g. if a function couldn't be typed) */
if (!type_is_builtin(&t->expr->type, BUILTIN_TYPE)) {
@@ -586,6 +589,11 @@ static bool type_resolve(Typer *tr, Type *t, Location where) {
return true;
}
+/* fixes the type (replaces [5+3]int with [8]int, etc.) */
+static bool type_resolve(Typer *tr, Type *t, Location where) {
+ return type_resolve_(tr, t, where, false);
+}
+
static bool type_can_be_truthy(Type *t) {
@@ -2266,6 +2274,7 @@ static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *a
tr->pkg_name = NULL;
tr->allocr = allocr;
tr->idents = idents;
+ tr->is_reference_stack = NULL;
*(Block **)arr_adda(&tr->blocks, allocr) = NULL;
}
diff --git a/types.h b/types.h
index b69c525..513741b 100644
--- a/types.h
+++ b/types.h
@@ -777,6 +777,8 @@ typedef struct Typer {
FnExpr *fn; /* the function we're currently parsing. */
char *pkg_name;
ErrCtx *err_ctx;
+ /* for checking for problematic struct circular dependencies */
+ bool *is_reference_stack;
} Typer;
typedef struct Package {