| ... | ... | @@ -2718,7 +2718,87 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry |
| 2718 | 2718 | } |
| 2719 | 2719 | } |
| 2720 | 2720 | |
| 2721 | | static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call, |
| 2721 | static bool is_container(TypeTableEntry *type_entry) { |
| 2722 | switch (type_entry->id) { |
| 2723 | case TypeTableEntryIdInvalid: |
| 2724 | case TypeTableEntryIdVar: |
| 2725 | zig_unreachable(); |
| 2726 | case TypeTableEntryIdStruct: |
| 2727 | case TypeTableEntryIdEnum: |
| 2728 | case TypeTableEntryIdUnion: |
| 2729 | return true; |
| 2730 | case TypeTableEntryIdPointer: |
| 2731 | case TypeTableEntryIdMetaType: |
| 2732 | case TypeTableEntryIdVoid: |
| 2733 | case TypeTableEntryIdBool: |
| 2734 | case TypeTableEntryIdUnreachable: |
| 2735 | case TypeTableEntryIdInt: |
| 2736 | case TypeTableEntryIdFloat: |
| 2737 | case TypeTableEntryIdArray: |
| 2738 | case TypeTableEntryIdNumLitFloat: |
| 2739 | case TypeTableEntryIdNumLitInt: |
| 2740 | case TypeTableEntryIdUndefLit: |
| 2741 | case TypeTableEntryIdNullLit: |
| 2742 | case TypeTableEntryIdMaybe: |
| 2743 | case TypeTableEntryIdErrorUnion: |
| 2744 | case TypeTableEntryIdPureError: |
| 2745 | case TypeTableEntryIdFn: |
| 2746 | case TypeTableEntryIdTypeDecl: |
| 2747 | case TypeTableEntryIdNamespace: |
| 2748 | case TypeTableEntryIdGenericFn: |
| 2749 | return false; |
| 2750 | } |
| 2751 | zig_unreachable(); |
| 2752 | } |
| 2753 | |
| 2754 | static bool is_container_ref(TypeTableEntry *type_entry) { |
| 2755 | return (type_entry->id == TypeTableEntryIdPointer) ? |
| 2756 | is_container(type_entry->data.pointer.child_type) : is_container(type_entry); |
| 2757 | } |
| 2758 | |
| 2759 | static TypeTableEntry *container_ref_type(TypeTableEntry *type_entry) { |
| 2760 | assert(is_container_ref(type_entry)); |
| 2761 | return (type_entry->id == TypeTableEntryIdPointer) ? |
| 2762 | type_entry->data.pointer.child_type : type_entry; |
| 2763 | } |
| 2764 | |
| 2765 | static void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { |
| 2766 | switch (type_entry->id) { |
| 2767 | case TypeTableEntryIdStruct: |
| 2768 | resolve_struct_type(g, type_entry->data.structure.decl_node->owner, type_entry); |
| 2769 | break; |
| 2770 | case TypeTableEntryIdEnum: |
| 2771 | resolve_enum_type(g, type_entry->data.enumeration.decl_node->owner, type_entry); |
| 2772 | break; |
| 2773 | case TypeTableEntryIdUnion: |
| 2774 | resolve_union_type(g, type_entry->data.unionation.decl_node->owner, type_entry); |
| 2775 | break; |
| 2776 | case TypeTableEntryIdPointer: |
| 2777 | case TypeTableEntryIdMetaType: |
| 2778 | case TypeTableEntryIdVoid: |
| 2779 | case TypeTableEntryIdBool: |
| 2780 | case TypeTableEntryIdUnreachable: |
| 2781 | case TypeTableEntryIdInt: |
| 2782 | case TypeTableEntryIdFloat: |
| 2783 | case TypeTableEntryIdArray: |
| 2784 | case TypeTableEntryIdNumLitFloat: |
| 2785 | case TypeTableEntryIdNumLitInt: |
| 2786 | case TypeTableEntryIdUndefLit: |
| 2787 | case TypeTableEntryIdNullLit: |
| 2788 | case TypeTableEntryIdMaybe: |
| 2789 | case TypeTableEntryIdErrorUnion: |
| 2790 | case TypeTableEntryIdPureError: |
| 2791 | case TypeTableEntryIdFn: |
| 2792 | case TypeTableEntryIdTypeDecl: |
| 2793 | case TypeTableEntryIdNamespace: |
| 2794 | case TypeTableEntryIdGenericFn: |
| 2795 | case TypeTableEntryIdInvalid: |
| 2796 | case TypeTableEntryIdVar: |
| 2797 | zig_unreachable(); |
| 2798 | } |
| 2799 | } |
| 2800 | |
| 2801 | static TypeTableEntry *analyze_container_member_access_inner(CodeGen *g, bool wrapped_in_fn_call, |
| 2722 | 2802 | TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type) |
| 2723 | 2803 | { |
| 2724 | 2804 | assert(node->type == NodeTypeFieldAccessExpr); |
| ... | ... | @@ -2753,56 +2833,54 @@ static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call |
| 2753 | 2833 | } |
| 2754 | 2834 | } |
| 2755 | 2835 | |
| 2756 | | static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2757 | | TypeTableEntry *expected_type, AstNode *node) |
| 2836 | static TypeTableEntry *analyze_container_member_access(CodeGen *g, bool wrapped_in_fn_call, |
| 2837 | Buf *field_name, AstNode *node, TypeTableEntry *struct_type) |
| 2758 | 2838 | { |
| 2759 | | assert(node->type == NodeTypeFieldAccessExpr); |
| 2760 | | |
| 2761 | | AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr; |
| 2762 | | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node); |
| 2763 | | Buf *field_name = node->data.field_access_expr.field_name; |
| 2764 | | |
| 2765 | | bool wrapped_in_fn_call = node->data.field_access_expr.is_fn_call; |
| 2766 | | |
| 2767 | | if (struct_type->id == TypeTableEntryIdInvalid) { |
| 2768 | | return struct_type; |
| 2769 | | } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer && |
| 2770 | | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) |
| 2771 | | { |
| 2772 | | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? |
| 2773 | | struct_type : struct_type->data.pointer.child_type; |
| 2839 | TypeTableEntry *bare_type = container_ref_type(struct_type); |
| 2840 | if (!type_is_complete(bare_type)) { |
| 2841 | resolve_container_type(g, bare_type); |
| 2842 | } |
| 2774 | 2843 | |
| 2775 | | if (!bare_struct_type->data.structure.complete) { |
| 2776 | | resolve_struct_type(g, bare_struct_type->data.structure.decl_node->owner, bare_struct_type); |
| 2777 | | } |
| 2844 | node->data.field_access_expr.bare_container_type = bare_type; |
| 2778 | 2845 | |
| 2779 | | node->data.field_access_expr.bare_struct_type = bare_struct_type; |
| 2780 | | node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name); |
| 2846 | if (bare_type->id == TypeTableEntryIdStruct) { |
| 2847 | node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_type, field_name); |
| 2781 | 2848 | if (node->data.field_access_expr.type_struct_field) { |
| 2782 | 2849 | return node->data.field_access_expr.type_struct_field->type_entry; |
| 2783 | 2850 | } else { |
| 2784 | | return analyze_member_access(g, wrapped_in_fn_call, bare_struct_type, field_name, |
| 2851 | return analyze_container_member_access_inner(g, wrapped_in_fn_call, bare_type, field_name, |
| 2785 | 2852 | node, struct_type); |
| 2786 | 2853 | } |
| 2787 | | } else if (struct_type->id == TypeTableEntryIdEnum || (struct_type->id == TypeTableEntryIdPointer && |
| 2788 | | struct_type->data.pointer.child_type->id == TypeTableEntryIdEnum)) |
| 2789 | | { |
| 2790 | | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdEnum) ? |
| 2791 | | struct_type : struct_type->data.pointer.child_type; |
| 2792 | | |
| 2793 | | if (!bare_struct_type->data.enumeration.complete) { |
| 2794 | | resolve_struct_type(g, bare_struct_type->data.enumeration.decl_node->owner, bare_struct_type); |
| 2795 | | } |
| 2796 | | |
| 2797 | | node->data.field_access_expr.bare_struct_type = bare_struct_type; |
| 2798 | | node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_struct_type, field_name); |
| 2799 | | |
| 2854 | } else if (bare_type->id == TypeTableEntryIdEnum) { |
| 2855 | node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_type, field_name); |
| 2800 | 2856 | if (node->data.field_access_expr.type_enum_field) { |
| 2801 | 2857 | return node->data.field_access_expr.type_enum_field->type_entry; |
| 2802 | 2858 | } else { |
| 2803 | | return analyze_member_access(g, wrapped_in_fn_call, bare_struct_type, field_name, |
| 2859 | return analyze_container_member_access_inner(g, wrapped_in_fn_call, bare_type, field_name, |
| 2804 | 2860 | node, struct_type); |
| 2805 | 2861 | } |
| 2862 | } else if (bare_type->id == TypeTableEntryIdUnion) { |
| 2863 | zig_panic("TODO"); |
| 2864 | } else { |
| 2865 | zig_unreachable(); |
| 2866 | } |
| 2867 | } |
| 2868 | |
| 2869 | static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2870 | TypeTableEntry *expected_type, AstNode *node) |
| 2871 | { |
| 2872 | assert(node->type == NodeTypeFieldAccessExpr); |
| 2873 | |
| 2874 | AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr; |
| 2875 | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node); |
| 2876 | Buf *field_name = node->data.field_access_expr.field_name; |
| 2877 | |
| 2878 | bool wrapped_in_fn_call = node->data.field_access_expr.is_fn_call; |
| 2879 | |
| 2880 | if (struct_type->id == TypeTableEntryIdInvalid) { |
| 2881 | return struct_type; |
| 2882 | } else if (is_container_ref(struct_type)) { |
| 2883 | return analyze_container_member_access(g, wrapped_in_fn_call, field_name, node, struct_type); |
| 2806 | 2884 | } else if (struct_type->id == TypeTableEntryIdArray) { |
| 2807 | 2885 | if (buf_eql_str(field_name, "len")) { |
| 2808 | 2886 | return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |