Commit fdadab40c6

Andrew Kelley <superjoe30@gmail.com>
2016-02-04 10:11:50
implement constant values for enums with payload
1 parent 3a9009b
src/all_types.hpp
@@ -859,6 +859,7 @@ struct TypeTableEntryEnum {
     TypeEnumField *fields;
     bool is_invalid; // true if any fields are invalid
     TypeTableEntry *tag_type;
+    TypeTableEntry *union_type;
 
     // reminder: hash tables must be initialized before use
     HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
src/analyze.cpp
@@ -973,6 +973,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
 
     if (!enum_type->data.enumeration.is_invalid) {
         enum_type->data.enumeration.gen_field_count = gen_field_index;
+        enum_type->data.enumeration.union_type = biggest_union_member;
 
         TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
         enum_type->data.enumeration.tag_type = tag_type_entry;
@@ -2034,6 +2035,9 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
             codegen->type_entry = enum_type;
             codegen->source_node = field_access_node;
             context->struct_val_expr_alloca_list.append(codegen);
+
+            Expr *expr = get_resolved_expr(field_access_node);
+            expr->const_val.ok = false;
         } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) {
             add_node_error(g, field_access_node,
                 buf_sprintf("enum value '%s.%s' requires parameter of type '%s'",
src/codegen.cpp
@@ -2567,7 +2567,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
                 if (type_entry->data.enumeration.gen_field_count == 0) {
                     return tag_value;
                 } else {
-                    zig_panic("TODO");
+                    TypeTableEntry *union_type = type_entry->data.enumeration.union_type;
+                    TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag];
+                    assert(enum_field->value == const_val->data.x_enum.tag);
+                    LLVMValueRef union_value;
+                    if (type_has_bits(enum_field->type_entry)) {
+                        union_value = gen_const_val(g, union_type, const_val->data.x_enum.payload);
+                    } else {
+                        union_value = LLVMGetUndef(union_type->type_ref);
+                    }
+                    LLVMValueRef fields[] = {
+                        tag_value,
+                        union_value,
+                    };
+                    return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
                 }
             }
         case TypeTableEntryIdFn:
test/self_hosted.zig
@@ -38,11 +38,31 @@ fn call_struct_field(foo: Foo) -> i32 {
 
 
 
+#attribute("test")
+fn redefinition_of_error_values_allowed() {
+    if (error.AnError == error.SecondError) unreachable{}
+}
 error AnError;
 error AnError;
 error SecondError;
 
+
+
+
 #attribute("test")
-fn redefinition_of_error_values_allowed() {
-    if (error.AnError == error.SecondError) unreachable{}
+fn constant_enum_with_payload() {
+    should_be_empty(AnEnumWithPayload.Empty);
+    should_be_13(AnEnumWithPayload.Full(13));
+}
+
+fn should_be_empty(x: AnEnumWithPayload) {
+    if (x != AnEnumWithPayload.Empty) unreachable{}
+}
+
+fn should_be_13(x: AnEnumWithPayload) {
+}
+
+enum AnEnumWithPayload {
+    Empty,
+    Full: i32,
 }