| author | |
| committer | |
| log | 46ab981787a108ad4326c86aa2a6af4247e7191b |
| tree | 6ae8c6ca2774ea4dba4f5db784efb8233c623421 |
| parent | 4961910e7faf4df0a88d9571e894563f80613f7f |
10 files changed, 64 insertions(+), 7 deletions(-)
doc/langref.md+1-1| ... | ... | @@ -15,7 +15,7 @@ GlobalVarDecl = VariableDeclaration ";" |
| 15 | 15 | |
| 16 | 16 | VariableDeclaration = ("var" | "const") "Symbol" option(":" TypeExpr) "=" Expression |
| 17 | 17 | |
| 18 | ContainerDecl = ("struct" | "enum") "Symbol" "{" many(StructMember) "}" | |
| 18 | ContainerDecl = ("struct" | "enum" | "union") "Symbol" "{" many(StructMember) "}" | |
| 19 | 19 | |
| 20 | 20 | StructMember = many(Directive) option(VisibleMod) (StructField | FnDef) |
| 21 | 21 |
doc/vim/syntax/zig.vim+1-1| ... | ... | @@ -8,7 +8,7 @@ if exists("b:current_syntax") |
| 8 | 8 | endif |
| 9 | 9 | |
| 10 | 10 | syn keyword zigStorage const var extern volatile export pub noalias inline |
| 11 | syn keyword zigStructure struct enum | |
| 11 | syn keyword zigStructure struct enum union | |
| 12 | 12 | syn keyword zigStatement goto break return continue asm defer |
| 13 | 13 | syn keyword zigConditional if else switch |
| 14 | 14 | syn keyword zigRepeat while for |
src/all_types.hpp+20-1| ... | ... | @@ -135,7 +135,7 @@ struct TopLevelDecl { |
| 135 | 135 | struct TypeEnumField { |
| 136 | 136 | Buf *name; |
| 137 | 137 | TypeTableEntry *type_entry; |
| 138 | uint32_t value; | |
| 138 | uint32_t value; // TODO is this used? | |
| 139 | 139 | }; |
| 140 | 140 | |
| 141 | 141 | enum NodeType { |
| ... | ... | @@ -590,6 +590,7 @@ struct AstNodeAsmExpr { |
| 590 | 590 | enum ContainerKind { |
| 591 | 591 | ContainerKindStruct, |
| 592 | 592 | ContainerKindEnum, |
| 593 | ContainerKindUnion, | |
| 593 | 594 | }; |
| 594 | 595 | |
| 595 | 596 | struct AstNodeStructDecl { |
| ... | ... | @@ -905,6 +906,22 @@ struct TypeTableEntryEnum { |
| 905 | 906 | bool complete; |
| 906 | 907 | }; |
| 907 | 908 | |
| 909 | struct TypeTableEntryUnion { | |
| 910 | AstNode *decl_node; | |
| 911 | uint32_t src_field_count; | |
| 912 | uint32_t gen_field_count; | |
| 913 | TypeStructField *fields; | |
| 914 | uint64_t size_bytes; | |
| 915 | bool is_invalid; // true if any fields are invalid | |
| 916 | BlockContext *block_context; | |
| 917 | ||
| 918 | // set this flag temporarily to detect infinite loops | |
| 919 | bool embedded_in_current; | |
| 920 | bool reported_infinite_err; | |
| 921 | // whether we've finished resolving it | |
| 922 | bool complete; | |
| 923 | }; | |
| 924 | ||
| 908 | 925 | struct FnGenParamInfo { |
| 909 | 926 | int src_index; |
| 910 | 927 | int gen_index; |
| ... | ... | @@ -949,6 +966,7 @@ enum TypeTableEntryId { |
| 949 | 966 | TypeTableEntryIdErrorUnion, |
| 950 | 967 | TypeTableEntryIdPureError, |
| 951 | 968 | TypeTableEntryIdEnum, |
| 969 | TypeTableEntryIdUnion, | |
| 952 | 970 | TypeTableEntryIdFn, |
| 953 | 971 | TypeTableEntryIdTypeDecl, |
| 954 | 972 | TypeTableEntryIdNamespace, |
| ... | ... | @@ -974,6 +992,7 @@ struct TypeTableEntry { |
| 974 | 992 | TypeTableEntryMaybe maybe; |
| 975 | 993 | TypeTableEntryError error; |
| 976 | 994 | TypeTableEntryEnum enumeration; |
| 995 | TypeTableEntryUnion unionation; | |
| 977 | 996 | TypeTableEntryFn fn; |
| 978 | 997 | TypeTableEntryTypeDecl type_decl; |
| 979 | 998 | TypeTableEntryGenericFn generic_fn; |
src/analyze.cpp+25| ... | ... | @@ -141,6 +141,8 @@ static BlockContext **get_container_block_context_ptr(TypeTableEntry *type_entry |
| 141 | 141 | return &type_entry->data.structure.block_context; |
| 142 | 142 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 143 | 143 | return &type_entry->data.enumeration.block_context; |
| 144 | } else if (type_entry->id == TypeTableEntryIdUnion) { | |
| 145 | return &type_entry->data.unionation.block_context; | |
| 144 | 146 | } |
| 145 | 147 | zig_unreachable(); |
| 146 | 148 | } |
| ... | ... | @@ -178,6 +180,8 @@ static bool type_is_complete(TypeTableEntry *type_entry) { |
| 178 | 180 | return type_entry->data.structure.complete; |
| 179 | 181 | case TypeTableEntryIdEnum: |
| 180 | 182 | return type_entry->data.enumeration.complete; |
| 183 | case TypeTableEntryIdUnion: | |
| 184 | return type_entry->data.unionation.complete; | |
| 181 | 185 | case TypeTableEntryIdMetaType: |
| 182 | 186 | case TypeTableEntryIdVoid: |
| 183 | 187 | case TypeTableEntryIdBool: |
| ... | ... | @@ -732,6 +736,8 @@ static TypeTableEntryId container_to_type(ContainerKind kind) { |
| 732 | 736 | return TypeTableEntryIdStruct; |
| 733 | 737 | case ContainerKindEnum: |
| 734 | 738 | return TypeTableEntryIdEnum; |
| 739 | case ContainerKindUnion: | |
| 740 | return TypeTableEntryIdUnion; | |
| 735 | 741 | } |
| 736 | 742 | zig_unreachable(); |
| 737 | 743 | } |
| ... | ... | @@ -749,6 +755,9 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, |
| 749 | 755 | case ContainerKindEnum: |
| 750 | 756 | entry->data.enumeration.decl_node = decl_node; |
| 751 | 757 | break; |
| 758 | case ContainerKindUnion: | |
| 759 | entry->data.unionation.decl_node = decl_node; | |
| 760 | break; | |
| 752 | 761 | } |
| 753 | 762 | |
| 754 | 763 | unsigned line = decl_node ? decl_node->line : 0; |
| ... | ... | @@ -874,6 +883,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor |
| 874 | 883 | case TypeTableEntryIdErrorUnion: |
| 875 | 884 | case TypeTableEntryIdPureError: |
| 876 | 885 | case TypeTableEntryIdEnum: |
| 886 | case TypeTableEntryIdUnion: | |
| 877 | 887 | case TypeTableEntryIdFn: |
| 878 | 888 | case TypeTableEntryIdTypeDecl: |
| 879 | 889 | break; |
| ... | ... | @@ -1397,6 +1407,10 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 1397 | 1407 | struct_type->zero_bits = (debug_size_in_bits == 0); |
| 1398 | 1408 | } |
| 1399 | 1409 | |
| 1410 | static void resolve_union_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type) { | |
| 1411 | zig_panic("TODO"); | |
| 1412 | } | |
| 1413 | ||
| 1400 | 1414 | static void get_fully_qualified_decl_name(Buf *buf, AstNode *decl_node, uint8_t sep) { |
| 1401 | 1415 | TopLevelDecl *tld = get_as_top_level_decl(decl_node); |
| 1402 | 1416 | AstNode *parent_decl = tld->parent_decl; |
| ... | ... | @@ -1541,6 +1555,9 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) |
| 1541 | 1555 | case ContainerKindEnum: |
| 1542 | 1556 | resolve_enum_type(g, import, type_entry); |
| 1543 | 1557 | break; |
| 1558 | case ContainerKindUnion: | |
| 1559 | resolve_union_type(g, import, type_entry); | |
| 1560 | break; | |
| 1544 | 1561 | } |
| 1545 | 1562 | |
| 1546 | 1563 | break; |
| ... | ... | @@ -1672,6 +1689,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) { |
| 1672 | 1689 | case TypeTableEntryIdErrorUnion: |
| 1673 | 1690 | case TypeTableEntryIdPureError: |
| 1674 | 1691 | case TypeTableEntryIdEnum: |
| 1692 | case TypeTableEntryIdUnion: | |
| 1675 | 1693 | case TypeTableEntryIdFn: |
| 1676 | 1694 | return true; |
| 1677 | 1695 | |
| ... | ... | @@ -4450,6 +4468,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 4450 | 4468 | case TypeTableEntryIdErrorUnion: |
| 4451 | 4469 | case TypeTableEntryIdPureError: |
| 4452 | 4470 | case TypeTableEntryIdEnum: |
| 4471 | case TypeTableEntryIdUnion: | |
| 4453 | 4472 | case TypeTableEntryIdFn: |
| 4454 | 4473 | case TypeTableEntryIdTypeDecl: |
| 4455 | 4474 | return resolve_expr_const_val_as_type(g, node, type_entry); |
| ... | ... | @@ -6179,6 +6198,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 6179 | 6198 | return false; |
| 6180 | 6199 | case TypeTableEntryIdArray: |
| 6181 | 6200 | case TypeTableEntryIdStruct: |
| 6201 | case TypeTableEntryIdUnion: | |
| 6182 | 6202 | return true; |
| 6183 | 6203 | case TypeTableEntryIdErrorUnion: |
| 6184 | 6204 | 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) |
| 6280 | 6300 | case TypeTableEntryIdStruct: |
| 6281 | 6301 | // TODO better hashing algorithm |
| 6282 | 6302 | return 1532530855; |
| 6303 | case TypeTableEntryIdUnion: | |
| 6304 | // TODO better hashing algorithm | |
| 6305 | return 2709806591; | |
| 6283 | 6306 | case TypeTableEntryIdMaybe: |
| 6284 | 6307 | if (const_val->data.x_maybe) { |
| 6285 | 6308 | TypeTableEntry *child_type = type->data.maybe.child_type; |
| ... | ... | @@ -6374,6 +6397,8 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry) |
| 6374 | 6397 | return type_of_first_thing_in_memory(type_entry->data.array.child_type); |
| 6375 | 6398 | case TypeTableEntryIdStruct: |
| 6376 | 6399 | return type_of_first_thing_in_memory(first_struct_field_type(type_entry)); |
| 6400 | case TypeTableEntryIdUnion: | |
| 6401 | zig_panic("TODO"); | |
| 6377 | 6402 | case TypeTableEntryIdMaybe: |
| 6378 | 6403 | return type_of_first_thing_in_memory(type_entry->data.maybe.child_type); |
| 6379 | 6404 | case TypeTableEntryIdErrorUnion: |
src/ast_render.cpp+1| ... | ... | @@ -84,6 +84,7 @@ static const char *container_string(ContainerKind kind) { |
| 84 | 84 | switch (kind) { |
| 85 | 85 | case ContainerKindEnum: return "enum"; |
| 86 | 86 | case ContainerKindStruct: return "struct"; |
| 87 | case ContainerKindUnion: return "union"; | |
| 87 | 88 | } |
| 88 | 89 | zig_unreachable(); |
| 89 | 90 | } |
src/codegen.cpp+4| ... | ... | @@ -2972,6 +2972,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE |
| 2972 | 2972 | return LLVMConstNamedStruct(type_entry->type_ref, fields, |
| 2973 | 2973 | type_entry->data.structure.gen_field_count); |
| 2974 | 2974 | } |
| 2975 | case TypeTableEntryIdUnion: | |
| 2976 | { | |
| 2977 | zig_panic("TODO"); | |
| 2978 | } | |
| 2975 | 2979 | case TypeTableEntryIdArray: |
| 2976 | 2980 | { |
| 2977 | 2981 | TypeTableEntry *child_type = type_entry->data.array.child_type; |
src/eval.cpp+2| ... | ... | @@ -41,6 +41,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty |
| 41 | 41 | zig_panic("TODO"); |
| 42 | 42 | case TypeTableEntryIdStruct: |
| 43 | 43 | zig_panic("TODO"); |
| 44 | case TypeTableEntryIdUnion: | |
| 45 | zig_panic("TODO"); | |
| 44 | 46 | case TypeTableEntryIdUndefLit: |
| 45 | 47 | zig_panic("TODO"); |
| 46 | 48 | case TypeTableEntryIdMaybe: |
src/parser.cpp+5-3| ... | ... | @@ -2504,11 +2504,11 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index, |
| 2504 | 2504 | } |
| 2505 | 2505 | |
| 2506 | 2506 | /* |
| 2507 | ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}" | |
| 2507 | ContainerDecl = ("struct" | "enum" | "union") "Symbol" "{" many(StructMember) "}" | |
| 2508 | 2508 | StructMember: many(Directive) option(VisibleMod) (StructField | FnDef) |
| 2509 | 2509 | StructField : "Symbol" option(":" Expression) ",") |
| 2510 | 2510 | */ |
| 2511 | static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index, | |
| 2511 | static AstNode *ast_parse_container_decl(ParseContext *pc, int *token_index, | |
| 2512 | 2512 | ZigList<AstNode*> *directives, VisibMod visib_mod) |
| 2513 | 2513 | { |
| 2514 | 2514 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -2519,6 +2519,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index, |
| 2519 | 2519 | kind = ContainerKindStruct; |
| 2520 | 2520 | } else if (first_token->id == TokenIdKeywordEnum) { |
| 2521 | 2521 | kind = ContainerKindEnum; |
| 2522 | } else if (first_token->id == TokenIdKeywordUnion) { | |
| 2523 | kind = ContainerKindUnion; | |
| 2522 | 2524 | } else { |
| 2523 | 2525 | return nullptr; |
| 2524 | 2526 | } |
| ... | ... | @@ -2689,7 +2691,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 2689 | 2691 | continue; |
| 2690 | 2692 | } |
| 2691 | 2693 | |
| 2692 | AstNode *struct_node = ast_parse_struct_decl(pc, token_index, directives, visib_mod); | |
| 2694 | AstNode *struct_node = ast_parse_container_decl(pc, token_index, directives, visib_mod); | |
| 2693 | 2695 | if (struct_node) { |
| 2694 | 2696 | top_level_decls->append(struct_node); |
| 2695 | 2697 | continue; |
src/tokenizer.cpp+4-1| ... | ... | @@ -108,7 +108,7 @@ const char * zig_keywords[] = { |
| 108 | 108 | "pub", "export", "use", "if", "else", "goto", "asm", |
| 109 | 109 | "volatile", "struct", "enum", "while", "for", "continue", "break", |
| 110 | 110 | "null", "noalias", "switch", "undefined", "error", "type", "inline", |
| 111 | "defer", | |
| 111 | "defer", "union", | |
| 112 | 112 | }; |
| 113 | 113 | |
| 114 | 114 | bool is_zig_keyword(Buf *buf) { |
| ... | ... | @@ -269,6 +269,8 @@ static void end_token(Tokenize *t) { |
| 269 | 269 | t->cur_tok->id = TokenIdKeywordStruct; |
| 270 | 270 | } else if (mem_eql_str(token_mem, token_len, "enum")) { |
| 271 | 271 | t->cur_tok->id = TokenIdKeywordEnum; |
| 272 | } else if (mem_eql_str(token_mem, token_len, "union")) { | |
| 273 | t->cur_tok->id = TokenIdKeywordUnion; | |
| 272 | 274 | } else if (mem_eql_str(token_mem, token_len, "for")) { |
| 273 | 275 | t->cur_tok->id = TokenIdKeywordFor; |
| 274 | 276 | } else if (mem_eql_str(token_mem, token_len, "while")) { |
| ... | ... | @@ -1195,6 +1197,7 @@ const char * token_name(TokenId id) { |
| 1195 | 1197 | case TokenIdKeywordAsm: return "asm"; |
| 1196 | 1198 | case TokenIdKeywordStruct: return "struct"; |
| 1197 | 1199 | case TokenIdKeywordEnum: return "enum"; |
| 1200 | case TokenIdKeywordUnion: return "union"; | |
| 1198 | 1201 | case TokenIdKeywordWhile: return "while"; |
| 1199 | 1202 | case TokenIdKeywordFor: return "for"; |
| 1200 | 1203 | case TokenIdKeywordContinue: return "continue"; |
src/tokenizer.hpp+1| ... | ... | @@ -30,6 +30,7 @@ enum TokenId { |
| 30 | 30 | TokenIdKeywordVolatile, |
| 31 | 31 | TokenIdKeywordStruct, |
| 32 | 32 | TokenIdKeywordEnum, |
| 33 | TokenIdKeywordUnion, | |
| 33 | 34 | TokenIdKeywordWhile, |
| 34 | 35 | TokenIdKeywordFor, |
| 35 | 36 | TokenIdKeywordContinue, |