harec

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

commit 8fcadc2d6e54c377ca8e816c36b60ec5f3a64709
parent fcb4b5f352c01905cca5075de822e4f28a6b7e33
Author: Bor Grošelj Simić <bgs@turminal.net>
Date:   Thu,  2 Jun 2022 00:33:45 +0200

complete enum types immediately

Enums never have any dependencies, so resolving them immediately upon
encounter is safe. This simplifies a bunch of things because there is no
need to handle the incomplete enum case everywhere.

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

Diffstat:
Minclude/check.h | 9++-------
Minclude/type_store.h | 3+++
Msrc/check.c | 79++++++++++++++++++++++++++++++++++---------------------------------------------
Msrc/type_store.c | 39++++++++++++++++++++++++---------------
4 files changed, 63 insertions(+), 67 deletions(-)

diff --git a/include/check.h b/include/check.h @@ -105,14 +105,13 @@ struct unit { enum idecl_type { IDECL_DECL, - IDECL_ENUM_TYPE, IDECL_ENUM_FLD, }; // Keeps track of enum specific context required for enum field resolution struct incomplete_enum_field { struct ast_enum_field *field; - struct ast_type *type; + const struct type *type; struct scope *enum_scope; }; @@ -124,11 +123,7 @@ struct incomplete_declaration { enum idecl_type type; bool in_progress; union { - struct { - struct ast_decl decl; - struct scope *enum_values; - struct identifiers *enum_aliases; - }; + struct ast_decl decl; struct incomplete_enum_field *field; }; }; diff --git a/include/type_store.h b/include/type_store.h @@ -58,4 +58,7 @@ const struct type *type_store_tagged_to_union( const struct type *type_store_lookup_tuple(struct type_store *store, struct type_tuple *values, struct location loc); +const struct type *type_store_lookup_enum(struct type_store *store, + const struct ast_type *atype, bool exported); + #endif diff --git a/src/check.c b/src/check.c @@ -3184,11 +3184,12 @@ check_type(struct context *ctx, decl->ident = adecl->ident; } decl->type = DECL_TYPE; - const struct type *type = - type_store_lookup_atype(ctx->store, adecl->type); if (adecl->type->storage == STORAGE_ENUM) { - decl->_type = type; + decl->_type = + type_store_lookup_enum(ctx->store, adecl->type, exported); } else { + const struct type *type = + type_store_lookup_atype(ctx->store, adecl->type); struct type _alias = { .storage = STORAGE_ALIAS, .alias = { @@ -3297,7 +3298,7 @@ incomplete_declaration_create(struct context *ctx, struct location loc, static void incomplete_enum_field_create(struct context *ctx, struct scope *imports, - struct scope *enum_scope, struct ast_type *etype, + struct scope *enum_scope, const struct type *etype, struct ast_enum_field *f) { // We have to process the last field first @@ -3320,27 +3321,27 @@ incomplete_enum_field_create(struct context *ctx, struct scope *imports, .name = strdup(f->name), }; struct identifier name_ns = { - .name = etype->alias.name, - .ns = etype->alias.ns, + .name = etype->alias.name.name, + .ns = etype->alias.name.ns, }; struct identifier name = { .name = strdup(f->name), .ns = &name_ns, }; struct incomplete_declaration *fld = - incomplete_declaration_create(ctx, etype->loc, enum_scope, + incomplete_declaration_create(ctx, f->loc, enum_scope, &name, &localname); fld->type = IDECL_ENUM_FLD; fld->imports = imports; fld->field = field; struct identifier _ident = {0}; - mkident(ctx, &_ident, &etype->alias); + mkident(ctx, &_ident, &etype->alias.name); struct identifier ident = { .name = strdup(f->name), .ns = &_ident, }; - fld = incomplete_declaration_create(ctx, etype->loc, ctx->scope, + fld = incomplete_declaration_create(ctx, f->loc, ctx->scope, &ident, &name); fld->type = IDECL_ENUM_FLD, fld->imports = imports, @@ -3365,10 +3366,17 @@ incomplete_types_create(struct context *ctx, struct scope *imp, struct ast_decl }; idecl->imports = imp; if (t->type->storage == STORAGE_ENUM) { - scope_push(&idecl->enum_values, SCOPE_ENUM); - incomplete_enum_field_create(ctx, imp, idecl->enum_values, - t->type, t->type->_enum.values); - idecl->type = IDECL_ENUM_TYPE; + bool exported = idecl->decl.exported; + const struct type *type = type_store_lookup_enum( + ctx->store, t->type, exported); + if (type->storage == STORAGE_VOID) { + return; // error occured + } + scope_push((struct scope **)&type->_enum.values, SCOPE_ENUM); + incomplete_enum_field_create(ctx, imp, + type->_enum.values, type, t->type->_enum.values); + scope_insert(ctx->scope, O_TYPE, &with_ns, + &t->ident, type, NULL); } else { idecl->type = IDECL_DECL; } @@ -3490,8 +3498,7 @@ resolve_enum_field(struct context *ctx, const struct scope_object *obj) assert(ctx->resolving_enum == NULL); assert(idecl->type == IDECL_ENUM_FLD); - const struct type *type = - type_store_lookup_atype(ctx->store, idecl->field->type); + const struct type *type = idecl->field->type; struct identifier nsident, nsname, localname = { .name = idecl->obj.ident.name @@ -3522,9 +3529,11 @@ resolve_enum_field(struct context *ctx, const struct scope_object *obj) return obj; } + idecl = (struct incomplete_declaration *)obj; + assert(idecl->type == IDECL_ENUM_FLD); + ctx->resolving_enum = idecl->field->enum_scope; - struct expression *value = - xcalloc(1, sizeof(struct expression)); + struct expression *value = xcalloc(1, sizeof(struct expression)); value->result = type; if (idecl->field->field->value) { // explicit value struct expression *initializer = @@ -3587,9 +3596,6 @@ resolve_enum_field(struct context *ctx, const struct scope_object *obj) return scope_insert(idecl->field->enum_scope, O_CONST, &name, &localname, type, value); } -static const struct scope_object * -resolve_enum_type(struct context *ctx, const struct scope_object *obj); - const struct scope_object * resolve_enum_alias(struct context *ctx, const struct scope_object *obj) { @@ -3602,10 +3608,6 @@ resolve_enum_alias(struct context *ctx, const struct scope_object *obj) switch (idecl->type) { case IDECL_ENUM_FLD: return NULL; - case IDECL_ENUM_TYPE: - // XXX: does this need to be wrapped? - obj = resolve_enum_type(ctx, obj); - return obj; case IDECL_DECL: if (idecl->decl.decl_type != AST_DECL_TYPE) { return NULL; @@ -3673,21 +3675,6 @@ resolve_enum_alias(struct context *ctx, const struct scope_object *obj) return obj; } -static const struct scope_object * -resolve_enum_type(struct context *ctx, const struct scope_object *obj) -{ - struct incomplete_declaration *idecl = (struct incomplete_declaration*)obj; - assert(idecl->type == IDECL_ENUM_TYPE); - struct type *type = (struct type *)type_store_lookup_atype(ctx->store, - idecl->decl.type.type); - type->_enum.values = idecl->enum_values; - type->_enum.aliases = idecl->enum_aliases; - type->alias.exported = idecl->decl.exported; - type_store_lookup_alias(ctx->store, type); - return scope_insert(ctx->scope, O_TYPE, - &idecl->obj.ident, &idecl->obj.name, type, NULL); -} - const struct scope_object * resolve_dimensions(struct context *ctx, const struct scope_object *obj) { @@ -3705,10 +3692,11 @@ resolve_dimensions(struct context *ctx, const struct scope_object *obj) const struct scope_object * resolve_type(struct context *ctx, const struct scope_object *obj) { - struct incomplete_declaration *idecl = (struct incomplete_declaration*)obj; - if (idecl->type == IDECL_ENUM_TYPE) { - return resolve_enum_type(ctx, obj); + if (obj->otype != O_SCAN) { + assert(obj->otype == O_TYPE); + return obj; } + struct incomplete_declaration *idecl = (struct incomplete_declaration*)obj; if (idecl->type != IDECL_DECL || idecl->decl.decl_type != AST_DECL_TYPE) { struct location loc; if (idecl->type == IDECL_ENUM_FLD) { @@ -3825,8 +3813,6 @@ resolve_decl(struct context *ctx, const struct scope_object *obj) switch (idecl->type) { case IDECL_ENUM_FLD: return resolve_enum_field(ctx, obj); - case IDECL_ENUM_TYPE: - return resolve_enum_type(ctx, obj); case IDECL_DECL: break; } @@ -4111,7 +4097,10 @@ check_internal(struct type_store *ts, // Perform actual declaration resolution ctx.resolving_enum = NULL; for (const struct scope_object *obj = ctx.scope->objects; - obj && obj->otype == O_SCAN; obj = obj->lnext) { + obj; obj = obj->lnext) { + if (obj->otype != O_SCAN) { + continue; + } wrap_resolver(&ctx, obj, resolve_decl); assert(ctx.resolving_enum == NULL); } diff --git a/src/type_store.c b/src/type_store.c @@ -608,6 +608,7 @@ type_init_from_atype(struct type_store *store, case STORAGE_FCONST: case STORAGE_ICONST: case STORAGE_RCONST: + case STORAGE_ENUM: assert(0); // Invariant case STORAGE_BOOL: case STORAGE_CHAR: @@ -704,21 +705,6 @@ type_init_from_atype(struct type_store *store, type->size = memb.size * type->array.length; } break; - case STORAGE_ENUM: - mkident(store->check_context, &type->alias.ident, &atype->alias); - identifier_dup(&type->alias.name, &atype->alias); - type->alias.type = - builtin_type_for_storage(atype->_enum.storage, false); - if (!type_is_integer(type->alias.type) - && type->alias.type->storage != STORAGE_RUNE) { - error(store->check_context, atype->loc, - "Enum storage must be an integer or rune"); - *type = builtin_type_void; - return (struct dimensions){0}; - } - type->size = type->alias.type->size; - type->align = type->alias.type->size; - break; case STORAGE_FUNCTION: type->size = SIZE_UNDEFINED; type->align = ALIGN_UNDEFINED; @@ -1066,6 +1052,29 @@ type_store_lookup_tuple(struct type_store *store, struct type_tuple *values, return type_store_lookup_type(store, &type); } +const struct type * +type_store_lookup_enum(struct type_store *store, const struct ast_type *atype, + bool exported) +{ + struct type type = {0}; + type.storage = STORAGE_ENUM; + type.flags = atype->flags; + mkident(store->check_context, &type.alias.ident, &atype->alias); + identifier_dup(&type.alias.name, &atype->alias); + type.alias.exported = exported; + type.alias.type = + builtin_type_for_storage(atype->_enum.storage, false); + if (!type_is_integer(type.alias.type) + && type.alias.type->storage != STORAGE_RUNE) { + error(store->check_context, atype->loc, + "Enum storage must be an integer or rune"); + return &builtin_type_void; + } + type.size = type.alias.type->size; + type.align = type.alias.type->size; + return type_store_lookup_type(store, &type); +} + // Algorithm: // - Deduplicate and collect nested unions // - Merge *type with nullable *type