Commit 01e13de7ca

Andrew Kelley <superjoe30@gmail.com>
2016-09-26 06:06:37
refactor field access code into more generic container code
1 parent 683da0e
Changed files (2)
src/all_types.hpp
@@ -142,7 +142,7 @@ struct TopLevelDecl {
 struct TypeEnumField {
     Buf *name;
     TypeTableEntry *type_entry;
-    uint32_t value; // TODO is this used?
+    uint32_t value;
 };
 
 enum NodeType {
@@ -453,7 +453,7 @@ struct AstNodeFieldAccessExpr {
     Expr resolved_expr;
     StructValExprCodeGen resolved_struct_val_expr; // for enum values
     bool is_fn_call;
-    TypeTableEntry *bare_struct_type;
+    TypeTableEntry *bare_container_type;
     bool is_member_fn;
     AstNode *container_init_expr_node;
 };
src/analyze.cpp
@@ -2718,7 +2718,87 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
     }
 }
 
-static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call,
+static bool is_container(TypeTableEntry *type_entry) {
+    switch (type_entry->id) {
+        case TypeTableEntryIdInvalid:
+        case TypeTableEntryIdVar:
+            zig_unreachable();
+        case TypeTableEntryIdStruct:
+        case TypeTableEntryIdEnum:
+        case TypeTableEntryIdUnion:
+            return true;
+        case TypeTableEntryIdPointer:
+        case TypeTableEntryIdMetaType:
+        case TypeTableEntryIdVoid:
+        case TypeTableEntryIdBool:
+        case TypeTableEntryIdUnreachable:
+        case TypeTableEntryIdInt:
+        case TypeTableEntryIdFloat:
+        case TypeTableEntryIdArray:
+        case TypeTableEntryIdNumLitFloat:
+        case TypeTableEntryIdNumLitInt:
+        case TypeTableEntryIdUndefLit:
+        case TypeTableEntryIdNullLit:
+        case TypeTableEntryIdMaybe:
+        case TypeTableEntryIdErrorUnion:
+        case TypeTableEntryIdPureError:
+        case TypeTableEntryIdFn:
+        case TypeTableEntryIdTypeDecl:
+        case TypeTableEntryIdNamespace:
+        case TypeTableEntryIdGenericFn:
+            return false;
+    }
+    zig_unreachable();
+}
+
+static bool is_container_ref(TypeTableEntry *type_entry) {
+    return (type_entry->id == TypeTableEntryIdPointer) ?
+        is_container(type_entry->data.pointer.child_type) : is_container(type_entry);
+}
+
+static TypeTableEntry *container_ref_type(TypeTableEntry *type_entry) {
+    assert(is_container_ref(type_entry));
+    return (type_entry->id == TypeTableEntryIdPointer) ?
+        type_entry->data.pointer.child_type : type_entry;
+}
+
+static void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
+    switch (type_entry->id) {
+        case TypeTableEntryIdStruct:
+            resolve_struct_type(g, type_entry->data.structure.decl_node->owner, type_entry);
+            break;
+        case TypeTableEntryIdEnum:
+            resolve_enum_type(g, type_entry->data.enumeration.decl_node->owner, type_entry);
+            break;
+        case TypeTableEntryIdUnion:
+            resolve_union_type(g, type_entry->data.unionation.decl_node->owner, type_entry);
+            break;
+        case TypeTableEntryIdPointer:
+        case TypeTableEntryIdMetaType:
+        case TypeTableEntryIdVoid:
+        case TypeTableEntryIdBool:
+        case TypeTableEntryIdUnreachable:
+        case TypeTableEntryIdInt:
+        case TypeTableEntryIdFloat:
+        case TypeTableEntryIdArray:
+        case TypeTableEntryIdNumLitFloat:
+        case TypeTableEntryIdNumLitInt:
+        case TypeTableEntryIdUndefLit:
+        case TypeTableEntryIdNullLit:
+        case TypeTableEntryIdMaybe:
+        case TypeTableEntryIdErrorUnion:
+        case TypeTableEntryIdPureError:
+        case TypeTableEntryIdFn:
+        case TypeTableEntryIdTypeDecl:
+        case TypeTableEntryIdNamespace:
+        case TypeTableEntryIdGenericFn:
+        case TypeTableEntryIdInvalid:
+        case TypeTableEntryIdVar:
+            zig_unreachable();
+    }
+}
+
+static TypeTableEntry *analyze_container_member_access_inner(CodeGen *g, bool wrapped_in_fn_call,
     TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type)
 {
     assert(node->type == NodeTypeFieldAccessExpr);
@@ -2753,56 +2833,54 @@ static TypeTableEntry *analyze_member_access(CodeGen *g, bool wrapped_in_fn_call
     }
 }
 
