harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit ec59e8c5881a3b4c68e9c7d023f11f18c40d83cc
parent d1e5d917b8d94fc0c8efe3eaffb28dd7fab38553
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 24 Jan 2021 10:15:57 -0500

Fix several issues with aliases and match

Diffstat:
Minclude/type_store.h | 3+++
Msrc/check.c | 14+++++++++++---
Msrc/gen.c | 5+++--
Msrc/type_store.c | 18+++++++++++++++++-
Msrc/types.c | 1-
Mtests/18-match.ha | 17+++++++++++++++++
6 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/include/type_store.h b/include/type_store.h @@ -41,4 +41,7 @@ const struct type *type_store_lookup_array(struct type_store *store, const struct type *type_store_lookup_slice(struct type_store *store, const struct type *members); +const struct type *type_store_lookup_alias(struct type_store *store, + const struct identifier *ident, const struct type *secondary); + #endif diff --git a/src/check.c b/src/check.c @@ -87,7 +87,12 @@ check_expr_access(struct context *ctx, expr->access.object = obj; break; case O_TYPE: - expect(&aexpr->loc, false, "Expected identifier, got type"); + expect(&aexpr->loc, + type_dealias(obj->type)->storage == TYPE_STORAGE_VOID, + "Cannot use non-void type alias as constant"); + expr->type = EXPR_CONSTANT; + expr->result = obj->type; + break; } break; case ACCESS_INDEX: @@ -874,7 +879,7 @@ check_expr_match(struct context *ctx, check_expression(ctx, aexpr->match.value, value, NULL); expr->match.value = value; - const struct type *type = value->result; + const struct type *type = type_dealias(value->result); bool is_ptr = type->storage == TYPE_STORAGE_POINTER && type->pointer.flags & PTR_NULLABLE; expect(&aexpr->match.value->loc, @@ -1632,7 +1637,10 @@ scan_type(struct context *ctx, const struct ast_type_decl *decl) struct identifier ident = {0}; mkident(ctx, &ident, &decl->ident); - scope_insert(ctx->unit, O_TYPE, &ident, &decl->ident, type, NULL); + + const struct type *alias = + type_store_lookup_alias(ctx->store, &ident, type); + scope_insert(ctx->unit, O_TYPE, &ident, &decl->ident, alias, NULL); if (type->storage == TYPE_STORAGE_ENUM) { for (struct type_enum_value *value = type->_enum.values; value; diff --git a/src/gen.c b/src/gen.c @@ -1230,8 +1230,9 @@ gen_expr_constant(struct gen_context *ctx, case Q_DOUBLE: constd(&val, expr->constant.fval); break; - case Q__AGGREGATE: case Q__VOID: + return; // no-op + case Q__AGGREGATE: assert(0); // Invariant } @@ -1549,7 +1550,7 @@ gen_expr_match(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) { - const struct type *mtype = expr->match.value->result; + const struct type *mtype = type_dealias(expr->match.value->result); switch (mtype->storage) { case TYPE_STORAGE_TAGGED_UNION: gen_match_tagged(ctx, expr, out); diff --git a/src/type_store.c b/src/type_store.c @@ -611,7 +611,7 @@ type_init_from_atype(struct type_store *store, case TYPE_STORAGE_ALIAS: obj = scope_lookup(store->check_context->scope, &atype->alias); if (atype->unwrap) { - *type = *obj->type; + *type = *type_dealias(obj->type); break; } assert(obj && obj->otype == O_TYPE); // TODO: Bubble this up @@ -821,3 +821,19 @@ type_store_lookup_slice(struct type_store *store, const struct type *members) }; return type_store_lookup_type(store, &slice); } + +const struct type * +type_store_lookup_alias(struct type_store *store, + const struct identifier *ident, const struct type *secondary) +{ + struct type alias = { + .storage = TYPE_STORAGE_ALIAS, + .alias = { + .ident = *ident, + .type = secondary, + }, + .size = secondary->size, + .align = secondary->align, + }; + return type_store_lookup_type(store, &alias); +} diff --git a/src/types.c b/src/types.c @@ -281,7 +281,6 @@ type_hash(const struct type *type) hash = fnv1a_s(hash, ident->name); hash = fnv1a(hash, 0); } - hash = fnv1a_u32(hash, type_hash(type->alias.type)); break; case TYPE_STORAGE_ARRAY: hash = fnv1a_u32(hash, type_hash(type->array.members)); diff --git a/tests/18-match.ha b/tests/18-match.ha @@ -47,9 +47,26 @@ fn pointer() void = { assert(z == 1337); }; +type foo = void; +type bar = void; +type foobar = (foo | bar); + +fn alias() void = { + let cases: []foobar = [foo, bar]; + let expected = [42, 24]; + for (let i = 0z; i < len(cases); i += 1z) { + let y: int = match (cases[i]) { + foo => 42, + bar => 24, + }; + assert(y == expected[i]); + }; +}; + export fn main() void = { tagged(); termination(); default(); pointer(); + alias(); };