From 9952500a2786720dcdd4be96ff5a945c4d423ffb Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 10 Jan 2020 10:30:21 -0500 Subject: allow circular dependencies in structs --- cgen.c | 4 +--- eval.c | 12 ++++++++++-- main.c | 2 ++ parse.c | 16 +++++++++------- test.toc | 10 +++++++++- types.c | 6 ++++++ 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); -- cgit v1.2.3