union #shared_nil

This adds a feature to `union` which requires all the variants to have a `nil` value and on assign to the union, checks whether that value is `nil` or not. If the value is `nil`, the union will be `nil` (thus sharing the `nil` value)
This commit is contained in:
gingerBill
2022-03-24 11:55:03 +00:00
parent 3e66eec735
commit 3f935bea25
10 changed files with 104 additions and 32 deletions

View File

@@ -165,9 +165,8 @@ struct TypeUnion {
i16 tag_size;
bool is_polymorphic;
bool is_poly_specialized : 1;
bool no_nil : 1;
bool maybe : 1;
bool is_poly_specialized;
UnionTypeKind kind;
};
struct TypeProc {
@@ -1664,7 +1663,7 @@ bool is_type_map(Type *t) {
bool is_type_union_maybe_pointer(Type *t) {
t = base_type(t);
if (t->kind == Type_Union && t->Union.maybe) {
if (t->kind == Type_Union && t->Union.kind == UnionType_maybe) {
if (t->Union.variants.count == 1) {
Type *v = t->Union.variants[0];
return is_type_pointer(v) || is_type_multi_pointer(v);
@@ -1676,7 +1675,7 @@ bool is_type_union_maybe_pointer(Type *t) {
bool is_type_union_maybe_pointer_original_alignment(Type *t) {
t = base_type(t);
if (t->kind == Type_Union && t->Union.maybe) {
if (t->kind == Type_Union && t->Union.kind == UnionType_maybe) {
if (t->Union.variants.count == 1) {
Type *v = t->Union.variants[0];
if (is_type_pointer(v) || is_type_multi_pointer(v)) {
@@ -2168,7 +2167,7 @@ bool type_has_nil(Type *t) {
case Type_Map:
return true;
case Type_Union:
return !t->Union.no_nil;
return t->Union.kind != UnionType_no_nil;
case Type_Struct:
if (is_type_soa_struct(t)) {
switch (t->Struct.soa_kind) {
@@ -2454,7 +2453,7 @@ bool are_types_identical_internal(Type *x, Type *y, bool check_tuple_names) {
if (y->kind == Type_Union) {
if (x->Union.variants.count == y->Union.variants.count &&
x->Union.custom_align == y->Union.custom_align &&
x->Union.no_nil == y->Union.no_nil) {
x->Union.kind == y->Union.kind) {
// NOTE(bill): zeroth variant is nullptr
for_array(i, x->Union.variants) {
if (!are_types_identical(x->Union.variants[i], y->Union.variants[i])) {
@@ -2598,7 +2597,7 @@ i64 union_variant_index(Type *u, Type *v) {
for_array(i, u->Union.variants) {
Type *vt = u->Union.variants[i];
if (are_types_identical(v, vt)) {
if (u->Union.no_nil) {
if (u->Union.kind == UnionType_no_nil) {
return cast(i64)(i+0);
} else {
return cast(i64)(i+1);
@@ -4021,8 +4020,11 @@ gbString write_type_to_string(gbString str, Type *type, bool shorthand=false) {
case Type_Union:
str = gb_string_appendc(str, "union");
if (type->Union.no_nil != 0) str = gb_string_appendc(str, " #no_nil");
if (type->Union.maybe != 0) str = gb_string_appendc(str, " #maybe");
switch (type->Union.kind) {
case UnionType_maybe: str = gb_string_appendc(str, " #maybe"); break;
case UnionType_no_nil: str = gb_string_appendc(str, " #no_nil"); break;
case UnionType_shared_nil: str = gb_string_appendc(str, " #shared_nil"); break;
}
if (type->Union.custom_align != 0) str = gb_string_append_fmt(str, " #align %d", cast(int)type->Union.custom_align);
str = gb_string_appendc(str, " {");
for_array(i, type->Union.variants) {