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 {
142142struct TypeEnumField {
143143 Buf *name;
144144 TypeTableEntry *type_entry;
145 uint32_t value; // TODO is this used?
145 uint32_t value;
146146};
147147
148148enum NodeType {
......@@ -453,7 +453,7 @@ struct AstNodeFieldAccessExpr {
453453 Expr resolved_expr;
454454 StructValExprCodeGen resolved_struct_val_expr; // for enum values
455455 bool is_fn_call;
456 TypeTableEntry *bare_struct_type;
456 TypeTableEntry *bare_container_type;
457457 bool is_member_fn;
458458 AstNode *container_init_expr_node;
459459};
src/analyze.cpp+116-38
......@@ -2718,7 +2718,87 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
27182718 }
27192719}
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,
27222802 TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type)
27232803{
27242804 assert(node->type == NodeTypeFieldAccessExpr);
......@@ -2753,56 +2833,54 @@ static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call
27532833 }
27542834}
27552835
2756static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2757 TypeTableEntry *expected_type, AstNode *node)
2836static TypeTableEntry *analyze_container_member_access(CodeGen *g, bool wrapped_in_fn_call,
2837 Buf *field_name, AstNode *node, TypeTableEntry *struct_type)
27582838{
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 }
27742843
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;
27782845
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);
27812848 if (node->data.field_access_expr.type_struct_field) {
27822849 return node->data.field_access_expr.type_struct_field->type_entry;
27832850 } 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,
27852852 node, struct_type);
27862853 }
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);
28002856 if (node->data.field_access_expr.type_enum_field) {
28012857 return node->data.field_access_expr.type_enum_field->type_entry;
28022858 } 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,
28042860 node, struct_type);
28052861 }
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);
28062884 } else if (struct_type->id == TypeTableEntryIdArray) {
28072885 if (buf_eql_str(field_name, "len")) {
28082886 return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,