harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

commit f84e891ddd0cbdc6471ef97300e3a27960bf1152
parent 5ea0e291896fa9cf6b67af8c5089ada284f47b8c
Author: Bor Grošelj Simić <bgs@turminal.net>
Date:   Sat, 21 May 2022 03:03:07 +0200

handle circular dependencies in enums

Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>

Diffstat:
Msrc/check.c | 22+++++++++++++---------
Mtests/15-enums.ha | 14++++++++++++++
2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -3685,9 +3685,21 @@ scan_decl_finish(struct context *ctx, const struct scope_object *obj, // load this declaration's subunit context ctx->unit->parent = idecl->imports; + // resolving a declaration that is already in progress -> cycle + if (idecl->in_progress) { + struct location *loc; + if (idecl->type == IDECL_ENUM_FLD) { + loc = &idecl->field->type->loc; + } else { + loc = &idecl->decl.loc; + } + expect(loc, false, "Circular dependency for '%s'\n", + identifier_unparse(&idecl->obj.ident)); + } + idecl->in_progress = true; + switch (idecl->type) { case IDECL_ENUM_FLD: - // TODO handle circular enum dependencies obj = scan_enum_field(ctx, idecl); goto exit; case IDECL_ENUM_TYPE: @@ -3697,14 +3709,6 @@ scan_decl_finish(struct context *ctx, const struct scope_object *obj, break; } - // resolving a declaration that is already in progress -> cycle - if (idecl->in_progress) { - expect(&idecl->decl.loc, false, - "Circular dependency for '%s'\n", - identifier_unparse(&idecl->obj.ident)); - } - idecl->in_progress = true; - switch (idecl->decl.decl_type) { case AST_DECL_CONST: obj = scan_const(ctx, &idecl->decl.constant); diff --git a/tests/15-enums.ha b/tests/15-enums.ha @@ -60,8 +60,22 @@ fn storage() void = { }; fn reject() void = { + // enum type definition used outside type declaration assert(rt::compile("export let a: enum { A, B } = 0;") != 0); assert(rt::compile("export let a: int = 0: enum{A, B}: int;") != 0); + + // enum circular dependencies + assert(rt::compile("type a = enum { A = B, B = A };") != 0); + assert(rt::compile("type a = enum { A = b::B }, + b = enum { B = a::A };") != 0); + assert(rt::compile(" + def a: int = e::VAL1; + type e = enum { VAL1 = a }; + ") != 0); + assert(rt::compile(" + def a: int = e::VAL1; + type e = enum { VAL1 = VAL2, VAL2 = a }; + ") != 0); }; type interdependent1 = enum {