| ... | @@ -27,7 +27,8 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry * | ... | @@ -27,7 +27,8 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry * |
| 27 | static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 27 | static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 28 | TypeTableEntry *expected_type, AstNode *node); | 28 | TypeTableEntry *expected_type, AstNode *node); |
| 29 | static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node); | 29 | static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node); |
| 30 | static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn); | 30 | static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context, |
| | 31 | FnTableEntry *fn); |
| 31 | static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type); | 32 | static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type); |
| 32 | static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node, | 33 | static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node, |
| 33 | TypeTableEntry *expected_type, uint64_t x); | 34 | TypeTableEntry *expected_type, uint64_t x); |
| ... | @@ -1990,6 +1991,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) { | ... | @@ -1990,6 +1991,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) { |
| 1990 | if (parent) { | 1991 | if (parent) { |
| 1991 | context->parent_loop_node = parent->parent_loop_node; | 1992 | context->parent_loop_node = parent->parent_loop_node; |
| 1992 | context->c_import_buf = parent->c_import_buf; | 1993 | context->c_import_buf = parent->c_import_buf; |
| | 1994 | context->codegen_excluded = parent->codegen_excluded; |
| 1993 | } | 1995 | } |
| 1994 | | 1996 | |
| 1995 | if (node && node->type == NodeTypeFnDef) { | 1997 | if (node && node->type == NodeTypeFnDef) { |
| ... | @@ -2271,7 +2273,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -2271,7 +2273,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 2271 | auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(field_name); | 2273 | auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(field_name); |
| 2272 | if (table_entry) { | 2274 | if (table_entry) { |
| 2273 | node->data.field_access_expr.is_member_fn = true; | 2275 | node->data.field_access_expr.is_member_fn = true; |
| 2274 | return resolve_expr_const_val_as_fn(g, node, table_entry->value); | 2276 | return resolve_expr_const_val_as_fn(g, node, context, table_entry->value); |
| 2275 | } else { | 2277 | } else { |
| 2276 | add_node_error(g, node, buf_sprintf("no member named '%s' in '%s'", | 2278 | add_node_error(g, node, buf_sprintf("no member named '%s' in '%s'", |
| 2277 | buf_ptr(field_name), buf_ptr(&bare_struct_type->name))); | 2279 | buf_ptr(field_name), buf_ptr(&bare_struct_type->name))); |
| ... | @@ -2304,7 +2306,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -2304,7 +2306,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 2304 | } else if (child_type->id == TypeTableEntryIdStruct) { | 2306 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| 2305 | auto entry = child_type->data.structure.fn_table.maybe_get(field_name); | 2307 | auto entry = child_type->data.structure.fn_table.maybe_get(field_name); |
| 2306 | if (entry) { | 2308 | if (entry) { |
| 2307 | return resolve_expr_const_val_as_fn(g, node, entry->value); | 2309 | return resolve_expr_const_val_as_fn(g, node, context, entry->value); |
| 2308 | } else { | 2310 | } else { |
| 2309 | add_node_error(g, node, | 2311 | add_node_error(g, node, |
| 2310 | buf_sprintf("struct '%s' has no function called '%s'", | 2312 | buf_sprintf("struct '%s' has no function called '%s'", |
| ... | @@ -2421,8 +2423,12 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode | ... | @@ -2421,8 +2423,12 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode |
| 2421 | return other_expr->type_entry; | 2423 | return other_expr->type_entry; |
| 2422 | } | 2424 | } |
| 2423 | | 2425 | |
| 2424 | static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) { | 2426 | static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context, |
| 2425 | fn->ref_count += 1; | 2427 | FnTableEntry *fn) |
| | 2428 | { |
| | 2429 | if (!context->codegen_excluded) { |
| | 2430 | fn->ref_count += 1; |
| | 2431 | } |
| 2426 | Expr *expr = get_resolved_expr(node); | 2432 | Expr *expr = get_resolved_expr(node); |
| 2427 | expr->const_val.ok = true; | 2433 | expr->const_val.ok = true; |
| 2428 | expr->const_val.data.x_fn = fn; | 2434 | expr->const_val.data.x_fn = fn; |
| ... | @@ -2604,7 +2610,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -2604,7 +2610,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, |
| 2604 | if (fn_table_entry) { | 2610 | if (fn_table_entry) { |
| 2605 | assert(fn_table_entry->value->type_entry); | 2611 | assert(fn_table_entry->value->type_entry); |
| 2606 | node->data.symbol_expr.fn_entry = fn_table_entry->value; | 2612 | node->data.symbol_expr.fn_entry = fn_table_entry->value; |
| 2607 | return resolve_expr_const_val_as_fn(g, node, fn_table_entry->value); | 2613 | return resolve_expr_const_val_as_fn(g, node, context, fn_table_entry->value); |
| 2608 | } | 2614 | } |
| 2609 | | 2615 | |
| 2610 | add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); | 2616 | add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); |
| ... | @@ -4344,7 +4350,9 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, | ... | @@ -4344,7 +4350,9 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, |
| 4344 | | 4350 | |
| 4345 | node->data.fn_call_expr.fn_entry = fn_table_entry; | 4351 | node->data.fn_call_expr.fn_entry = fn_table_entry; |
| 4346 | | 4352 | |
| 4347 | fn_table_entry->ref_count += 1; | 4353 | if (!context->codegen_excluded) { |
| | 4354 | fn_table_entry->ref_count += 1; |
| | 4355 | } |
| 4348 | | 4356 | |
| 4349 | return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type); | 4357 | return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type); |
| 4350 | | 4358 | |
| ... | @@ -4650,6 +4658,13 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -4650,6 +4658,13 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 4650 | { | 4658 | { |
| 4651 | AstNode **expr_node = &node->data.switch_expr.expr; | 4659 | AstNode **expr_node = &node->data.switch_expr.expr; |
| 4652 | TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node); | 4660 | TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node); |
| | 4661 | ConstExprValue *expr_val = &get_resolved_expr(*expr_node)->const_val; |
| | 4662 | if (expr_val->ok && !expr_val->depends_on_compile_var) { |
| | 4663 | add_node_error(g, first_executing_node(*expr_node), |
| | 4664 | buf_sprintf("value is constant; unnecessary switch statement")); |
| | 4665 | } |
| | 4666 | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| | 4667 | |
| 4653 | | 4668 | |
| 4654 | int prong_count = node->data.switch_expr.prongs.length; | 4669 | int prong_count = node->data.switch_expr.prongs.length; |
| 4655 | AstNode **peer_nodes = allocate<AstNode*>(prong_count); | 4670 | AstNode **peer_nodes = allocate<AstNode*>(prong_count); |
| ... | @@ -4662,113 +4677,132 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -4662,113 +4677,132 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 4662 | add_node_error(g, first_executing_node(*expr_node), | 4677 | add_node_error(g, first_executing_node(*expr_node), |
| 4663 | buf_sprintf("switch on unreachable expression not allowed")); | 4678 | buf_sprintf("switch on unreachable expression not allowed")); |
| 4664 | return g->builtin_types.entry_invalid; | 4679 | return g->builtin_types.entry_invalid; |
| 4665 | } else { | 4680 | } |
| 4666 | int *field_use_counts = nullptr; | | |
| 4667 | if (expr_type->id == TypeTableEntryIdEnum) { | | |
| 4668 | field_use_counts = allocate<int>(expr_type->data.enumeration.field_count); | | |
| 4669 | } | | |
| 4670 | | 4681 | |
| 4671 | AstNode *else_prong = nullptr; | | |
| 4672 | for (int prong_i = 0; prong_i < prong_count; prong_i += 1) { | | |
| 4673 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); | | |
| 4674 | | 4682 | |
| 4675 | TypeTableEntry *var_type; | 4683 | int *field_use_counts = nullptr; |
| 4676 | bool var_is_target_expr; | 4684 | if (expr_type->id == TypeTableEntryIdEnum) { |
| 4677 | if (prong_node->data.switch_prong.items.length == 0) { | 4685 | field_use_counts = allocate<int>(expr_type->data.enumeration.field_count); |
| 4678 | if (else_prong) { | 4686 | } |
| 4679 | add_node_error(g, prong_node, buf_sprintf("multiple else prongs in switch expression")); | 4687 | |
| 4680 | any_errors = true; | 4688 | int const_chosen_prong_index = -1; |
| 4681 | } else { | 4689 | AstNode *else_prong = nullptr; |
| 4682 | else_prong = prong_node; | 4690 | for (int prong_i = 0; prong_i < prong_count; prong_i += 1) { |
| 4683 | } | 4691 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); |
| 4684 | var_type = expr_type; | 4692 | |
| 4685 | var_is_target_expr = true; | 4693 | TypeTableEntry *var_type; |
| | 4694 | bool var_is_target_expr; |
| | 4695 | if (prong_node->data.switch_prong.items.length == 0) { |
| | 4696 | if (else_prong) { |
| | 4697 | add_node_error(g, prong_node, buf_sprintf("multiple else prongs in switch expression")); |
| | 4698 | any_errors = true; |
| 4686 | } else { | 4699 | } else { |
| 4687 | bool all_agree_on_var_type = true; | 4700 | else_prong = prong_node; |
| 4688 | var_type = nullptr; | 4701 | } |
| | 4702 | var_type = expr_type; |
| | 4703 | var_is_target_expr = true; |
| | 4704 | if (const_chosen_prong_index == -1) { |
| | 4705 | const_chosen_prong_index = prong_i; |
| | 4706 | } |
| | 4707 | } else { |
| | 4708 | bool all_agree_on_var_type = true; |
| | 4709 | var_type = nullptr; |
| 4689 | | 4710 | |
| 4690 | for (int item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) { | 4711 | for (int item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) { |
| 4691 | AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); | 4712 | AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); |
| 4692 | if (item_node->type == NodeTypeSwitchRange) { | 4713 | if (item_node->type == NodeTypeSwitchRange) { |
| 4693 | zig_panic("TODO range in switch statement"); | 4714 | zig_panic("TODO range in switch statement"); |
| 4694 | } | 4715 | } |
| 4695 | | 4716 | |
| 4696 | if (expr_type->id == TypeTableEntryIdEnum) { | 4717 | if (expr_type->id == TypeTableEntryIdEnum) { |
| 4697 | if (item_node->type == NodeTypeSymbol) { | 4718 | if (item_node->type == NodeTypeSymbol) { |
| 4698 | Buf *field_name = &item_node->data.symbol_expr.symbol; | 4719 | Buf *field_name = &item_node->data.symbol_expr.symbol; |
| 4699 | TypeEnumField *type_enum_field = get_enum_field(expr_type, field_name); | 4720 | TypeEnumField *type_enum_field = get_enum_field(expr_type, field_name); |
| 4700 | if (type_enum_field) { | 4721 | if (type_enum_field) { |
| 4701 | item_node->data.symbol_expr.enum_field = type_enum_field; | 4722 | item_node->data.symbol_expr.enum_field = type_enum_field; |
| 4702 | if (!var_type) { | 4723 | if (!var_type) { |
| 4703 | var_type = type_enum_field->type_entry; | 4724 | var_type = type_enum_field->type_entry; |
| 4704 | } | 4725 | } |
| 4705 | if (type_enum_field->type_entry != var_type) { | 4726 | if (type_enum_field->type_entry != var_type) { |
| 4706 | all_agree_on_var_type = false; | 4727 | all_agree_on_var_type = false; |
| 4707 | } | 4728 | } |
| 4708 | uint32_t field_index = type_enum_field->value; | 4729 | uint32_t field_index = type_enum_field->value; |
| 4709 | assert(field_use_counts); | 4730 | assert(field_use_counts); |
| 4710 | field_use_counts[field_index] += 1; | 4731 | field_use_counts[field_index] += 1; |
| 4711 | if (field_use_counts[field_index] > 1) { | 4732 | if (field_use_counts[field_index] > 1) { |
| 4712 | add_node_error(g, item_node, | | |
| 4713 | buf_sprintf("duplicate switch value: '%s'", | | |
| 4714 | buf_ptr(type_enum_field->name))); | | |
| 4715 | any_errors = true; | | |
| 4716 | } | | |
| 4717 | } else { | | |
| 4718 | add_node_error(g, item_node, | 4733 | add_node_error(g, item_node, |
| 4719 | buf_sprintf("enum '%s' has no field '%s'", | 4734 | buf_sprintf("duplicate switch value: '%s'", |
| 4720 | buf_ptr(&expr_type->name), buf_ptr(field_name))); | 4735 | buf_ptr(type_enum_field->name))); |
| 4721 | any_errors = true; | 4736 | any_errors = true; |
| 4722 | } | 4737 | } |
| | 4738 | if (!any_errors && expr_val->ok) { |
| | 4739 | if (expr_val->data.x_enum.tag == type_enum_field->value) { |
| | 4740 | const_chosen_prong_index = prong_i; |
| | 4741 | } |
| | 4742 | } |
| 4723 | } else { | 4743 | } else { |
| 4724 | add_node_error(g, item_node, buf_sprintf("expected enum tag name")); | 4744 | add_node_error(g, item_node, |
| | 4745 | buf_sprintf("enum '%s' has no field '%s'", |
| | 4746 | buf_ptr(&expr_type->name), buf_ptr(field_name))); |
| 4725 | any_errors = true; | 4747 | any_errors = true; |
| 4726 | } | 4748 | } |
| 4727 | } else { | 4749 | } else { |
| 4728 | TypeTableEntry *item_type = analyze_expression(g, import, context, expr_type, item_node); | 4750 | add_node_error(g, item_node, buf_sprintf("expected enum tag name")); |
| 4729 | if (item_type->id != TypeTableEntryIdInvalid) { | 4751 | any_errors = true; |
| 4730 | ConstExprValue *const_val = &get_resolved_expr(item_node)->const_val; | | |
| 4731 | if (!const_val->ok) { | | |
| 4732 | add_node_error(g, item_node, | | |
| 4733 | buf_sprintf("unable to resolve constant expression")); | | |
| 4734 | any_errors = true; | | |
| 4735 | } | | |
| 4736 | } | | |
| 4737 | } | 4752 | } |
| 4738 | } | | |
| 4739 | if (!var_type || !all_agree_on_var_type) { | | |
| 4740 | var_type = expr_type; | | |
| 4741 | var_is_target_expr = true; | | |
| 4742 | } else { | 4753 | } else { |
| 4743 | var_is_target_expr = false; | 4754 | if (!any_errors && expr_val->ok) { |
| | 4755 | zig_panic("TODO determine if const exprs are equal"); |
| | 4756 | } |
| | 4757 | TypeTableEntry *item_type = analyze_expression(g, import, context, expr_type, item_node); |
| | 4758 | if (item_type->id != TypeTableEntryIdInvalid) { |
| | 4759 | ConstExprValue *const_val = &get_resolved_expr(item_node)->const_val; |
| | 4760 | if (!const_val->ok) { |
| | 4761 | add_node_error(g, item_node, |
| | 4762 | buf_sprintf("unable to resolve constant expression")); |
| | 4763 | any_errors = true; |
| | 4764 | } |
| | 4765 | } |
| 4744 | } | 4766 | } |
| 4745 | } | 4767 | } |
| 4746 | | 4768 | if (!var_type || !all_agree_on_var_type) { |
| 4747 | BlockContext *child_context = new_block_context(node, context); | 4769 | var_type = expr_type; |
| 4748 | prong_node->data.switch_prong.block_context = child_context; | 4770 | var_is_target_expr = true; |
| 4749 | AstNode *var_node = prong_node->data.switch_prong.var_symbol; | 4771 | } else { |
| 4750 | if (var_node) { | 4772 | var_is_target_expr = false; |
| 4751 | assert(var_node->type == NodeTypeSymbol); | | |
| 4752 | Buf *var_name = &var_node->data.symbol_expr.symbol; | | |
| 4753 | var_node->block_context = child_context; | | |
| 4754 | prong_node->data.switch_prong.var = add_local_var(g, var_node, import, | | |
| 4755 | child_context, var_name, var_type, true); | | |
| 4756 | prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr; | | |
| 4757 | } | 4773 | } |
| | 4774 | } |
| 4758 | | 4775 | |
| 4759 | peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type, | 4776 | BlockContext *child_context = new_block_context(node, context); |
| 4760 | prong_node->data.switch_prong.expr); | 4777 | prong_node->data.switch_prong.block_context = child_context; |
| 4761 | peer_nodes[prong_i] = prong_node->data.switch_prong.expr; | 4778 | AstNode *var_node = prong_node->data.switch_prong.var_symbol; |
| | 4779 | if (var_node) { |
| | 4780 | assert(var_node->type == NodeTypeSymbol); |
| | 4781 | Buf *var_name = &var_node->data.symbol_expr.symbol; |
| | 4782 | var_node->block_context = child_context; |
| | 4783 | prong_node->data.switch_prong.var = add_local_var(g, var_node, import, |
| | 4784 | child_context, var_name, var_type, true); |
| | 4785 | prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr; |
| 4762 | } | 4786 | } |
| | 4787 | } |
| 4763 | | 4788 | |
| 4764 | if (expr_type->id == TypeTableEntryIdEnum && !else_prong) { | 4789 | for (int prong_i = 0; prong_i < prong_count; prong_i += 1) { |
| 4765 | for (uint32_t i = 0; i < expr_type->data.enumeration.field_count; i += 1) { | 4790 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); |
| 4766 | if (field_use_counts[i] == 0) { | 4791 | BlockContext *child_context = prong_node->data.switch_prong.block_context; |
| 4767 | add_node_error(g, node, | 4792 | child_context->codegen_excluded = expr_val->ok && (const_chosen_prong_index != prong_i); |
| 4768 | buf_sprintf("enumeration value '%s' not handled in switch", | 4793 | |
| 4769 | buf_ptr(expr_type->data.enumeration.fields[i].name))); | 4794 | peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type, |
| 4770 | any_errors = true; | 4795 | prong_node->data.switch_prong.expr); |
| 4771 | } | 4796 | peer_nodes[prong_i] = prong_node->data.switch_prong.expr; |
| | 4797 | } |
| | 4798 | |
| | 4799 | if (expr_type->id == TypeTableEntryIdEnum && !else_prong) { |
| | 4800 | for (uint32_t i = 0; i < expr_type->data.enumeration.field_count; i += 1) { |
| | 4801 | if (field_use_counts[i] == 0) { |
| | 4802 | add_node_error(g, node, |
| | 4803 | buf_sprintf("enumeration value '%s' not handled in switch", |
| | 4804 | buf_ptr(expr_type->data.enumeration.fields[i].name))); |
| | 4805 | any_errors = true; |
| 4772 | } | 4806 | } |
| 4773 | } | 4807 | } |
| 4774 | } | 4808 | } |
| ... | @@ -4782,49 +4816,18 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -4782,49 +4816,18 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 4782 | return g->builtin_types.entry_invalid; | 4816 | return g->builtin_types.entry_invalid; |
| 4783 | } | 4817 | } |
| 4784 | | 4818 | |
| 4785 | TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node, | 4819 | if (expr_val->ok) { |
| 4786 | peer_nodes, peer_types, prong_count); | 4820 | assert(const_chosen_prong_index != -1); |
| 4787 | | | |
| 4788 | if (resolved_type->id == TypeTableEntryIdInvalid) { | | |
| 4789 | return resolved_type; | | |
| 4790 | } | | |
| 4791 | | 4821 | |
| 4792 | ConstExprValue *expr_val = &get_resolved_expr(*expr_node)->const_val; | 4822 | *const_val = get_resolved_expr(peer_nodes[const_chosen_prong_index])->const_val; |
| 4793 | if (!expr_val->ok) { | 4823 | const_val->ok = true; |
| 4794 | return resolved_type; | 4824 | // the target expr depends on a compile var, |
| 4795 | } | 4825 | // so the entire if statement does too |
| 4796 | | 4826 | const_val->depends_on_compile_var = true; |
| 4797 | if (expr_val->ok && !expr_val->depends_on_compile_var) { | | |
| 4798 | add_node_error(g, first_executing_node(*expr_node), | | |
| 4799 | buf_sprintf("value is constant; unnecessary switch statement")); | | |
| 4800 | } | 4827 | } |
| 4801 | | 4828 | |
| 4802 | if (!expr_val->ok) { | | |
| 4803 | return resolved_type; | | |
| 4804 | } | | |
| 4805 | | 4829 | |
| 4806 | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | 4830 | return resolve_peer_type_compatibility(g, import, context, node, peer_nodes, peer_types, prong_count); |
| 4807 | | | |
| 4808 | for (int prong_i = 0; prong_i < prong_count; prong_i += 1) { | | |
| 4809 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); | | |
| 4810 | for (int item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) { | | |
| 4811 | AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); | | |
| 4812 | if (expr_type->id == TypeTableEntryIdEnum) { | | |
| 4813 | TypeEnumField *type_enum_field = item_node->data.symbol_expr.enum_field; | | |
| 4814 | if (expr_val->data.x_enum.tag == type_enum_field->value) { | | |
| 4815 | *const_val = get_resolved_expr(peer_nodes[prong_i])->const_val; | | |
| 4816 | const_val->ok = true; | | |
| 4817 | // the target expr depends on a compile var, so the entire if statement does too | | |
| 4818 | const_val->depends_on_compile_var = true; | | |
| 4819 | return resolved_type; | | |
| 4820 | } | | |
| 4821 | } else { | | |
| 4822 | zig_panic("TODO determine if const exprs are equal"); | | |
| 4823 | } | | |
| 4824 | } | | |
| 4825 | } | | |
| 4826 | | | |
| 4827 | zig_unreachable(); | | |
| 4828 | } | 4831 | } |
| 4829 | | 4832 | |
| 4830 | static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 4833 | static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |