Commit 36c6acfc76

Andrew Kelley <superjoe30@gmail.com>
2016-04-20 03:52:09
enum init uses container init syntax instead of fn call
See #5
1 parent 7a7f830
src/all_types.hpp
@@ -392,7 +392,6 @@ struct AstNodeFnCallExpr {
     Expr resolved_expr;
     FnTableEntry *fn_entry;
     CastOp cast_op;
-    TypeTableEntry *enum_type;
     // if cast_op is CastOpArrayToString, this will be a pointer to
     // the string struct on the stack
     LLVMValueRef tmp_ptr;
@@ -429,6 +428,7 @@ struct AstNodeFieldAccessExpr {
     bool is_fn_call;
     TypeTableEntry *bare_struct_type;
     bool is_member_fn;
+    AstNode *container_init_expr_node;
 };
 
 struct AstNodeDirective {
@@ -665,6 +665,7 @@ struct AstNodeContainerInitExpr {
     // populated by semantic analyzer
     StructValExprCodeGen resolved_struct_val_expr;
     Expr resolved_expr;
+    TypeTableEntry *enum_type;
 };
 
 struct AstNodeNullLiteral {
src/analyze.cpp
@@ -2197,7 +2197,23 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
 
     ContainerInitKind kind = container_init_expr->kind;
 
-    TypeTableEntry *container_type = analyze_type_expr(g, import, context, container_init_expr->type);
+    if (container_init_expr->type->type == NodeTypeFieldAccessExpr) {
+        container_init_expr->type->data.field_access_expr.container_init_expr_node = node;
+    }
+
+    TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr,
+            container_init_expr->type);
+
+    if (container_meta_type->id == TypeTableEntryIdInvalid) {
+        return g->builtin_types.entry_invalid;
+    }
+
+    if (node->data.container_init_expr.enum_type) {
+        get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val;
+        return node->data.container_init_expr.enum_type;
+    }
+
+    TypeTableEntry *container_type = resolve_type(g, container_init_expr->type);
 
     if (container_type->id == TypeTableEntryIdInvalid) {
         return container_type;
@@ -2322,9 +2338,6 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
     } else if (container_type->id == TypeTableEntryIdArray) {
         zig_panic("TODO array container init");
         return container_type;
-    } else if (container_type->id == TypeTableEntryIdEnum) {
-        zig_panic("TODO enum container init");
-        return container_type;
     } else if (container_type->id == TypeTableEntryIdVoid) {
         if (container_init_expr->entries.length != 0) {
             add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
@@ -2414,7 +2427,28 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
         } else if (wrapped_in_fn_call) {
             return resolve_expr_const_val_as_type(g, node, child_type);
         } else if (child_type->id == TypeTableEntryIdEnum) {
-            return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name, node);
+            AstNode *container_init_node = node->data.field_access_expr.container_init_expr_node;
+            AstNode *value_node;
+            if (container_init_node) {
+                assert(container_init_node->type == NodeTypeContainerInitExpr);
+                int param_count = container_init_node->data.container_init_expr.entries.length;
+                if (param_count > 1) {
+                    AstNode *first_invalid_node = container_init_node->data.container_init_expr.entries.at(1);
+                    add_node_error(g, first_executing_node(first_invalid_node),
+                            buf_sprintf("enum values accept only one parameter"));
+                    return child_type;
+                } else {
+                    if (param_count == 1) {
+                        value_node = container_init_node->data.container_init_expr.entries.at(0);
+                    } else {
+                        value_node = nullptr;
+                    }
+                    container_init_node->data.container_init_expr.enum_type = child_type;
+                }
+            } else {
+                value_node = nullptr;
+            }
+            return analyze_enum_value_expr(g, import, context, node, value_node, child_type, field_name, node);
         } else if (child_type->id == TypeTableEntryIdStruct) {
             BlockContext *container_block_context = get_container_block_context(child_type);
             auto entry = container_block_context->decl_table.maybe_get(field_name);
@@ -4725,26 +4759,6 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
 
                 if (child_type->id == TypeTableEntryIdInvalid) {
                     return g->builtin_types.entry_invalid;
-                } else if (child_type->id == TypeTableEntryIdEnum) {
-                    Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
-                    int param_count = node->data.fn_call_expr.params.length;
-                    if (param_count > 1) {
-                        add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)),
-                                buf_sprintf("enum values accept only one parameter"));
-                        return child_type;
-                    } else {
-                        AstNode *value_node;
-                        if (param_count == 1) {
-                            value_node = node->data.fn_call_expr.params.at(0);
-                        } else {
-                            value_node = nullptr;
-                        }
-
-                        node->data.fn_call_expr.enum_type = child_type;
-
-                        return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node,
-                                child_type, field_name, node);
-                    }
                 } else if (child_type->id == TypeTableEntryIdStruct) {
                     Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
                     BlockContext *container_block_context = get_container_block_context(child_type);
src/codegen.cpp
@@ -764,23 +764,11 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
         return gen_cast_expr(g, node);
     }
 
