commit 11519092415f3ca5f62f71d30dee52d760390b56
parent 3a72092cb99f4e57fd6f5c2d7f3fd9af512c6c8c
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 16 Jan 2021 11:39:17 -0500
type store: reduction of tagged unions with alias
Diffstat:
2 files changed, 55 insertions(+), 7 deletions(-)
diff --git a/src/type_store.c b/src/type_store.c
@@ -415,12 +415,14 @@ struct_init_from_atype(struct type_store *store, enum type_storage storage,
}
static size_t
-sum_atagged_memb(const struct ast_tagged_union_type *u)
+sum_tagged_memb(struct type_store *store,
+ const struct type_tagged_union *u)
{
size_t nmemb = 0;
for (; u; u = u->next) {
- if (u->type->storage == TYPE_STORAGE_TAGGED_UNION) {
- nmemb += sum_atagged_memb(&u->type->tagged_union);
+ const struct type *type = u->type;
+ if (type->storage == TYPE_STORAGE_TAGGED_UNION) {
+ nmemb += sum_tagged_memb(store, &type->tagged);
} else {
++nmemb;
}
@@ -428,6 +430,42 @@ sum_atagged_memb(const struct ast_tagged_union_type *u)
return nmemb;
}
+static size_t
+sum_atagged_memb(struct type_store *store,
+ const struct ast_tagged_union_type *u)
+{
+ size_t nmemb = 0;
+ for (; u; u = u->next) {
+ const struct type *type =
+ type_store_lookup_atype(store, u->type);
+ if (type->storage == TYPE_STORAGE_TAGGED_UNION) {
+ nmemb += sum_tagged_memb(store, &type->tagged);
+ } else {
+ ++nmemb;
+ }
+ }
+ return nmemb;
+}
+
+static void
+collect_tagged_memb(struct type_store *store,
+ struct type_tagged_union **ta,
+ const struct type_tagged_union *src,
+ size_t *i)
+{
+ for (; src; src = src->next) {
+ const struct type *type = src->type;
+ if (type->storage == TYPE_STORAGE_TAGGED_UNION) {
+ collect_tagged_memb(store, ta, &type->tagged, i);
+ continue;
+ }
+ struct type_tagged_union *tu;
+ ta[*i] = tu = xcalloc(1, sizeof(struct type_tagged_union));
+ tu->type = type;
+ *i += 1;
+ }
+}
+
static void
collect_atagged_memb(struct type_store *store,
struct type_tagged_union **ta,
@@ -435,13 +473,15 @@ collect_atagged_memb(struct type_store *store,
size_t *i)
{
for (; atu; atu = atu->next) {
- if (atu->type->storage == TYPE_STORAGE_TAGGED_UNION) {
- collect_atagged_memb(store, ta, &atu->type->tagged_union, i);
+ const struct type *type =
+ type_store_lookup_atype(store, atu->type);
+ if (type->storage == TYPE_STORAGE_TAGGED_UNION) {
+ collect_tagged_memb(store, ta, &type->tagged, i);
continue;
}
struct type_tagged_union *tu;
ta[*i] = tu = xcalloc(1, sizeof(struct type_tagged_union));
- tu->type = type_store_lookup_atype(store, atu->type);
+ tu->type = type;
*i += 1;
}
}
@@ -461,7 +501,7 @@ static void
tagged_init_from_atype(struct type_store *store,
struct type *type, const struct ast_type *atype)
{
- size_t nmemb = sum_atagged_memb(&atype->tagged_union);
+ size_t nmemb = sum_atagged_memb(store, &atype->tagged_union);
struct type_tagged_union **tu =
xcalloc(nmemb, sizeof(struct type_tagged_union *));
size_t i = 0;
diff --git a/tests/13-tagged.ha b/tests/13-tagged.ha
@@ -40,6 +40,10 @@ fn operators() void = {
assert(x is u64);
};
+type signed = (i8 | i16 | i32 | i64 | int);
+type unsigned = (u8 | u16 | u32 | u64 | uint);
+type integer = (...signed | ...unsigned);
+
fn reduction() void = {
let a: (i8 | i16) = 42i8;
let b: (i16 | i8) = a;
@@ -48,6 +52,10 @@ fn reduction() void = {
assert(b is i8);
assert(c is i8);
assert(size((i8 | i16 | i32)) == size((i8 | (i16 | i32))));
+ assert(size(integer) == size(signed));
+ assert(size(integer) != size((signed | unsigned)));
+ let i: integer = 10;
+ assert(i is int);
};
export fn main() void = {