From 0cf4c0567399f597e2d3a5a9e0612c7ce69d9992 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Wed, 15 Jul 2020 17:06:01 -0400 Subject: only allow using a struct after its declared (except for inside other structs) --- eval.c | 3 ++- main.c | 1 - test.toc | 8 ++++---- types.c | 15 +++++++++------ types.h | 1 + 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/eval.c b/eval.c index f91ef0b..61f9512 100644 --- a/eval.c +++ b/eval.c @@ -10,6 +10,7 @@ static Value get_builtin_val(GlobalCtx *gctx, BuiltinVal val); static void evalr_create(Evaluator *ev, Typer *tr, Allocator *allocr) { ev->returning = NULL; + ev->evaluating_struct_member_type = false; ev->typer = tr; ev->allocr = allocr; ev->to_free = NULL; @@ -1020,7 +1021,7 @@ static Status eval_ident(Evaluator *ev, Identifier ident, Value *v, Location whe return false; } Declaration *d = ident->decl; - if ((d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_TYPE && d->expr.typeval->kind == TYPE_STRUCT) { + if (ev->evaluating_struct_member_type && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_TYPE && d->expr.typeval->kind == TYPE_STRUCT) { // necessary for circularly-dependent structs v->type = allocr_malloc(ev->allocr, sizeof *v->type); v->type->flags = TYPE_IS_RESOLVED; diff --git a/main.c b/main.c index 8c9edb0..7455951 100644 --- a/main.c +++ b/main.c @@ -8,7 +8,6 @@ see development.md for development information @TODO: -fix problem with a : b; #include "file_which_defines_X"; b ::= struct { a: X; } see note in types.c : we probably shouldn't go to the trouble of evaluating this (just do this stuff if it's an ident) ensure that in s[a:b] s is an l-value if it's an array make sure you can't pass a function template or a tuple to varargs diff --git a/test.toc b/test.toc index a47bab6..d4064de 100644 --- a/test.toc +++ b/test.toc @@ -1,12 +1,12 @@ +#include "std/io.toc"; +a ::= struct { + foo: File; +} main ::= fn() { x: &a; k := x.foo; } main(); -#include "std/io.toc"; -a ::= struct { - foo: File; -} /* diff --git a/types.c b/types.c index a4e41d3..3412801 100644 --- a/types.c +++ b/types.c @@ -302,13 +302,18 @@ static size_t compiler_sizeof(Type *t) { static Status struct_resolve(Typer *tr, StructDef *s) { if (s->flags & STRUCT_DEF_RESOLVING_FAILED) return false; // silently fail; do not try to resolve again, because there'll be duplicate errors + if (s->flags & STRUCT_DEF_RESOLVING) + return true; // silently succeed; this is so that circularly dependent structs work. if (!(s->flags & STRUCT_DEF_RESOLVED)) { s->flags |= STRUCT_DEF_RESOLVING; typer_arr_add(tr, tr->all_structs, s); { // resolving stuff Block *body = &s->body; - if (!types_block(tr, body)) - goto fail; + tr->evalr->evaluating_struct_member_type = true; + bool success = types_block(tr, body); + tr->evalr->evaluating_struct_member_type = false; + + if (!success) goto fail; s->fields = NULL; Statement *stmts = body->stmts; if (!struct_add_stmts(tr, s, stmts)) @@ -2912,10 +2917,8 @@ static Status types_expr(Typer *tr, Expression *e) { err_print(e->where, "You can't access the '_member_names' type information from a struct template."); return false; } - if (!(struc->flags & STRUCT_DEF_RESOLVED)) { - if (!struct_resolve(tr, struc)) - return false; - } + if (!struct_resolve(tr, struc)) + return false; t->kind = TYPE_SLICE; t->flags = TYPE_IS_RESOLVED; diff --git a/types.h b/types.h index 9028624..a0ef8f9 100644 --- a/types.h +++ b/types.h @@ -1047,6 +1047,7 @@ typedef struct Evaluator { Declaration **decls_given_values; // array of declarations whose last value in their val stacks should be removed when the block is exited Value ret_val; ForeignFnManager ffmgr; + bool evaluating_struct_member_type; // we only allow references to future structs if it's within another struct (so that circularly dependent structs can exist). hence, this keeps track of if we're evaluating the type of a declaration inside a struct. } Evaluator; -- cgit v1.2.3