Commit 46ab981787
Changed files (10)
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,