authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-26 00:06:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-26 00:06:37-04:00
log01e13de7ca39bbc9208d49e14066f72a7f168163
treef8c329440d549d14be14ed1d5029a3b32d2db5bb
parent683da0e4ecd336f9a74098d49d5748bdc1ed2f70

refactor field access code into more generic container code


2 files changed, 118 insertions(+), 40 deletions(-)

src/all_types.hpp+2-2
...@@ -142,7 +142,7 @@ struct TopLevelDecl {...@@ -142,7 +142,7 @@ struct TopLevelDecl {
142struct TypeEnumField {142struct TypeEnumField {
143 Buf *name;143 Buf *name;
144 TypeTableEntry *type_entry;144 TypeTableEntry *type_entry;
145 uint32_t value; // TODO is this used?145 uint32_t value;
146};146};
147147
148enum NodeType {148enum NodeType {
...@@ -453,7 +453,7 @@ struct AstNodeFieldAccessExpr {...@@ -453,7 +453,7 @@ struct AstNodeFieldAccessExpr {
453 Expr resolved_expr;453 Expr resolved_expr;
454 StructValExprCodeGen resolved_struct_val_expr; // for enum values454 StructValExprCodeGen resolved_struct_val_expr; // for enum values
455 bool is_fn_call;455 bool is_fn_call;
456 TypeTableEntry *bare_struct_type;456 TypeTableEntry *bare_container_type;
457 bool is_member_fn;457 bool is_member_fn;
458 AstNode *container_init_expr_node;458 AstNode *container_init_expr_node;
459};459};
src/analyze.cpp+116-38
...@@ -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}
27202720
2721static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call,2721static 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
2754static 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
2759static 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
2765static 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
2801static 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}
27552835
2756static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2836static 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);
27602840 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;
27742843
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 }
27782845
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
2869static 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,