From 36c6acfc76eeeed1498b5cc9ecb3137214e69bbf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Apr 2016 18:52:09 -0700 Subject: enum init uses container init syntax instead of fn call See #5 --- src/all_types.hpp | 3 ++- src/analyze.cpp | 64 ++++++++++++++++++++++++++++++++-------------------- src/codegen.cpp | 29 +++++++++++++----------- src/eval.cpp | 9 ++++---- test/self_hosted.zig | 14 ++++++------ 5 files changed, 69 insertions(+), 50 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index ee71a0ec28..46c0ba0882 100644 --- a/src/all_types.hpp +++ b/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 { diff --git a/src/analyze.cpp b/src/analyze.cpp index 50b51312bf..ef8dbf31e1 100644 --- a/src/analyze.cpp +++ b/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); diff --git a/src/codegen.cpp b/src/codegen.cpp index aa383b9c3b..8aebdf14bd 100644 --- a/src/codegen.cpp +++ b/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); diff --git a/src/eval.cpp b/src/eval.cpp index 1f2a05a247..60051234e2 100644 --- a/src/eval.cpp +++ b/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 && diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 74fb23c464..dd487e7a71 100644 --- a/test/self_hosted.zig +++ b/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) { -- cgit v1.2.3