Commit 46ab981787

Andrew Kelley <superjoe30@gmail.com>
2016-04-24 20:24:04
add skeleton for union support
1 parent 4961910
doc/vim/syntax/zig.vim
@@ -8,7 +8,7 @@ if exists("b:current_syntax")
 endif
 
 syn keyword zigStorage const var extern volatile export pub noalias inline
-syn keyword zigStructure struct enum
+syn keyword zigStructure struct enum union
 syn keyword zigStatement goto break return continue asm defer
 syn keyword zigConditional if else switch
 syn keyword zigRepeat while for
doc/langref.md
@@ -15,7 +15,7 @@ GlobalVarDecl = VariableDeclaration ";"
 
 VariableDeclaration = ("var" | "const") "Symbol" option(":" TypeExpr) "=" Expression
 
-ContainerDecl = ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
+ContainerDecl = ("struct" | "enum" | "union") "Symbol" "{" many(StructMember) "}"
 
 StructMember = many(Directive) option(VisibleMod) (StructField | FnDef)
 
src/all_types.hpp
@@ -135,7 +135,7 @@ struct TopLevelDecl {
 struct TypeEnumField {
     Buf *name;
     TypeTableEntry *type_entry;
-    uint32_t value;
+    uint32_t value; // TODO is this used?
 };
 
 enum NodeType {
@@ -590,6 +590,7 @@ struct AstNodeAsmExpr {
 enum ContainerKind {
     ContainerKindStruct,
     ContainerKindEnum,
+    ContainerKindUnion,
 };
 
 struct AstNodeStructDecl {
@@ -905,6 +906,22 @@ struct TypeTableEntryEnum {
     bool complete;
 };
 
+struct TypeTableEntryUnion {
+    AstNode *decl_node;
+    uint32_t src_field_count;
+    uint32_t gen_field_count;
+    TypeStructField *fields;
+    uint64_t size_bytes;
+    bool is_invalid; // true if any fields are invalid
+    BlockContext *block_context;
+
+    // set this flag temporarily to detect infinite loops
+    bool embedded_in_current;
+    bool reported_infinite_err;
+    // whether we've finished resolving it
+    bool complete;
+};
+
 struct FnGenParamInfo {
     int src_index;
     int gen_index;
@@ -949,6 +966,7 @@ enum TypeTableEntryId {
     TypeTableEntryIdErrorUnion,
     TypeTableEntryIdPureError,
     TypeTableEntryIdEnum,
+    TypeTableEntryIdUnion,
     TypeTableEntryIdFn,
     TypeTableEntryIdTypeDecl,
     TypeTableEntryIdNamespace,
@@ -974,6 +992,7 @@ struct TypeTableEntry {
         TypeTableEntryMaybe maybe;
         TypeTableEntryError error;
         TypeTableEntryEnum enumeration;
+        TypeTableEntryUnion unionation;
         TypeTableEntryFn fn;
         TypeTableEntryTypeDecl type_decl;
         TypeTableEntryGenericFn generic_fn;
src/analyze.cpp
@@ -141,6 +141,8 @@ static BlockContext **get_container_block_context_ptr(TypeTableEntry *type_entry
         return &type_entry->data.structure.block_context;
     } else if (type_entry->id == TypeTableEntryIdEnum) {
         return &type_entry->data.enumeration.block_context;
+    } else if (type_entry->id == TypeTableEntryIdUnion) {
+        return &type_entry->data.unionation.block_context;
     }
     zig_unreachable();
 }
@@ -178,6 +180,8 @@ static bool type_is_complete(TypeTableEntry *type_entry) {
             return type_entry->data.structure.complete;
         case TypeTableEntryIdEnum:
             return type_entry->data.enumeration.complete;
+        case TypeTableEntryIdUnion:
+            return type_entry->data.unionation.complete;
         case TypeTableEntryIdMetaType:
         case TypeTableEntryIdVoid:
         case TypeTableEntryIdBool:
@@ -732,6 +736,8 @@ static TypeTableEntryId container_to_type(ContainerKind kind) {
             return TypeTableEntryIdStruct;
         case ContainerKindEnum:
             return TypeTableEntryIdEnum;
+        case ContainerKindUnion:
+            return TypeTableEntryIdUnion;
     }
     zig_unreachable();
 }
@@ -749,6 +755,9 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
         case ContainerKindEnum:
             entry->data.enumeration.decl_node = decl_node;
             break;
+        case ContainerKindUnion:
+            entry->data.unionation.decl_node = decl_node;
+            break;
     }
 
     unsigned line = decl_node ? decl_node->line : 0;
@@ -874,6 +883,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
             case TypeTableEntryIdErrorUnion:
             case TypeTableEntryIdPureError:
             case TypeTableEntryIdEnum:
+            case TypeTableEntryIdUnion:
             case TypeTableEntryIdFn:
             case TypeTableEntryIdTypeDecl:
                 break;
@@ -1397,6 +1407,10 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
     struct_type->zero_bits = (debug_size_in_bits == 0);
 }
 
+static void resolve_union_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type) {
+    zig_panic("TODO");
+}
+
 static void get_fully_qualified_decl_name(Buf *buf, AstNode *decl_node, uint8_t sep) {
     TopLevelDecl *tld = get_as_top_level_decl(decl_node);
     AstNode *parent_decl = tld->parent_decl;
@@ -1541,6 +1555,9 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only)
                     case ContainerKindEnum:
                         resolve_enum_type(g, import, type_entry);
                         break;
+                    case ContainerKindUnion:
+                        resolve_union_type(g, import, type_entry);
+                        break;
                 }
 
                 break;
@@ -1672,6 +1689,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
         case TypeTableEntryIdErrorUnion:
         case TypeTableEntryIdPureError:
         case TypeTableEntryIdEnum:
+        case TypeTableEntryIdUnion:
         case TypeTableEntryIdFn:
             return true;
 
@@ -4450,6 +4468,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
                     case TypeTableEntryIdErrorUnion:
                     case TypeTableEntryIdPureError:
                     case TypeTableEntryIdEnum:
+                    case TypeTableEntryIdUnion:
                     case TypeTableEntryIdFn:
                     case TypeTableEntryIdTypeDecl:
                         return resolve_expr_const_val_as_type(g, node, type_entry);
@@ -6179,6 +6198,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
              return false;
         case TypeTableEntryIdArray:
         case TypeTableEntryIdStruct:
+        case TypeTableEntryIdUnion:
              return true;
         case TypeTableEntryIdErrorUnion:
              return type_has_bits(type_entry->data.error.child_type);
@@ -6280,6 +6300,9 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)
         case TypeTableEntryIdStruct:
             // TODO better hashing algorithm
             return 1532530855;
+        case TypeTableEntryIdUnion:
+            // TODO better hashing algorithm
+            return 2709806591;
         case TypeTableEntryIdMaybe:
             if (const_val->data.x_maybe) {
                 TypeTableEntry *child_type = type->data.maybe.child_type;
@@ -6374,6 +6397,8 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
             return type_of_first_thing_in_memory(type_entry->data.array.child_type);
         case TypeTableEntryIdStruct:
             return type_of_first_thing_in_memory(first_struct_field_type(type_entry));
+        case TypeTableEntryIdUnion:
+            zig_panic("TODO");
         case TypeTableEntryIdMaybe:
             return type_of_first_thing_in_memory(type_entry->data.maybe.child_type);
         case TypeTableEntryIdErrorUnion:
src/ast_render.cpp
@@ -84,6 +84,7 @@ static const char *container_string(ContainerKind kind) {
     switch (kind) {
         case ContainerKindEnum: return "enum";
         case ContainerKindStruct: return "struct";
+        case ContainerKindUnion: return "union";
     }
     zig_unreachable();
 }
src/codegen.cpp
@@ -2972,6 +2972,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
                 return LLVMConstNamedStruct(type_entry->type_ref, fields,
                         type_entry->data.structure.gen_field_count);
             }
+        case TypeTableEntryIdUnion:
+            {
+                zig_panic("TODO");
+            }
         case TypeTableEntryIdArray:
             {
                 TypeTableEntry *child_type = type_entry->data.array.child_type;
src/eval.cpp
@@ -41,6 +41,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty
             zig_panic("TODO");
         case TypeTableEntryIdStruct:
             zig_panic("TODO");
+        case TypeTableEntryIdUnion:
+            zig_panic("TODO");
         case TypeTableEntryIdUndefLit:
             zig_panic("TODO");
         case TypeTableEntryIdMaybe:
src/parser.cpp
@@ -2504,11 +2504,11 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index,
 }
 
 /*
-ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
+ContainerDecl = ("struct" | "enum" | "union") "Symbol" "{" many(StructMember) "}"
 StructMember: many(Directive) option(VisibleMod) (StructField | FnDef)
 StructField : "Symbol" option(":" Expression) ",")
 */
-static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,
+static AstNode *ast_parse_container_decl(ParseContext *pc, int *token_index,
         ZigList<AstNode*> *directives, VisibMod visib_mod)
 {
     Token *first_token = &pc->tokens->at(*token_index);
@@ -2519,6 +2519,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,
         kind = ContainerKindStruct;
     } else if (first_token->id == TokenIdKeywordEnum) {
         kind = ContainerKindEnum;
+    } else if (first_token->id == TokenIdKeywordUnion) {
+        kind = ContainerKindUnion;
     } else {
         return nullptr;
     }
@@ -2689,7 +2691,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
             continue;
         }
 