-    AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
-    if (node->data.fn_call_expr.enum_type) {
-        int param_count = node->data.fn_call_expr.params.length;
-        AstNode *arg1_node;
-        if (param_count == 1) {
-            arg1_node = node->data.fn_call_expr.params.at(0);
-        } else {
-            assert(param_count == 0);
-            arg1_node = nullptr;
-        }
-        return gen_enum_value_expr(g, fn_ref_expr, node->data.fn_call_expr.enum_type, arg1_node);
-    }
-
     FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
     TypeTableEntry *struct_type = nullptr;
     AstNode *first_param_expr = nullptr;
 
+    AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
     if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
         fn_ref_expr->data.field_access_expr.is_member_fn)
     {
@@ -2207,6 +2195,21 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
 
     TypeTableEntry *type_entry = get_expr_type(node);
 
+
+    if (node->data.container_init_expr.enum_type) {
+        int param_count = node->data.container_init_expr.entries.length;
+        AstNode *arg1_node;
+        if (param_count == 1) {
+            arg1_node = node->data.container_init_expr.entries.at(0);
+        } else {
+            assert(param_count == 0);
+            arg1_node = nullptr;
+        }
+        return gen_enum_value_expr(g, node->data.container_init_expr.type,
+                node->data.container_init_expr.enum_type, arg1_node);
+    }
+
+
     if (type_entry->id == TypeTableEntryIdStruct) {
         assert(node->data.container_init_expr.kind == ContainerInitKindStruct);
 
src/eval.cpp
@@ -320,6 +320,11 @@ static bool eval_container_init_expr(EvalFn *ef, AstNode *node, ConstExprValue *
 
     AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
     ContainerInitKind kind = container_init_expr->kind;
+
+    if (container_init_expr->enum_type) {
+        zig_panic("TODO");
+    }
+
     TypeTableEntry *container_type = resolve_expr_type(container_init_expr->type);
     out_val->ok = true;
 
@@ -723,10 +728,6 @@ static bool eval_fn_call_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val
         return false;
     }
 
-    if (node->data.fn_call_expr.enum_type) {
-        zig_panic("TODO");
-    }
-
     FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
 
     if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
test/self_hosted.zig
@@ -353,8 +353,8 @@ fn maybe_type() {
 
 #attribute("test")
 fn enum_type() {
-    const foo1 = EnumTypeFoo.One(13);
-    const foo2 = EnumTypeFoo.Two(EnumType { .x = 1234, .y = 5678, });
+    const foo1 = EnumTypeFoo.One {13};
+    const foo2 = EnumTypeFoo.Two {EnumType { .x = 1234, .y = 5678, }};
     const bar = EnumTypeBar.B;
 
     assert(bar == EnumTypeBar.B);
@@ -449,7 +449,7 @@ fn should_be_not_equal(a: error, b: error) {
 #attribute("test")
 fn constant_enum_with_payload() {
     var empty = AnEnumWithPayload.Empty;
-    var full = AnEnumWithPayload.Full(13);
+    var full = AnEnumWithPayload.Full {13};
     should_be_empty(empty);
     should_be_not_empty(full);
 }
@@ -547,8 +547,8 @@ enum SwitchStatmentFoo {
 
 #attribute("test")
 fn switch_prong_with_var() {
-    switch_prong_with_var_fn(SwitchProngWithVarEnum.One(13));
-    switch_prong_with_var_fn(SwitchProngWithVarEnum.Two(13.0));
+    switch_prong_with_var_fn(SwitchProngWithVarEnum.One {13});
+    switch_prong_with_var_fn(SwitchProngWithVarEnum.Two {13.0});
     switch_prong_with_var_fn(SwitchProngWithVarEnum.Meh);
 }
 enum SwitchProngWithVarEnum {
@@ -1221,8 +1221,8 @@ struct Test3Point {
     x: i32,
     y: i32,
 }
-const test3_foo = Test3Foo.Three(Test3Point {.x = 3, .y = 4});
-const test3_bar = Test3Foo.Two(13);
+const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}};
+const test3_bar = Test3Foo.Two{13};
 #static_eval_enable(false)
 fn test3_1(f: Test3Foo) {
     switch (f) {