Merge pull request #1802 from odin-lang/remove-maybe-tag

Merge functionality of `#maybe` with the standard 'union' functionality
This commit is contained in:
gingerBill
2022-05-23 12:35:06 +01:00
committed by GitHub
12 changed files with 31 additions and 27 deletions

View File

@@ -209,7 +209,7 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
variant := u.variants[0]
v.id = variant.id
ti = reflect.type_info_base(variant)
if !(u.maybe && reflect.is_pointer(variant)) {
if !reflect.is_pointer_internally(variant) {
tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id}
assign_int(tag, 1)
}

View File

@@ -654,7 +654,7 @@ union_variant_type_info :: proc(a: any) -> ^Type_Info {
}
type_info_union_is_pure_maybe :: proc(info: runtime.Type_Info_Union) -> bool {
return info.maybe && len(info.variants) == 1 && is_pointer(info.variants[0])
return len(info.variants) == 1 && is_pointer(info.variants[0])
}
union_variant_typeid :: proc(a: any) -> typeid {

View File

@@ -256,6 +256,17 @@ is_multi_pointer :: proc(info: ^Type_Info) -> bool {
_, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer)
return ok
}
is_pointer_internally :: proc(info: ^Type_Info) -> bool {
if info == nil { return false }
#partial switch v in info.variant {
case Type_Info_Pointer, Type_Info_Multi_Pointer,
Type_Info_Procedure:
return true
case Type_Info_String:
return v.is_cstring
}
return false
}
is_procedure :: proc(info: ^Type_Info) -> bool {
if info == nil { return false }
_, ok := type_info_base(info).variant.(Type_Info_Procedure)
@@ -531,9 +542,8 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
case Type_Info_Union:
io.write_string(w, "union ", &n) or_return
if info.maybe {
io.write_string(w, "#maybe ", &n) or_return
}
if info.no_nil { io.write_string(w, "#no_nil ", &n) or_return }
if info.shared_nil { io.write_string(w, "#shared_nil ", &n) or_return }
if info.custom_align {
io.write_string(w, "#align ", &n) or_return
io.write_i64(w, i64(ti.align), 10, &n) or_return

View File

@@ -135,7 +135,6 @@ Type_Info_Union :: struct {
custom_align: bool,
no_nil: bool,
maybe: bool,
shared_nil: bool,
}
Type_Info_Enum :: struct {

View File

@@ -3,7 +3,7 @@ package runtime
import "core:intrinsics"
@builtin
Maybe :: union($T: typeid) #maybe {T}
Maybe :: union($T: typeid) {T}
@builtin

View File

@@ -1977,15 +1977,17 @@ constant_literal_expressions :: proc() {
}
union_maybe :: proc() {
fmt.println("\n#union #maybe")
fmt.println("\n#union based maybe")
// NOTE: This is already built-in, and this is just a reimplementation to explain the behaviour
Maybe :: union($T: typeid) #maybe {T}
Maybe :: union($T: typeid) {T}
i: Maybe(u8)
p: Maybe(^u8) // No tag is stored for pointers, nil is the sentinel value
// Tag size will be as small as needed for the number of variants
#assert(size_of(i) == size_of(u8) + size_of(u8))
// No need to store a tag here, the `nil` state is shared with the variant's `nil`
#assert(size_of(p) == size_of(^u8))
i = 123

View File

@@ -10065,7 +10065,6 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
str = gb_string_appendc(str, ") ");
}
switch (st->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;
}

View File

@@ -620,7 +620,6 @@ OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
doc_type.kind = OdinDocType_Union;
if (type->Union.is_polymorphic) { doc_type.flags |= OdinDocTypeFlag_Union_polymorphic; }
switch (type->Union.kind) {
case UnionType_maybe: doc_type.flags |= OdinDocTypeFlag_Union_maybe; break;
case UnionType_no_nil: doc_type.flags |= OdinDocTypeFlag_Union_no_nil; break;
case UnionType_shared_nil: doc_type.flags |= OdinDocTypeFlag_Union_shared_nil; break;
}

View File

@@ -641,7 +641,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_union_ptr);
{
LLVMValueRef vals[8] = {};
LLVMValueRef vals[7] = {};
isize variant_count = gb_max(0, t->Union.variants.count);
lbValue memory_types = lb_type_info_member_types_offset(p, variant_count);
@@ -676,8 +676,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
vals[4] = lb_const_bool(m, t_bool, t->Union.custom_align != 0).value;
vals[5] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_no_nil).value;
vals[6] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_maybe).value;
vals[7] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_shared_nil).value;
vals[6] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_shared_nil).value;
for (isize i = 0; i < gb_count_of(vals); i++) {
if (vals[i] == nullptr) {

View File

@@ -2529,6 +2529,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
if (maybe) {
union_kind = UnionType_maybe;
syntax_error(f->curr_token, "#maybe functionality has now been merged with standard 'union' functionality");
} else if (no_nil) {
union_kind = UnionType_no_nil;
} else if (shared_nil) {

View File

@@ -332,7 +332,7 @@ char const *inline_asm_dialect_strings[InlineAsmDialect_COUNT] = {
enum UnionTypeKind : u8 {
UnionType_Normal = 0,
UnionType_maybe = 1,
UnionType_maybe = 1, // removed
UnionType_no_nil = 2,
UnionType_shared_nil = 3,
};

View File

@@ -1685,11 +1685,9 @@ 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.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);
}
if (t->kind == Type_Union && t->Union.variants.count == 1) {
Type *v = t->Union.variants[0];
return is_type_internally_pointer_like(v);
}
return false;
}
@@ -1697,12 +1695,10 @@ 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.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)) {
return type_align_of(v) == type_align_of(t);
}
if (t->kind == Type_Union && t->Union.variants.count == 1) {
Type *v = t->Union.variants[0];
if (is_type_internally_pointer_like(v)) {
return type_align_of(v) == type_align_of(t);
}
}
return false;
@@ -4054,7 +4050,6 @@ gbString write_type_to_string(gbString str, Type *type, bool shorthand=false) {
case Type_Union:
str = gb_string_appendc(str, "union");
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;
}