-        AstNode *struct_node = ast_parse_struct_decl(pc, token_index, directives, visib_mod);
+        AstNode *struct_node = ast_parse_container_decl(pc, token_index, directives, visib_mod);
         if (struct_node) {
             top_level_decls->append(struct_node);
             continue;
src/tokenizer.cpp
@@ -108,7 +108,7 @@ const char * zig_keywords[] = {
     "pub", "export", "use", "if", "else", "goto", "asm",
     "volatile", "struct", "enum", "while", "for", "continue", "break",
     "null", "noalias", "switch", "undefined", "error", "type", "inline",
-    "defer",
+    "defer", "union",
 };
 
 bool is_zig_keyword(Buf *buf) {
@@ -269,6 +269,8 @@ static void end_token(Tokenize *t) {
         t->cur_tok->id = TokenIdKeywordStruct;
     } else if (mem_eql_str(token_mem, token_len, "enum")) {
         t->cur_tok->id = TokenIdKeywordEnum;
+    } else if (mem_eql_str(token_mem, token_len, "union")) {
+        t->cur_tok->id = TokenIdKeywordUnion;
     } else if (mem_eql_str(token_mem, token_len, "for")) {
         t->cur_tok->id = TokenIdKeywordFor;
     } else if (mem_eql_str(token_mem, token_len, "while")) {
@@ -1195,6 +1197,7 @@ const char * token_name(TokenId id) {
         case TokenIdKeywordAsm: return "asm";
         case TokenIdKeywordStruct: return "struct";
         case TokenIdKeywordEnum: return "enum";
+        case TokenIdKeywordUnion: return "union";
         case TokenIdKeywordWhile: return "while";
         case TokenIdKeywordFor: return "for";
         case TokenIdKeywordContinue: return "continue";
src/tokenizer.hpp
@@ -30,6 +30,7 @@ enum TokenId {
     TokenIdKeywordVolatile,
     TokenIdKeywordStruct,
     TokenIdKeywordEnum,
+    TokenIdKeywordUnion,
     TokenIdKeywordWhile,
     TokenIdKeywordFor,
     TokenIdKeywordContinue,