union #no_nil

This commit is contained in:
gingerBill
2019-07-09 10:28:13 +01:00
parent c5b3d7a736
commit 4ab9edeb53
7 changed files with 34 additions and 9 deletions
+7 -1
View File
@@ -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;
+4 -3
View File
@@ -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,
+1
View File
@@ -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;
+3
View File
@@ -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
View File
@@ -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: {
+1
View File
@@ -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
View File
@@ -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;