authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-07 08:29:19-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-07 08:29:19-07:00
logf6eecfe5f486b250de33a8129b1c85198be43280
tree2cef7045ade894407c6b6d99e6daa5c86a9a496b
parent94e61287e708f61d2a9d814bfe7910d13e067ada

getting started on array types


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)
144144
145ParamDecl : token(Symbol) token(Colon) Type145ParamDecl : token(Symbol) token(Colon) Type
146146
147Type : token(Symbol) | PointerType | token(Unreachable)147Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType
148148
149PointerType : token(Star) token(Const) Type | token(Star) token(Mut) Type149PointerType : token(Star) (token(Const) | token(Mut)) Type
150
151ArrayType : token(LBracket) Type token(Semicolon) Expression token(RBracket)
150152
151Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)153Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
152154
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}
5050
51TypeTableEntry *new_type_table_entry() {
52 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
53 entry->arrays_by_size.init(2);
54 return entry;
55}
56
51TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {57TypeTableEntry *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}
7075
76static 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
93static int parse_int(Buf *number) {
94 // TODO: think about integer size of array sizes
95 return atoi(buf_ptr(number));
96}
97
71static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {98static 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;
1818
19void semantic_analyze(CodeGen *g);19void semantic_analyze(CodeGen *g);
20void add_node_error(CodeGen *g, AstNode *node, Buf *msg);20void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
21TypeTableEntry *new_type_table_entry();
21TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);22TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
22LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);23LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);
2324
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) {
781static void define_primitive_types(CodeGen *g) {781static 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,
448455
449456
450/*457/*
451Type : token(Symbol) | PointerType | token(Unreachable)458Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType
452PointerType : token(Star) token(Const) Type | token(Star) token(Mut) Type;459PointerType : token(Star) (token(Const) | token(Mut)) Type
460ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket)
453*/461*/
454static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token_index) {462static 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 }
486488
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}
495511
496/*512/*
497ParamDecl<node> : token(Symbol) token(Colon) Type {513ParamDecl : token(Symbol) token(Colon) Type
498};
499*/514*/
500static AstNode *ast_parse_param_decl(ParseContext *pc, int token_index, int *new_token_index) {515static 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 {
81enum AstNodeTypeType {81enum AstNodeTypeType {
82 AstNodeTypeTypePrimitive,82 AstNodeTypeTypePrimitive,
83 AstNodeTypeTypePointer,83 AstNodeTypeTypePointer,
84 AstNodeTypeTypeArray,
84};85};
8586
86struct AstNodeType {87struct 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};
9294
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};
2932
30struct ImportTableEntry {33struct 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
23uint32_t int_hash(int i) {
24 return *reinterpret_cast<uint32_t*>(&i);
25}
26bool 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_HPP9#define ZIG_UTIL_HPP
1010
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>
1415
...@@ -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}
8081
82uint32_t int_hash(int i);
83bool int_eq(int a, int b);
84
81#endif85#endif