mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-03 05:08:14 +00:00
Add hidden __tag for union variables.
This commit is contained in:
@@ -422,6 +422,8 @@ isize check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
e->identifier = name;
|
||||
if (str_eq(name_token.string, str_lit("_"))) {
|
||||
fields[field_index++] = e;
|
||||
} else if (str_eq(name_token.string, str_lit("__tag"))) {
|
||||
error_node(name, "`__tag` is a reserved identifier for fields");
|
||||
} else {
|
||||
HashKey key = hash_string(name_token.string);
|
||||
Entity **found = map_entity_get(&entity_map, key);
|
||||
@@ -660,6 +662,10 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||
union_type->Record.field_count = field_count;
|
||||
union_type->Record.are_offsets_set = false;
|
||||
union_type->Record.is_ordered = true;
|
||||
{
|
||||
Entity *__tag = make_entity_field(c->allocator, NULL, make_token_ident(str_lit("__tag")), t_int, false, -1);
|
||||
union_type->Record.union__tag = __tag;
|
||||
}
|
||||
|
||||
for_array(i, ut->variants) {
|
||||
AstNode *variant = ut->variants.e[i];
|
||||
|
||||
@@ -2244,8 +2244,13 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
||||
} else if (is_type_union(t)) {
|
||||
type_set_offsets(a, t);
|
||||
GB_ASSERT(t->Record.field_count > 0);
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
||||
if (index == -1) {
|
||||
index = t->Record.field_count+1;
|
||||
result_type = t_int_ptr;
|
||||
} else {
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
||||
}
|
||||
} else if (is_type_tuple(t)) {
|
||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
||||
@@ -2316,8 +2321,12 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
||||
result_type = t->Record.fields[index]->type;
|
||||
} else if (is_type_union(t)) {
|
||||
type_set_offsets(a, t);
|
||||
GB_ASSERT(t->Record.field_count > 0);
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||
if (index == -1) {
|
||||
index = t->Record.field_count+1;
|
||||
result_type = t_int_ptr;
|
||||
} else {
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||
}
|
||||
result_type = t->Record.fields[index]->type;
|
||||
} else if (is_type_tuple(t)) {
|
||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||
@@ -2394,7 +2403,11 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel) {
|
||||
type = type->Record.fields[index]->type;
|
||||
e = ir_emit_conv(proc, e, make_type_pointer(proc->module->allocator, type));
|
||||
} else if (type->kind == Type_Record) {
|
||||
type = type->Record.fields[index]->type;
|
||||
if (index == -1) {
|
||||
type = t_int;
|
||||
} else {
|
||||
type = type->Record.fields[index]->type;
|
||||
}
|
||||
e = ir_emit_struct_ep(proc, e, index);
|
||||
} else if (type->kind == Type_Tuple) {
|
||||
type = type->Tuple.variables[index]->type;
|
||||
|
||||
+1
-1
@@ -1844,7 +1844,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
return ast_proc_lit(f, type, NULL, tags, foreign_library, foreign_name, link_name);
|
||||
}
|
||||
if (tags != 0) {
|
||||
syntax_error(token, "A procedure type cannot have tags");
|
||||
// syntax_error(token, "A procedure type cannot have tags");
|
||||
}
|
||||
|
||||
return type;
|
||||
|
||||
+11
@@ -92,6 +92,8 @@ typedef struct TypeRecord {
|
||||
// Entity_TypeName - union
|
||||
Entity **variants;
|
||||
i32 variant_count;
|
||||
Entity * union__tag;
|
||||
|
||||
|
||||
i64 * offsets;
|
||||
bool are_offsets_set;
|
||||
@@ -1415,6 +1417,15 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
||||
sel.index.count = prev_count;
|
||||
}
|
||||
}
|
||||
if (type->Record.kind == TypeRecord_Union) {
|
||||
if (str_eq(field_name, str_lit("__tag"))) {
|
||||
Entity *e = type->Record.union__tag;
|
||||
GB_ASSERT(e != NULL);
|
||||
selection_add_index(&sel, -1); // HACK(bill): Leaky memory
|
||||
sel.entity = e;
|
||||
return sel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sel;
|
||||
|
||||
Reference in New Issue
Block a user