| ... | ... | @@ -1325,7 +1325,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 1325 | 1325 | |
| 1326 | 1326 | uint32_t field_count = decl_node->data.struct_decl.fields.length; |
| 1327 | 1327 | |
| 1328 | | enum_type->data.enumeration.field_count = field_count; |
| 1328 | enum_type->data.enumeration.src_field_count = field_count; |
| 1329 | 1329 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); |
| 1330 | 1330 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| 1331 | 1331 | |
| ... | ... | @@ -2451,8 +2451,8 @@ static LabelTableEntry *find_label(CodeGen *g, BlockContext *orig_context, Buf * |
| 2451 | 2451 | return nullptr; |
| 2452 | 2452 | } |
| 2453 | 2453 | |
| 2454 | | static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) { |
| 2455 | | for (uint32_t i = 0; i < enum_type->data.enumeration.field_count; i += 1) { |
| 2454 | static TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) { |
| 2455 | for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) { |
| 2456 | 2456 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; |
| 2457 | 2457 | if (buf_eql_buf(type_enum_field->name, name)) { |
| 2458 | 2458 | return type_enum_field; |
| ... | ... | @@ -2467,7 +2467,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp |
| 2467 | 2467 | { |
| 2468 | 2468 | assert(field_access_node->type == NodeTypeFieldAccessExpr); |
| 2469 | 2469 | |
| 2470 | | TypeEnumField *type_enum_field = get_enum_field(enum_type, field_name); |
| 2470 | TypeEnumField *type_enum_field = find_enum_type_field(enum_type, field_name); |
| 2471 | 2471 | if (type_enum_field->type_entry->id == TypeTableEntryIdInvalid) { |
| 2472 | 2472 | return g->builtin_types.entry_invalid; |
| 2473 | 2473 | } |
| ... | ... | @@ -2715,6 +2715,41 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry |
| 2715 | 2715 | } |
| 2716 | 2716 | } |
| 2717 | 2717 | |
| 2718 | static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call, |
| 2719 | TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type) |
| 2720 | { |
| 2721 | assert(node->type == NodeTypeFieldAccessExpr); |
| 2722 | if (wrapped_in_fn_call && !is_slice(bare_struct_type)) { |
| 2723 | BlockContext *container_block_context = get_container_block_context(bare_struct_type); |
| 2724 | assert(container_block_context); |
| 2725 | auto entry = container_block_context->decl_table.maybe_get(field_name); |
| 2726 | AstNode *fn_decl_node = entry ? entry->value : nullptr; |
| 2727 | if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { |
| 2728 | resolve_top_level_decl(g, fn_decl_node, false); |
| 2729 | TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node); |
| 2730 | if (tld->resolution == TldResolutionInvalid) { |
| 2731 | return g->builtin_types.entry_invalid; |
| 2732 | } |
| 2733 | |
| 2734 | node->data.field_access_expr.is_member_fn = true; |
| 2735 | FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry; |
| 2736 | if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) { |
| 2737 | return resolve_expr_const_val_as_generic_fn(g, node, fn_entry->type_entry, false); |
| 2738 | } else { |
| 2739 | return resolve_expr_const_val_as_fn(g, node, fn_entry, false); |
| 2740 | } |
| 2741 | } else { |
| 2742 | add_node_error(g, node, buf_sprintf("no function named '%s' in '%s'", |
| 2743 | buf_ptr(field_name), buf_ptr(&bare_struct_type->name))); |
| 2744 | return g->builtin_types.entry_invalid; |
| 2745 | } |
| 2746 | } else { |
| 2747 | add_node_error(g, node, |
| 2748 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name))); |
| 2749 | return g->builtin_types.entry_invalid; |
| 2750 | } |
| 2751 | } |
| 2752 | |
| 2718 | 2753 | static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2719 | 2754 | TypeTableEntry *expected_type, AstNode *node) |
| 2720 | 2755 | { |
| ... | ... | @@ -2742,34 +2777,28 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 2742 | 2777 | node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name); |
| 2743 | 2778 | if (node->data.field_access_expr.type_struct_field) { |
| 2744 | 2779 | return node->data.field_access_expr.type_struct_field->type_entry; |
| 2745 | | } else if (wrapped_in_fn_call && !is_slice(bare_struct_type)) { |
| 2746 | | BlockContext *container_block_context = get_container_block_context(bare_struct_type); |
| 2747 | | assert(container_block_context); |
| 2748 | | auto entry = container_block_context->decl_table.maybe_get(field_name); |
| 2749 | | AstNode *fn_decl_node = entry ? entry->value : nullptr; |
| 2750 | | if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { |
| 2751 | | resolve_top_level_decl(g, fn_decl_node, false); |
| 2752 | | TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node); |
| 2753 | | if (tld->resolution == TldResolutionInvalid) { |
| 2754 | | return g->builtin_types.entry_invalid; |
| 2755 | | } |
| 2780 | } else { |
| 2781 | return analyze_member_access(g, wrapped_in_fn_call, bare_struct_type, field_name, |
| 2782 | node, struct_type); |
| 2783 | } |
| 2784 | } else if (struct_type->id == TypeTableEntryIdEnum || (struct_type->id == TypeTableEntryIdPointer && |
| 2785 | struct_type->data.pointer.child_type->id == TypeTableEntryIdEnum)) |
| 2786 | { |
| 2787 | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdEnum) ? |
| 2788 | struct_type : struct_type->data.pointer.child_type; |
| 2756 | 2789 | |
| 2757 | | node->data.field_access_expr.is_member_fn = true; |
| 2758 | | FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry; |
| 2759 | | if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) { |
| 2760 | | return resolve_expr_const_val_as_generic_fn(g, node, fn_entry->type_entry, false); |
| 2761 | | } else { |
| 2762 | | return resolve_expr_const_val_as_fn(g, node, fn_entry, false); |
| 2763 | | } |
| 2764 | | } else { |
| 2765 | | add_node_error(g, node, buf_sprintf("no function named '%s' in '%s'", |
| 2766 | | buf_ptr(field_name), buf_ptr(&bare_struct_type->name))); |
| 2767 | | return g->builtin_types.entry_invalid; |
| 2768 | | } |
| 2790 | if (!bare_struct_type->data.enumeration.complete) { |
| 2791 | resolve_struct_type(g, bare_struct_type->data.enumeration.decl_node->owner, bare_struct_type); |
| 2792 | } |
| 2793 | |
| 2794 | node->data.field_access_expr.bare_struct_type = bare_struct_type; |
| 2795 | node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_struct_type, field_name); |
| 2796 | |
| 2797 | if (node->data.field_access_expr.type_enum_field) { |
| 2798 | return node->data.field_access_expr.type_enum_field->type_entry; |
| 2769 | 2799 | } else { |
| 2770 | | add_node_error(g, node, |
| 2771 | | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name))); |
| 2772 | | return g->builtin_types.entry_invalid; |
| 2800 | return analyze_member_access(g, wrapped_in_fn_call, bare_struct_type, field_name, |
| 2801 | node, struct_type); |
| 2773 | 2802 | } |
| 2774 | 2803 | } else if (struct_type->id == TypeTableEntryIdArray) { |
| 2775 | 2804 | if (buf_eql_str(field_name, "len")) { |
| ... | ... | @@ -5269,7 +5298,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 5269 | 5298 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 5270 | 5299 | return type_entry; |
| 5271 | 5300 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 5272 | | uint64_t value_count = type_entry->data.enumeration.field_count; |
| 5301 | uint64_t value_count = type_entry->data.enumeration.src_field_count; |
| 5273 | 5302 | return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |
| 5274 | 5303 | value_count, false); |
| 5275 | 5304 | } else { |
| ... | ... | @@ -6130,7 +6159,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 6130 | 6159 | size_t *field_use_counts = nullptr; |
| 6131 | 6160 | HashMap<int, AstNode *, int_hash, int_eq> err_use_nodes = {}; |
| 6132 | 6161 | if (expr_type->id == TypeTableEntryIdEnum) { |
| 6133 | | field_use_counts = allocate<size_t>(expr_type->data.enumeration.field_count); |
| 6162 | field_use_counts = allocate<size_t>(expr_type->data.enumeration.src_field_count); |
| 6134 | 6163 | } else if (expr_type->id == TypeTableEntryIdErrorUnion) { |
| 6135 | 6164 | err_use_nodes.init(10); |
| 6136 | 6165 | } |
| ... | ... | @@ -6168,7 +6197,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 6168 | 6197 | if (expr_type->id == TypeTableEntryIdEnum) { |
| 6169 | 6198 | if (item_node->type == NodeTypeSymbol) { |
| 6170 | 6199 | Buf *field_name = item_node->data.symbol_expr.symbol; |
| 6171 | | TypeEnumField *type_enum_field = get_enum_field(expr_type, field_name); |
| 6200 | TypeEnumField *type_enum_field = find_enum_type_field(expr_type, field_name); |
| 6172 | 6201 | if (type_enum_field) { |
| 6173 | 6202 | item_node->data.symbol_expr.enum_field = type_enum_field; |
| 6174 | 6203 | if (!var_type) { |
| ... | ... | @@ -6300,7 +6329,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, |
| 6300 | 6329 | } |
| 6301 | 6330 | |
| 6302 | 6331 | if (expr_type->id == TypeTableEntryIdEnum && !else_prong) { |
| 6303 | | for (uint32_t i = 0; i < expr_type->data.enumeration.field_count; i += 1) { |
| 6332 | for (uint32_t i = 0; i < expr_type->data.enumeration.src_field_count; i += 1) { |
| 6304 | 6333 | if (field_use_counts[i] == 0) { |
| 6305 | 6334 | add_node_error(g, node, |
| 6306 | 6335 | buf_sprintf("enumeration value '%s' not handled in switch", |