-static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
-        TypeTableEntry *expected_type, AstNode *node)
+static TypeTableEntry *analyze_container_member_access(CodeGen *g, bool wrapped_in_fn_call,
+        Buf *field_name, AstNode *node, TypeTableEntry *struct_type)
 {
-    assert(node->type == NodeTypeFieldAccessExpr);
-
-    AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr;
-    TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node);
-    Buf *field_name = node->data.field_access_expr.field_name;
-
-    bool wrapped_in_fn_call = node->data.field_access_expr.is_fn_call;
-
-    if (struct_type->id == TypeTableEntryIdInvalid) {
-        return struct_type;
-    } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
-         struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
-    {
-        TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
-            struct_type : struct_type->data.pointer.child_type;
+    TypeTableEntry *bare_type = container_ref_type(struct_type);
+    if (!type_is_complete(bare_type)) {
+        resolve_container_type(g, bare_type);
+    }
 
-        if (!bare_struct_type->data.structure.complete) {
-            resolve_struct_type(g, bare_struct_type->data.structure.decl_node->owner, bare_struct_type);
-        }
+    node->data.field_access_expr.bare_container_type = bare_type;
 
-        node->data.field_access_expr.bare_struct_type = bare_struct_type;
-        node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name);
+    if (bare_type->id == TypeTableEntryIdStruct) {
+        node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_type, field_name);
         if (node->data.field_access_expr.type_struct_field) {
             return node->data.field_access_expr.type_struct_field->type_entry;
         } else {
-            return analyze_member_access(g, wrapped_in_fn_call, bare_struct_type, field_name,
+            return analyze_container_member_access_inner(g, wrapped_in_fn_call, bare_type, field_name,
                 node, struct_type);
         }
-    } else if (struct_type->id == TypeTableEntryIdEnum || (struct_type->id == TypeTableEntryIdPointer &&
-        struct_type->data.pointer.child_type->id == TypeTableEntryIdEnum))
-    {
-        TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdEnum) ?
-            struct_type : struct_type->data.pointer.child_type;
-
-        if (!bare_struct_type->data.enumeration.complete) {
-            resolve_struct_type(g, bare_struct_type->data.enumeration.decl_node->owner, bare_struct_type);
-        }
-
-        node->data.field_access_expr.bare_struct_type = bare_struct_type;
-        node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_struct_type, field_name);
-
+    } else if (bare_type->id == TypeTableEntryIdEnum) {
+        node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_type, field_name);
         if (node->data.field_access_expr.type_enum_field) {
             return node->data.field_access_expr.type_enum_field->type_entry;
         } else {
-            return analyze_member_access(g, wrapped_in_fn_call, bare_struct_type, field_name,
+            return analyze_container_member_access_inner(g, wrapped_in_fn_call, bare_type, field_name,
                 node, struct_type);
         }
+    } else if (bare_type->id == TypeTableEntryIdUnion) {
+        zig_panic("TODO");
+    } else {
+        zig_unreachable();
+    }
+}
+
+static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
+        TypeTableEntry *expected_type, AstNode *node)
+{
+    assert(node->type == NodeTypeFieldAccessExpr);
+
+    AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr;
+    TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node);
+    Buf *field_name = node->data.field_access_expr.field_name;
+
+    bool wrapped_in_fn_call = node->data.field_access_expr.is_fn_call;
+
+    if (struct_type->id == TypeTableEntryIdInvalid) {
+        return struct_type;
+    } else if (is_container_ref(struct_type)) {
+        return analyze_container_member_access(g, wrapped_in_fn_call, field_name, node, struct_type);
     } else if (struct_type->id == TypeTableEntryIdArray) {
         if (buf_eql_str(field_name, "len")) {
             return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,