| ... | @@ -2718,7 +2718,87 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry | ... | @@ -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 | TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type) | 2802 | TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type) |
| 2723 | { | 2803 | { |
| 2724 | assert(node->type == NodeTypeFieldAccessExpr); | 2804 | assert(node->type == NodeTypeFieldAccessExpr); |
| ... | @@ -2753,56 +2833,54 @@ static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call | ... | @@ -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, | 2836 | static TypeTableEntry *analyze_container_member_access(CodeGen *g, bool wrapped_in_fn_call, |
| 2757 | TypeTableEntry *expected_type, AstNode *node) | 2837 | Buf *field_name, AstNode *node, TypeTableEntry *struct_type) |
| 2758 | { | 2838 | { |
| 2759 | assert(node->type == NodeTypeFieldAccessExpr); | 2839 | TypeTableEntry *bare_type = container_ref_type(struct_type); |
| 2760 | | 2840 | if (!type_is_complete(bare_type)) { |
| 2761 | AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr; | 2841 | resolve_container_type(g, bare_type); |
| 2762 | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node); | 2842 | } |
| 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; | | |
| 2774 | | 2843 | |
| 2775 | if (!bare_struct_type->data.structure.complete) { | 2844 | node->data.field_access_expr.bare_container_type = bare_type; |
| 2776 | resolve_struct_type(g, bare_struct_type->data.structure.decl_node->owner, bare_struct_type); | | |
| 2777 | } | | |
| 2778 | | 2845 | |
| 2779 | node->data.field_access_expr.bare_struct_type = bare_struct_type; | 2846 | if (bare_type->id == TypeTableEntryIdStruct) { |
| 2780 | node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name); | 2847 | node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_type, field_name); |
| 2781 | if (node->data.field_access_expr.type_struct_field) { | 2848 | if (node->data.field_access_expr.type_struct_field) { |
| 2782 | return node->data.field_access_expr.type_struct_field->type_entry; | 2849 | return node->data.field_access_expr.type_struct_field->type_entry; |
| 2783 | } else { | 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 | node, struct_type); | 2852 | node, struct_type); |
| 2786 | } | 2853 | } |
| 2787 | } else if (struct_type->id == TypeTableEntryIdEnum || (struct_type->id == TypeTableEntryIdPointer && | 2854 | } else if (bare_type->id == TypeTableEntryIdEnum) { |
| 2788 | struct_type->data.pointer.child_type->id == TypeTableEntryIdEnum)) | 2855 | node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_type, field_name); |
| 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 | | | |
| 2800 | if (node->data.field_access_expr.type_enum_field) { | 2856 | if (node->data.field_access_expr.type_enum_field) { |
| 2801 | return node->data.field_access_expr.type_enum_field->type_entry; | 2857 | return node->data.field_access_expr.type_enum_field->type_entry; |
| 2802 | } else { | 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 | node, struct_type); | 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 | } else if (struct_type->id == TypeTableEntryIdArray) { | 2884 | } else if (struct_type->id == TypeTableEntryIdArray) { |
| 2807 | if (buf_eql_str(field_name, "len")) { | 2885 | if (buf_eql_str(field_name, "len")) { |
| 2808 | return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, | 2886 | return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |