mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00: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 i64: tag = i64(i);
|
||||||
case: panic("Invalid union tag type");
|
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");
|
strings.write_string(fi.buf, "nil");
|
||||||
} else {
|
} else {
|
||||||
id := info.variants[tag-1].id;
|
id := info.variants[tag-1].id;
|
||||||
|
|||||||
@@ -86,10 +86,11 @@ Type_Info_Struct :: struct {
|
|||||||
custom_align: bool,
|
custom_align: bool,
|
||||||
};
|
};
|
||||||
Type_Info_Union :: struct {
|
Type_Info_Union :: struct {
|
||||||
variants: []^Type_Info,
|
variants: []^Type_Info,
|
||||||
tag_offset: uintptr,
|
tag_offset: uintptr,
|
||||||
tag_type: ^Type_Info,
|
tag_type: ^Type_Info,
|
||||||
custom_align: bool,
|
custom_align: bool,
|
||||||
|
no_nil: bool,
|
||||||
};
|
};
|
||||||
Type_Info_Enum :: struct {
|
Type_Info_Enum :: struct {
|
||||||
base: ^Type_Info,
|
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.variants = variants;
|
||||||
|
union_type->Union.no_nil = ut->no_nil;
|
||||||
|
|
||||||
if (ut->align != nullptr) {
|
if (ut->align != nullptr) {
|
||||||
i64 custom_align = 1;
|
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_offset_ptr = ir_emit_struct_ep(proc, tag, 1);
|
||||||
irValue *tag_type_ptr = ir_emit_struct_ep(proc, tag, 2);
|
irValue *tag_type_ptr = ir_emit_struct_ep(proc, tag, 2);
|
||||||
irValue *custom_align_ptr = ir_emit_struct_ep(proc, tag, 3);
|
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);
|
isize variant_count = gb_max(0, t->Union.variants.count);
|
||||||
irValue *memory_types = ir_type_info_member_types_offset(proc, variant_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);
|
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, custom_align_ptr, is_custom_align);
|
||||||
|
|
||||||
|
ir_emit_store(proc, no_nil_ptr, ir_const_bool(t->Union.no_nil));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
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);
|
Ast *result = alloc_ast_node(f, Ast_UnionType);
|
||||||
result->UnionType.token = token;
|
result->UnionType.token = token;
|
||||||
result->UnionType.variants = variants;
|
result->UnionType.variants = variants;
|
||||||
result->UnionType.polymorphic_params = polymorphic_params;
|
result->UnionType.polymorphic_params = polymorphic_params;
|
||||||
result->UnionType.align = align;
|
result->UnionType.align = align;
|
||||||
|
result->UnionType.no_nil = no_nil;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1971,6 +1972,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
|||||||
auto variants = array_make<Ast *>(heap_allocator());
|
auto variants = array_make<Ast *>(heap_allocator());
|
||||||
Ast *polymorphic_params = nullptr;
|
Ast *polymorphic_params = nullptr;
|
||||||
Ast *align = nullptr;
|
Ast *align = nullptr;
|
||||||
|
bool no_nil = false;
|
||||||
|
|
||||||
CommentGroup *docs = f->lead_comment;
|
CommentGroup *docs = f->lead_comment;
|
||||||
Token start_token = f->curr_token;
|
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));
|
syntax_error(tag, "Duplicate union tag '#%.*s'", LIT(tag.string));
|
||||||
}
|
}
|
||||||
align = parse_expr(f, true);
|
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 {
|
} else {
|
||||||
syntax_error(tag, "Invalid union tag '#%.*s'", LIT(tag.string));
|
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);
|
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;
|
} break;
|
||||||
|
|
||||||
case Token_enum: {
|
case Token_enum: {
|
||||||
|
|||||||
@@ -480,6 +480,7 @@ AST_KIND(_TypeBegin, "", bool) \
|
|||||||
Array<Ast *> variants; \
|
Array<Ast *> variants; \
|
||||||
Ast *polymorphic_params; \
|
Ast *polymorphic_params; \
|
||||||
Ast * align; \
|
Ast * align; \
|
||||||
|
bool no_nil; \
|
||||||
}) \
|
}) \
|
||||||
AST_KIND(EnumType, "enum type", struct { \
|
AST_KIND(EnumType, "enum type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
|
|||||||
+9
-3
@@ -131,6 +131,7 @@ struct TypeUnion {
|
|||||||
i64 variant_block_size;
|
i64 variant_block_size;
|
||||||
i64 custom_align;
|
i64 custom_align;
|
||||||
i64 tag_size;
|
i64 tag_size;
|
||||||
|
bool no_nil;
|
||||||
|
|
||||||
bool is_polymorphic;
|
bool is_polymorphic;
|
||||||
bool is_poly_specialized;
|
bool is_poly_specialized;
|
||||||
@@ -1468,7 +1469,7 @@ bool type_has_nil(Type *t) {
|
|||||||
case Type_Map:
|
case Type_Map:
|
||||||
return true;
|
return true;
|
||||||
case Type_Union:
|
case Type_Union:
|
||||||
return true;
|
return !t->Union.no_nil;
|
||||||
case Type_Struct:
|
case Type_Struct:
|
||||||
return false;
|
return false;
|
||||||
case Type_Opaque:
|
case Type_Opaque:
|
||||||
@@ -1625,7 +1626,8 @@ bool are_types_identical(Type *x, Type *y) {
|
|||||||
case Type_Union:
|
case Type_Union:
|
||||||
if (y->kind == Type_Union) {
|
if (y->kind == Type_Union) {
|
||||||
if (x->Union.variants.count == y->Union.variants.count &&
|
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
|
// NOTE(bill): zeroth variant is nullptr
|
||||||
for_array(i, x->Union.variants) {
|
for_array(i, x->Union.variants) {
|
||||||
if (!are_types_identical(x->Union.variants[i], y->Union.variants[i])) {
|
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) {
|
for_array(i, u->Union.variants) {
|
||||||
Type *vt = u->Union.variants[i];
|
Type *vt = u->Union.variants[i];
|
||||||
if (are_types_identical(v, vt)) {
|
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;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user