summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-07-15 17:06:01 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-07-15 17:06:01 -0400
commit0cf4c0567399f597e2d3a5a9e0612c7ce69d9992 (patch)
tree912814e5d71e67a52612960ffd7f6204edd3835d
parentd7d3e9ed8a6f6c2a116fb82ac3c891d3cae0a482 (diff)
only allow using a struct after its declared (except for inside other structs)HEADtrunk
-rw-r--r--eval.c3
-rw-r--r--main.c1
-rw-r--r--test.toc8
-rw-r--r--types.c15
-rw-r--r--types.h1
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;