mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-26 07:25:00 -07:00
union #no_nil
This commit is contained in:
+7
-1
@@ -1326,8 +1326,14 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
||||
case i64: tag = i64(i);
|
||||
case: panic("Invalid union tag type");
|
||||
}
|
||||
assert(tag >= 0);
|
||||
|
||||
if v.data == nil || tag == 0 {
|
||||
if v.data == nil {
|
||||
strings.write_string(fi.buf, "nil");
|
||||
} else if info.no_nil {
|
||||
id := info.variants[tag].id;
|
||||
fmt_arg(fi, any{v.data, id}, verb);
|
||||
} else if tag == 0 {
|
||||
strings.write_string(fi.buf, "nil");
|
||||
} else {
|
||||
id := info.variants[tag-1].id;
|
||||
|
||||
@@ -86,10 +86,11 @@ Type_Info_Struct :: struct {
|
||||
custom_align: bool,
|
||||
};
|
||||
Type_Info_Union :: struct {
|
||||
variants: []^Type_Info,
|
||||
tag_offset: uintptr,
|
||||
tag_type: ^Type_Info,
|
||||
variants: []^Type_Info,
|
||||
tag_offset: uintptr,
|
||||
tag_type: ^Type_Info,
|
||||
custom_align: bool,
|
||||
no_nil: bool,
|
||||
};
|
||||
Type_Info_Enum :: struct {
|
||||
base: ^Type_Info,
|
||||
|
||||
@@ -715,6 +715,7 @@ void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Array<Op
|
||||
}
|
||||
|
||||
union_type->Union.variants = variants;
|
||||
union_type->Union.no_nil = ut->no_nil;
|
||||
|
||||
if (ut->align != nullptr) {
|
||||
i64 custom_align = 1;
|
||||
|
||||
@@ -9991,6 +9991,7 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
|
||||
irValue *tag_offset_ptr = ir_emit_struct_ep(proc, tag, 1);
|
||||
irValue *tag_type_ptr = ir_emit_struct_ep(proc, tag, 2);
|
||||
irValue *custom_align_ptr = ir_emit_struct_ep(proc, tag, 3);
|
||||
irValue *no_nil_ptr = ir_emit_struct_ep(proc, tag, 4);
|
||||
|
||||
isize variant_count = gb_max(0, t->Union.variants.count);
|
||||
irValue *memory_types = ir_type_info_member_types_offset(proc, variant_count);
|
||||
@@ -10018,6 +10019,8 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
|
||||
|
||||
irValue *is_custom_align = ir_const_bool(t->Union.custom_align != 0);
|
||||
ir_emit_store(proc, custom_align_ptr, is_custom_align);
|
||||
|
||||
ir_emit_store(proc, no_nil_ptr, ir_const_bool(t->Union.no_nil));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
+9
-2
@@ -911,12 +911,13 @@ Ast *ast_struct_type(AstFile *f, Token token, Array<Ast *> fields, isize field_c
|
||||
}
|
||||
|
||||
|
||||
Ast *ast_union_type(AstFile *f, Token token, Array<Ast *> variants, Ast *polymorphic_params, Ast *align) {
|
||||
Ast *ast_union_type(AstFile *f, Token token, Array<Ast *> variants, Ast *polymorphic_params, Ast *align, bool no_nil) {
|
||||
Ast *result = alloc_ast_node(f, Ast_UnionType);
|
||||
result->UnionType.token = token;
|
||||
result->UnionType.variants = variants;
|
||||
result->UnionType.polymorphic_params = polymorphic_params;
|
||||
result->UnionType.align = align;
|
||||
result->UnionType.no_nil = no_nil;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1971,6 +1972,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
auto variants = array_make<Ast *>(heap_allocator());
|
||||
Ast *polymorphic_params = nullptr;
|
||||
Ast *align = nullptr;
|
||||
bool no_nil = false;
|
||||
|
||||
CommentGroup *docs = f->lead_comment;
|
||||
Token start_token = f->curr_token;
|
||||
@@ -1993,6 +1995,11 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
syntax_error(tag, "Duplicate union tag '#%.*s'", LIT(tag.string));
|
||||
}
|
||||
align = parse_expr(f, true);
|
||||
} else if (tag.string == "no_nil") {
|
||||
if (no_nil) {
|
||||
syntax_error(tag, "Duplicate union tag '#%.*s'", LIT(tag.string));
|
||||
}
|
||||
no_nil = true;
|
||||
} else {
|
||||
syntax_error(tag, "Invalid union tag '#%.*s'", LIT(tag.string));
|
||||
}
|
||||
@@ -2013,7 +2020,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
|
||||
Token close = expect_token(f, Token_CloseBrace);
|
||||
|
||||
return ast_union_type(f, token, variants, polymorphic_params, align);
|
||||
return ast_union_type(f, token, variants, polymorphic_params, align, no_nil);
|
||||
} break;
|
||||
|
||||
case Token_enum: {
|
||||
|
||||
@@ -480,6 +480,7 @@ AST_KIND(_TypeBegin, "", bool) \
|
||||
Array<Ast *> variants; \
|
||||
Ast *polymorphic_params; \
|
||||
Ast * align; \
|
||||
bool no_nil; \
|
||||
}) \
|
||||
AST_KIND(EnumType, "enum type", struct { \
|
||||
Token token; \
|
||||
|
||||
+9
-3
@@ -131,6 +131,7 @@ struct TypeUnion {
|
||||
i64 variant_block_size;
|
||||
i64 custom_align;
|
||||
i64 tag_size;
|
||||
bool no_nil;
|
||||
|
||||
bool is_polymorphic;
|
||||
bool is_poly_specialized;
|
||||
@@ -1468,7 +1469,7 @@ bool type_has_nil(Type *t) {
|
||||
case Type_Map:
|
||||
return true;
|
||||
case Type_Union:
|
||||
return true;
|
||||
return !t->Union.no_nil;
|
||||
case Type_Struct:
|
||||
return false;
|
||||
case Type_Opaque:
|
||||
@@ -1625,7 +1626,8 @@ bool are_types_identical(Type *x, Type *y) {
|
||||
case Type_Union:
|
||||
if (y->kind == Type_Union) {
|
||||
if (x->Union.variants.count == y->Union.variants.count &&
|
||||
x->Union.custom_align == y->Union.custom_align) {
|
||||
x->Union.custom_align == y->Union.custom_align &&
|
||||
x->Union.no_nil == y->Union.no_nil) {
|
||||
// NOTE(bill): zeroth variant is nullptr
|
||||
for_array(i, x->Union.variants) {
|
||||
if (!are_types_identical(x->Union.variants[i], y->Union.variants[i])) {
|
||||
@@ -1778,7 +1780,11 @@ 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)) {
|
||||
return cast(i64)(i+1);
|
||||
if (u->Union.no_nil) {
|
||||
return cast(i64)(i+0);
|
||||
} else {
|
||||
return cast(i64)(i+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user