authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-04 02:11:50-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-04 02:11:50-07:00
logfdadab40c61a6f70a65472cc95ccd5ba52c01772
treef471173c1e54a3cd4e35759970adfcd36c991c0b
parent3a9009b08e278dafd7b59b7d09408c80ea67f1fe

implement constant values for enums with payload


4 files changed, 41 insertions(+), 3 deletions(-)

src/all_types.hpp+1
...@@ -859,6 +859,7 @@ struct TypeTableEntryEnum {...@@ -859,6 +859,7 @@ struct TypeTableEntryEnum {
859 TypeEnumField *fields;859 TypeEnumField *fields;
860 bool is_invalid; // true if any fields are invalid860 bool is_invalid; // true if any fields are invalid
861 TypeTableEntry *tag_type;861 TypeTableEntry *tag_type;
862 TypeTableEntry *union_type;
862863
863 // reminder: hash tables must be initialized before use864 // reminder: hash tables must be initialized before use
864 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;865 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
src/analyze.cpp+4
...@@ -973,6 +973,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt...@@ -973,6 +973,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
973973
974 if (!enum_type->data.enumeration.is_invalid) {974 if (!enum_type->data.enumeration.is_invalid) {
975 enum_type->data.enumeration.gen_field_count = gen_field_index;975 enum_type->data.enumeration.gen_field_count = gen_field_index;
976 enum_type->data.enumeration.union_type = biggest_union_member;
976977
977 TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);978 TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
978 enum_type->data.enumeration.tag_type = tag_type_entry;979 enum_type->data.enumeration.tag_type = tag_type_entry;
...@@ -2034,6 +2035,9 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp...@@ -2034,6 +2035,9 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
2034 codegen->type_entry = enum_type;2035 codegen->type_entry = enum_type;
2035 codegen->source_node = field_access_node;2036 codegen->source_node = field_access_node;
2036 context->struct_val_expr_alloca_list.append(codegen);2037 context->struct_val_expr_alloca_list.append(codegen);
2038
2039 Expr *expr = get_resolved_expr(field_access_node);
2040 expr->const_val.ok = false;
2037 } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) {2041 } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) {
2038 add_node_error(g, field_access_node,2042 add_node_error(g, field_access_node,
2039 buf_sprintf("enum value '%s.%s' requires parameter of type '%s'",2043 buf_sprintf("enum value '%s.%s' requires parameter of type '%s'",
src/codegen.cpp+14-1
...@@ -2567,7 +2567,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2567,7 +2567,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2567 if (type_entry->data.enumeration.gen_field_count == 0) {2567 if (type_entry->data.enumeration.gen_field_count == 0) {
2568 return tag_value;2568 return tag_value;
2569 } else {2569 } else {
2570 zig_panic("TODO");2570 TypeTableEntry *union_type = type_entry->data.enumeration.union_type;
2571 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag];
2572 assert(enum_field->value == const_val->data.x_enum.tag);
2573 LLVMValueRef union_value;
2574 if (type_has_bits(enum_field->type_entry)) {
2575 union_value = gen_const_val(g, union_type, const_val->data.x_enum.payload);
2576 } else {
2577 union_value = LLVMGetUndef(union_type->type_ref);
2578 }
2579 LLVMValueRef fields[] = {
2580 tag_value,
2581 union_value,
2582 };
2583 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
2571 }2584 }
2572 }2585 }
2573 case TypeTableEntryIdFn:2586 case TypeTableEntryIdFn:
test/self_hosted.zig+22-2
...@@ -38,11 +38,31 @@ fn call_struct_field(foo: Foo) -> i32 {...@@ -38,11 +38,31 @@ fn call_struct_field(foo: Foo) -> i32 {
3838
3939
4040
41#attribute("test")
42fn redefinition_of_error_values_allowed() {
43 if (error.AnError == error.SecondError) unreachable{}
44}
41error AnError;45error AnError;
42error AnError;46error AnError;
43error SecondError;47error SecondError;
4448
49
50
51
45#attribute("test")52#attribute("test")
46fn redefinition_of_error_values_allowed() {53fn constant_enum_with_payload() {
47 if (error.AnError == error.SecondError) unreachable{}54 should_be_empty(AnEnumWithPayload.Empty);
55 should_be_13(AnEnumWithPayload.Full(13));
56}
57
58fn should_be_empty(x: AnEnumWithPayload) {
59 if (x != AnEnumWithPayload.Empty) unreachable{}
60}
61
62fn should_be_13(x: AnEnumWithPayload) {
63}
64
65enum AnEnumWithPayload {
66 Empty,
67 Full: i32,
48}68}