| author | |
| committer | |
| log | f6eecfe5f486b250de33a8129b1c85198be43280 |
| tree | 2cef7045ade894407c6b6d99e6daa5c86a9a496b |
| parent | 94e61287e708f61d2a9d814bfe7910d13e067ada |
11 files changed, 116 insertions(+), 21 deletions(-)
README.md+4-2| ... | @@ -144,9 +144,11 @@ ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen) | ... | @@ -144,9 +144,11 @@ ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen) |
| 144 | 144 | ||
| 145 | ParamDecl : token(Symbol) token(Colon) Type | 145 | ParamDecl : token(Symbol) token(Colon) Type |
| 146 | 146 | ||
| 147 | Type : token(Symbol) | PointerType | token(Unreachable) | 147 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType |
| 148 | 148 | ||
| 149 | PointerType : token(Star) token(Const) Type | token(Star) token(Mut) Type | 149 | PointerType : token(Star) (token(Const) | token(Mut)) Type |
| 150 | |||
| 151 | ArrayType : token(LBracket) Type token(Semicolon) Expression token(RBracket) | ||
| 150 | 152 | ||
| 151 | Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace) | 153 | Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace) |
| 152 | 154 |
src/analyze.cpp+52-3| ... | @@ -48,18 +48,23 @@ static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node) | ... | @@ -48,18 +48,23 @@ static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node) |
| 48 | } | 48 | } |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | TypeTableEntry *new_type_table_entry() { | ||
| 52 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); | ||
| 53 | entry->arrays_by_size.init(2); | ||
| 54 | return entry; | ||
| 55 | } | ||
| 56 | |||
| 51 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { | 57 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { |
| 52 | TypeTableEntry **parent_pointer = is_const ? | 58 | TypeTableEntry **parent_pointer = is_const ? |
| 53 | &child_type->pointer_const_parent : | 59 | &child_type->pointer_const_parent : |
| 54 | &child_type->pointer_mut_parent; | 60 | &child_type->pointer_mut_parent; |
| 55 | const char *const_or_mut_str = is_const ? "const" : "mut"; | ||
| 56 | if (*parent_pointer) { | 61 | if (*parent_pointer) { |
| 57 | return *parent_pointer; | 62 | return *parent_pointer; |
| 58 | } else { | 63 | } else { |
| 59 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); | 64 | TypeTableEntry *entry = new_type_table_entry(); |
| 60 | entry->type_ref = LLVMPointerType(child_type->type_ref, 0); | 65 | entry->type_ref = LLVMPointerType(child_type->type_ref, 0); |
| 61 | buf_resize(&entry->name, 0); | 66 | buf_resize(&entry->name, 0); |
| 62 | buf_appendf(&entry->name, "*%s %s", const_or_mut_str, buf_ptr(&child_type->name)); | 67 | buf_appendf(&entry->name, "*%s %s", is_const ? "const" : "mut", buf_ptr(&child_type->name)); |
| 63 | entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type, | 68 | entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type, |
| 64 | g->pointer_size_bytes * 8, g->pointer_size_bytes * 8, buf_ptr(&entry->name)); | 69 | g->pointer_size_bytes * 8, g->pointer_size_bytes * 8, buf_ptr(&entry->name)); |
| 65 | g->type_table.put(&entry->name, entry); | 70 | g->type_table.put(&entry->name, entry); |
| ... | @@ -68,6 +73,28 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool | ... | @@ -68,6 +73,28 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 68 | } | 73 | } |
| 69 | } | 74 | } |
| 70 | 75 | ||
| 76 | static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, int array_size) { | ||
| 77 | auto existing_entry = child_type->arrays_by_size.maybe_get(array_size); | ||
| 78 | if (existing_entry) { | ||
| 79 | return existing_entry->value; | ||
| 80 | } else { | ||
| 81 | TypeTableEntry *entry = new_type_table_entry(); | ||
| 82 | entry->type_ref = LLVMArrayType(child_type->type_ref, array_size); | ||
| 83 | buf_resize(&entry->name, 0); | ||
| 84 | buf_appendf(&entry->name, "[%s; %ud]", buf_ptr(&child_type->name), array_size); | ||
| 85 | //entry->di_type = LLVMZigCreateDebugArrayType(g->dbuilder, ..., buf_ptr(&entry->name)); // TODO | ||
| 86 | |||
| 87 | g->type_table.put(&entry->name, entry); | ||
| 88 | child_type->arrays_by_size.put(array_size, entry); | ||
| 89 | return entry; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | static int parse_int(Buf *number) { | ||
| 94 | // TODO: think about integer size of array sizes | ||
| 95 | return atoi(buf_ptr(number)); | ||
| 96 | } | ||
| 97 | |||
| 71 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { | 98 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 72 | assert(node->type == NodeTypeType); | 99 | assert(node->type == NodeTypeType); |
| 73 | assert(!node->codegen_node); | 100 | assert(!node->codegen_node); |
| ... | @@ -98,6 +125,28 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { | ... | @@ -98,6 +125,28 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 98 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const); | 125 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const); |
| 99 | return type_node->entry; | 126 | return type_node->entry; |
| 100 | } | 127 | } |
| 128 | case AstNodeTypeTypeArray: | ||
| 129 | { | ||
| 130 | resolve_type(g, node->data.type.child_type); | ||
| 131 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; | ||
| 132 | if (child_type == g->builtin_types.entry_unreachable) { | ||
| 133 | add_node_error(g, node, | ||
| 134 | buf_create_from_str("array of unreachable not allowed")); | ||
| 135 | } | ||
| 136 | |||
| 137 | AstNode *size_node = node->data.type.array_size; | ||
| 138 | int size; // TODO: think about integer size of array sizes | ||
| 139 | if (size_node->type != NodeTypeNumberLiteral) { | ||
| 140 | add_node_error(g, size_node, | ||
| 141 | buf_create_from_str("array size must be literal number")); | ||
| 142 | size = -1; | ||
| 143 | } else { | ||
| 144 | size = parse_int(&size_node->data.number); | ||
| 145 | } | ||
| 146 | |||
| 147 | type_node->entry = get_array_type(g, child_type, size); // TODO | ||
| 148 | return type_node->entry; | ||
| 149 | } | ||
| 101 | } | 150 | } |
| 102 | zig_unreachable(); | 151 | zig_unreachable(); |
| 103 | } | 152 | } |
src/analyze.hpp+1| ... | @@ -18,6 +18,7 @@ struct BlockContext; | ... | @@ -18,6 +18,7 @@ struct BlockContext; |
| 18 | 18 | ||
| 19 | void semantic_analyze(CodeGen *g); | 19 | void semantic_analyze(CodeGen *g); |
| 20 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); | 20 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 21 | TypeTableEntry *new_type_table_entry(); | ||
| 21 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); | 22 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 22 | LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name); | 23 | LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name); |
| 23 | 24 |
src/codegen.cpp+6-6| ... | @@ -781,12 +781,12 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -781,12 +781,12 @@ static void do_code_gen(CodeGen *g) { |
| 781 | static void define_primitive_types(CodeGen *g) { | 781 | static void define_primitive_types(CodeGen *g) { |
| 782 | { | 782 | { |
| 783 | // if this type is anywhere in the AST, we should never hit codegen. | 783 | // if this type is anywhere in the AST, we should never hit codegen. |
| 784 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); | 784 | TypeTableEntry *entry = new_type_table_entry(); |
| 785 | buf_init_from_str(&entry->name, "(invalid)"); | 785 | buf_init_from_str(&entry->name, "(invalid)"); |
| 786 | g->builtin_types.entry_invalid = entry; | 786 | g->builtin_types.entry_invalid = entry; |
| 787 | } | 787 | } |
| 788 | { | 788 | { |
| 789 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); | 789 | TypeTableEntry *entry = new_type_table_entry(); |
| 790 | entry->type_ref = LLVMInt1Type(); | 790 | entry->type_ref = LLVMInt1Type(); |
| 791 | buf_init_from_str(&entry->name, "bool"); | 791 | buf_init_from_str(&entry->name, "bool"); |
| 792 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 1, 8, | 792 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 1, 8, |
| ... | @@ -795,7 +795,7 @@ static void define_primitive_types(CodeGen *g) { | ... | @@ -795,7 +795,7 @@ static void define_primitive_types(CodeGen *g) { |
| 795 | g->builtin_types.entry_bool = entry; | 795 | g->builtin_types.entry_bool = entry; |
| 796 | } | 796 | } |
| 797 | { | 797 | { |
| 798 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); | 798 | TypeTableEntry *entry = new_type_table_entry(); |
| 799 | entry->type_ref = LLVMInt8Type(); | 799 | entry->type_ref = LLVMInt8Type(); |
| 800 | buf_init_from_str(&entry->name, "u8"); | 800 | buf_init_from_str(&entry->name, "u8"); |
| 801 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8, | 801 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8, |
| ... | @@ -805,7 +805,7 @@ static void define_primitive_types(CodeGen *g) { | ... | @@ -805,7 +805,7 @@ static void define_primitive_types(CodeGen *g) { |
| 805 | } | 805 | } |
| 806 | g->builtin_types.entry_string_literal = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | 806 | g->builtin_types.entry_string_literal = get_pointer_to_type(g, g->builtin_types.entry_u8, true); |
| 807 | { | 807 | { |
| 808 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); | 808 | TypeTableEntry *entry = new_type_table_entry(); |
| 809 | entry->type_ref = LLVMInt32Type(); | 809 | entry->type_ref = LLVMInt32Type(); |
| 810 | buf_init_from_str(&entry->name, "i32"); | 810 | buf_init_from_str(&entry->name, "i32"); |
| 811 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32, | 811 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32, |
| ... | @@ -814,7 +814,7 @@ static void define_primitive_types(CodeGen *g) { | ... | @@ -814,7 +814,7 @@ static void define_primitive_types(CodeGen *g) { |
| 814 | g->builtin_types.entry_i32 = entry; | 814 | g->builtin_types.entry_i32 = entry; |
| 815 | } | 815 | } |
| 816 | { | 816 | { |
| 817 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); | 817 | TypeTableEntry *entry = new_type_table_entry(); |
| 818 | entry->type_ref = LLVMVoidType(); | 818 | entry->type_ref = LLVMVoidType(); |
| 819 | buf_init_from_str(&entry->name, "void"); | 819 | buf_init_from_str(&entry->name, "void"); |
| 820 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0, | 820 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0, |
| ... | @@ -823,7 +823,7 @@ static void define_primitive_types(CodeGen *g) { | ... | @@ -823,7 +823,7 @@ static void define_primitive_types(CodeGen *g) { |
| 823 | g->builtin_types.entry_void = entry; | 823 | g->builtin_types.entry_void = entry; |
| 824 | } | 824 | } |
| 825 | { | 825 | { |
| 826 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); | 826 | TypeTableEntry *entry = new_type_table_entry(); |
| 827 | entry->type_ref = LLVMVoidType(); | 827 | entry->type_ref = LLVMVoidType(); |
| 828 | buf_init_from_str(&entry->name, "unreachable"); | 828 | buf_init_from_str(&entry->name, "unreachable"); |
| 829 | entry->di_type = g->builtin_types.entry_void->di_type; | 829 | entry->di_type = g->builtin_types.entry_void->di_type; |
src/parser.cpp+25-10| ... | @@ -180,6 +180,13 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -180,6 +180,13 @@ void ast_print(AstNode *node, int indent) { |
| 180 | ast_print(node->data.type.child_type, indent + 2); | 180 | ast_print(node->data.type.child_type, indent + 2); |
| 181 | break; | 181 | break; |
| 182 | } | 182 | } |
| 183 | case AstNodeTypeTypeArray: | ||
| 184 | { | ||
| 185 | fprintf(stderr, "ArrayType\n"); | ||
| 186 | ast_print(node->data.type.child_type, indent + 2); | ||
| 187 | ast_print(node->data.type.array_size, indent + 2); | ||
| 188 | break; | ||
| 189 | } | ||
| 183 | } | 190 | } |
| 184 | break; | 191 | break; |
| 185 | case NodeTypeReturnExpr: | 192 | case NodeTypeReturnExpr: |
| ... | @@ -448,8 +455,9 @@ static void ast_parse_directives(ParseContext *pc, int *token_index, | ... | @@ -448,8 +455,9 @@ static void ast_parse_directives(ParseContext *pc, int *token_index, |
| 448 | 455 | ||
| 449 | 456 | ||
| 450 | /* | 457 | /* |
| 451 | Type : token(Symbol) | PointerType | token(Unreachable) | 458 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType |
| 452 | PointerType : token(Star) token(Const) Type | token(Star) token(Mut) Type; | 459 | PointerType : token(Star) (token(Const) | token(Mut)) Type |
| 460 | ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket) | ||
| 453 | */ | 461 | */ |
| 454 | static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token_index) { | 462 | static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token_index) { |
| 455 | Token *token = &pc->tokens->at(token_index); | 463 | Token *token = &pc->tokens->at(token_index); |
| ... | @@ -463,12 +471,6 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token | ... | @@ -463,12 +471,6 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token |
| 463 | } else if (token->id == TokenIdKeywordVoid) { | 471 | } else if (token->id == TokenIdKeywordVoid) { |
| 464 | node->data.type.type = AstNodeTypeTypePrimitive; | 472 | node->data.type.type = AstNodeTypeTypePrimitive; |
| 465 | buf_init_from_str(&node->data.type.primitive_name, "void"); | 473 | buf_init_from_str(&node->data.type.primitive_name, "void"); |
| 466 | } else if (token->id == TokenIdKeywordTrue) { | ||
| 467 | node->data.type.type = AstNodeTypeTypePrimitive; | ||
| 468 | buf_init_from_str(&node->data.type.primitive_name, "true"); | ||
| 469 | } else if (token->id == TokenIdKeywordFalse) { | ||
| 470 | node->data.type.type = AstNodeTypeTypePrimitive; | ||
| 471 | buf_init_from_str(&node->data.type.primitive_name, "false"); | ||
| 472 | } else if (token->id == TokenIdSymbol) { | 474 | } else if (token->id == TokenIdSymbol) { |
| 473 | node->data.type.type = AstNodeTypeTypePrimitive; | 475 | node->data.type.type = AstNodeTypeTypePrimitive; |
| 474 | ast_buf_from_token(pc, token, &node->data.type.primitive_name); | 476 | ast_buf_from_token(pc, token, &node->data.type.primitive_name); |
| ... | @@ -485,6 +487,20 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token | ... | @@ -485,6 +487,20 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token |
| 485 | } | 487 | } |
| 486 | 488 | ||
| 487 | node->data.type.child_type = ast_parse_type(pc, token_index, &token_index); | 489 | node->data.type.child_type = ast_parse_type(pc, token_index, &token_index); |
| 490 | } else if (token->id == TokenIdLBracket) { | ||
| 491 | node->data.type.type = AstNodeTypeTypeArray; | ||
| 492 | |||
| 493 | node->data.type.child_type = ast_parse_type(pc, token_index, &token_index); | ||
| 494 | |||
| 495 | Token *semicolon_token = &pc->tokens->at(token_index); | ||
| 496 | token_index += 1; | ||
| 497 | ast_expect_token(pc, semicolon_token, TokenIdSemicolon); | ||
| 498 | |||
| 499 | node->data.type.array_size = ast_parse_expression(pc, &token_index, true); | ||
| 500 | |||
| 501 | Token *rbracket_token = &pc->tokens->at(token_index); | ||
| 502 | token_index += 1; | ||
| 503 | ast_expect_token(pc, rbracket_token, TokenIdRBracket); | ||
| 488 | } else { | 504 | } else { |
| 489 | ast_invalid_token_error(pc, token); | 505 | ast_invalid_token_error(pc, token); |
| 490 | } | 506 | } |
| ... | @@ -494,8 +510,7 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token | ... | @@ -494,8 +510,7 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token |
| 494 | } | 510 | } |
| 495 | 511 | ||
| 496 | /* | 512 | /* |
| 497 | ParamDecl<node> : token(Symbol) token(Colon) Type { | 513 | ParamDecl : token(Symbol) token(Colon) Type |
| 498 | }; | ||
| 499 | */ | 514 | */ |
| 500 | static AstNode *ast_parse_param_decl(ParseContext *pc, int token_index, int *new_token_index) { | 515 | static AstNode *ast_parse_param_decl(ParseContext *pc, int token_index, int *new_token_index) { |
| 501 | Token *param_name = &pc->tokens->at(token_index); | 516 | Token *param_name = &pc->tokens->at(token_index); |
src/parser.hpp+2| ... | @@ -81,12 +81,14 @@ struct AstNodeParamDecl { | ... | @@ -81,12 +81,14 @@ struct AstNodeParamDecl { |
| 81 | enum AstNodeTypeType { | 81 | enum AstNodeTypeType { |
| 82 | AstNodeTypeTypePrimitive, | 82 | AstNodeTypeTypePrimitive, |
| 83 | AstNodeTypeTypePointer, | 83 | AstNodeTypeTypePointer, |
| 84 | AstNodeTypeTypeArray, | ||
| 84 | }; | 85 | }; |
| 85 | 86 | ||
| 86 | struct AstNodeType { | 87 | struct AstNodeType { |
| 87 | AstNodeTypeType type; | 88 | AstNodeTypeType type; |
| 88 | Buf primitive_name; | 89 | Buf primitive_name; |
| 89 | AstNode *child_type; | 90 | AstNode *child_type; |
| 91 | AstNode *array_size; | ||
| 90 | bool is_const; | 92 | bool is_const; |
| 91 | }; | 93 | }; |
| 92 | 94 |
src/semantic_info.hpp+3| ... | @@ -23,8 +23,11 @@ struct TypeTableEntry { | ... | @@ -23,8 +23,11 @@ struct TypeTableEntry { |
| 23 | bool pointer_is_const; | 23 | bool pointer_is_const; |
| 24 | int user_defined_id; | 24 | int user_defined_id; |
| 25 | Buf name; | 25 | Buf name; |
| 26 | |||
| 27 | // use these fields to make sure we don't duplicate type table entries for the same type | ||
| 26 | TypeTableEntry *pointer_const_parent; | 28 | TypeTableEntry *pointer_const_parent; |
| 27 | TypeTableEntry *pointer_mut_parent; | 29 | TypeTableEntry *pointer_mut_parent; |
| 30 | HashMap<int, TypeTableEntry *, int_hash, int_eq> arrays_by_size; | ||
| 28 | }; | 31 | }; |
| 29 | 32 | ||
| 30 | struct ImportTableEntry { | 33 | struct ImportTableEntry { |
src/tokenizer.cpp+10| ... | @@ -259,6 +259,14 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -259,6 +259,14 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 259 | begin_token(&t, TokenIdRBrace); | 259 | begin_token(&t, TokenIdRBrace); |
| 260 | end_token(&t); | 260 | end_token(&t); |
| 261 | break; | 261 | break; |
| 262 | case '[': | ||
| 263 | begin_token(&t, TokenIdLBracket); | ||
| 264 | end_token(&t); | ||
| 265 | break; | ||
| 266 | case ']': | ||
| 267 | begin_token(&t, TokenIdRBracket); | ||
| 268 | end_token(&t); | ||
| 269 | break; | ||
| 262 | case ';': | 270 | case ';': |
| 263 | begin_token(&t, TokenIdSemicolon); | 271 | begin_token(&t, TokenIdSemicolon); |
| 264 | end_token(&t); | 272 | end_token(&t); |
| ... | @@ -601,6 +609,8 @@ static const char * token_name(Token *token) { | ... | @@ -601,6 +609,8 @@ static const char * token_name(Token *token) { |
| 601 | case TokenIdStar: return "Star"; | 609 | case TokenIdStar: return "Star"; |
| 602 | case TokenIdLBrace: return "LBrace"; | 610 | case TokenIdLBrace: return "LBrace"; |
| 603 | case TokenIdRBrace: return "RBrace"; | 611 | case TokenIdRBrace: return "RBrace"; |
| 612 | case TokenIdLBracket: return "LBracket"; | ||
| 613 | case TokenIdRBracket: return "RBracket"; | ||
| 604 | case TokenIdStringLiteral: return "StringLiteral"; | 614 | case TokenIdStringLiteral: return "StringLiteral"; |
| 605 | case TokenIdSemicolon: return "Semicolon"; | 615 | case TokenIdSemicolon: return "Semicolon"; |
| 606 | case TokenIdNumberLiteral: return "NumberLiteral"; | 616 | case TokenIdNumberLiteral: return "NumberLiteral"; |
src/tokenizer.hpp+2| ... | @@ -36,6 +36,8 @@ enum TokenId { | ... | @@ -36,6 +36,8 @@ enum TokenId { |
| 36 | TokenIdStar, | 36 | TokenIdStar, |
| 37 | TokenIdLBrace, | 37 | TokenIdLBrace, |
| 38 | TokenIdRBrace, | 38 | TokenIdRBrace, |
| 39 | TokenIdLBracket, | ||
| 40 | TokenIdRBracket, | ||
| 39 | TokenIdStringLiteral, | 41 | TokenIdStringLiteral, |
| 40 | TokenIdSemicolon, | 42 | TokenIdSemicolon, |
| 41 | TokenIdNumberLiteral, | 43 | TokenIdNumberLiteral, |
src/util.cpp+7| ... | @@ -19,3 +19,10 @@ void zig_panic(const char *format, ...) { | ... | @@ -19,3 +19,10 @@ void zig_panic(const char *format, ...) { |
| 19 | va_end(ap); | 19 | va_end(ap); |
| 20 | abort(); | 20 | abort(); |
| 21 | } | 21 | } |
| 22 | |||
| 23 | uint32_t int_hash(int i) { | ||
| 24 | return *reinterpret_cast<uint32_t*>(&i); | ||
| 25 | } | ||
| 26 | bool int_eq(int a, int b) { | ||
| 27 | return a == b; | ||
| 28 | } |
src/util.hpp+4| ... | @@ -9,6 +9,7 @@ | ... | @@ -9,6 +9,7 @@ |
| 9 | #define ZIG_UTIL_HPP | 9 | #define ZIG_UTIL_HPP |
| 10 | 10 | ||
| 11 | #include <stdlib.h> | 11 | #include <stdlib.h> |
| 12 | #include <stdint.h> | ||
| 12 | #include <string.h> | 13 | #include <string.h> |
| 13 | #include <assert.h> | 14 | #include <assert.h> |
| 14 | 15 | ||
| ... | @@ -78,4 +79,7 @@ static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) | ... | @@ -78,4 +79,7 @@ static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) |
| 78 | return memcmp(mem, str, mem_len) == 0; | 79 | return memcmp(mem, str, mem_len) == 0; |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 82 | uint32_t int_hash(int i); | ||
| 83 | bool int_eq(int a, int b); | ||
| 84 | |||
| 81 | #endif | 85 | #endif |