diff options
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | test.toc | 8 | ||||
-rw-r--r-- | types.c | 15 | ||||
-rw-r--r-- | types.h | 1 |
5 files changed, 16 insertions, 12 deletions
@@ -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; @@ -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 @@ -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; -} /* @@ -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; @@ -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; |