summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-01-10 10:30:21 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-01-10 10:30:21 -0500
commit9952500a2786720dcdd4be96ff5a945c4d423ffb (patch)
tree400fbda886b68997a5eac6d9174520cd1a06abc8
parentb9ee8f9f83b4ed8fac81a3b530732537c4495ea1 (diff)
allow circular dependencies in structs
-rw-r--r--cgen.c4
-rw-r--r--eval.c12
-rw-r--r--main.c2
-rw-r--r--parse.c16
-rw-r--r--test.toc10
-rw-r--r--types.c6
6 files changed, 37 insertions, 13 deletions
diff --git a/cgen.c b/cgen.c
index 9f16b8b..2131abd 100644
--- a/cgen.c
+++ b/cgen.c
@@ -158,9 +158,7 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d);
#define cgen_recurse_subtypes(f, g, type, extra) \
switch (type->kind) { \
case TYPE_STRUCT: \
- arr_foreach(type->struc->fields, Field, fl) \
- if (!f(g, fl->type, extra)) \
- return false; \
+ /* don't descend into fields */ \
break; \
case TYPE_FN: \
arr_foreach(type->fn.types, Type, sub) { \
diff --git a/eval.c b/eval.c
index 38fc316..e13c5ba 100644
--- a/eval.c
+++ b/eval.c
@@ -1320,8 +1320,16 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
Declaration *d = NULL;
if (is_decl) {
d = idecl->decl;
- if (!types_decl(ev->typer, d)) return false;
- assert(d->type.flags & TYPE_IS_RESOLVED);
+ if ((d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_TYPE && d->expr.typeval.kind == TYPE_STRUCT) {
+ v->type = allocr_malloc(ev->allocr, sizeof *v->type);
+ v->type->flags = TYPE_IS_RESOLVED;
+ v->type->kind = TYPE_STRUCT;
+ v->type->struc = d->expr.typeval.struc;
+ break;
+ } else {
+ if (!types_decl(ev->typer, d)) return false;
+ assert(d->type.flags & TYPE_IS_RESOLVED);
+ }
}
if (idecl->flags & IDECL_HAS_VAL) {
*v = idecl->val;
diff --git a/main.c b/main.c
index 0259f07..c329d27 100644
--- a/main.c
+++ b/main.c
@@ -18,6 +18,8 @@
/*
TODO:
+check for problematic circular dependencies
+test really long type names
packages
---
X ::= newtype(int); or something
diff --git a/parse.c b/parse.c
index bb3bf5e..3265f7d 100644
--- a/parse.c
+++ b/parse.c
@@ -228,13 +228,15 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) {
return written;
}
case TYPE_STRUCT: {
- size_t written = str_copy(buffer, bufsize, "struct { ");
- arr_foreach(t->struc->fields, Field, f) {
- written += type_to_str_(f->type, buffer + written, bufsize - written);
- written += str_copy(buffer + written, bufsize - written, "; ");
- }
- written += str_copy(buffer + written, bufsize - written, " }");
- return written;
+ /* size_t written = str_copy(buffer, bufsize, "struct { "); */
+ /* arr_foreach(t->struc->fields, Field, f) { */
+ /* written += type_to_str_(f->type, buffer + written, bufsize - written); */
+ /* written += str_copy(buffer + written, bufsize - written, "; "); */
+ /* } */
+ /* written += str_copy(buffer + written, bufsize - written, " }"); */
+ /* TODO: show name or something (to allow circular dependencies)? */
+ return str_copy(buffer, bufsize, "struct { ... }");
+
}
case TYPE_ARR: {
size_t written = str_copy(buffer, bufsize, "[");
diff --git a/test.toc b/test.toc
index fc5dd32..2855bb1 100644
--- a/test.toc
+++ b/test.toc
@@ -6,7 +6,15 @@ putf ::= fn(x: float) {
#C("printf(\"%f\\n\", (double)x);
");
};
-point ::= pkg "point";
+// point ::= pkg "point";
+
+Foo ::= struct {
+ b: &Bar;
+};
+
+Bar ::= struct {
+ f: &Foo;
+};
main ::= fn() {
f::=fn(t::Type)Type {t};
diff --git a/types.c b/types.c
index e2a544c..2de05c0 100644
--- a/types.c
+++ b/types.c
@@ -441,6 +441,12 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
/* allow using a function before declaring it */
if (!type_of_fn(tr, d->expr.fn, t, 0)) return false;
return true;
+ } else if ((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;
+ t->flags = TYPE_IS_RESOLVED;
+ return true;
} else {
if (where.start <= d->where.end) {
char *s = ident_to_str(i);