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:
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();
};