commit ae4c3c71a23f1b9d496c106a43aa434b2b0562f4
parent af16fa5d315b6f30b0e999e31c18d763839b7d93
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 16 Jan 2021 09:55:57 -0500
type store: implement tagged mutual assignment
Diffstat:
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/src/type_store.c b/src/type_store.c
@@ -32,7 +32,22 @@ tagged_assignable(struct type_store *store,
const struct type *from)
{
if (from->storage == TYPE_STORAGE_TAGGED_UNION) {
- assert(0); // TODO
+ if (to->storage != TYPE_STORAGE_TAGGED_UNION) {
+ return false;
+ }
+ // Only assignable if 'to' is a superset of 'from'
+ // Invariant: type_tagged_union is sorted by type tag
+ const struct type_tagged_union *to_t = &to->tagged;
+ const struct type_tagged_union *from_t = &from->tagged;
+ while (to_t && from_t) {
+ if (to_t->type->id == from_t->type->id) {
+ to_t = to_t->next;
+ from_t = from_t->next;
+ } else {
+ from_t = from_t->next;
+ }
+ }
+ return from_t == NULL;
}
size_t nassignable = 0;
@@ -171,6 +186,9 @@ static bool
tagged_castable(const struct type *to, const struct type *from)
{
if (to->storage == TYPE_STORAGE_TAGGED_UNION) {
+ if (from->storage == TYPE_STORAGE_TAGGED_UNION) {
+ return true;
+ }
assert(0); // TODO
}
diff --git a/tests/13-tagged.ha b/tests/13-tagged.ha
@@ -40,9 +40,19 @@ fn operators() void = {
assert(x is u64);
};
+fn reduction() void = {
+ let a: (i8 | i16) = 42i8;
+ let b: (i16 | i8) = a;
+ let c: (i8 | i16 | i32) = a;
+ assert(a is i8);
+ assert(b is i8);
+ assert(c is i8);
+};
+
export fn main() void = {
measurements();
storage();
operators();
+ reduction();
// TODO: Expand this as other tagged union features become available
};