harec

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

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:
Msrc/type_store.c | 54+++++++++++++++++++++++++++++++++++++++++++++++-------
Mtests/13-tagged.ha | 8++++++++
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 = {