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)
144144
145145ParamDecl : 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) Type
149PointerType : token(Star) (token(Const) | token(Mut)) Type
150
151ArrayType : token(LBracket) Type token(Semicolon) Expression token(RBracket)
150152
151153Block : 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)
4848 }
4949}
5050
51TypeTableEntry *new_type_table_entry() {
52 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
53 entry->arrays_by_size.init(2);
54 return entry;
55}
56
5157TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
5258 TypeTableEntry **parent_pointer = is_const ?
5359 &child_type->pointer_const_parent :
5460 &child_type->pointer_mut_parent;
55 const char *const_or_mut_str = is_const ? "const" : "mut";
5661 if (*parent_pointer) {
5762 return *parent_pointer;
5863 } else {
59 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
64 TypeTableEntry *entry = new_type_table_entry();
6065 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
6166 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));
6368 entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
6469 g->pointer_size_bytes * 8, g->pointer_size_bytes * 8, buf_ptr(&entry->name));
6570 g->type_table.put(&entry->name, entry);
......@@ -68,6 +73,28 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
6873 }
6974}
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
7198static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
7299 assert(node->type == NodeTypeType);
73100 assert(!node->codegen_node);
......@@ -98,6 +125,28 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
98125 type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const);
99126 return type_node->entry;
100127 }
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 }
101150 }
102151 zig_unreachable();
103152}
src/analyze.hpp+1
......@@ -18,6 +18,7 @@ struct BlockContext;
1818
1919void semantic_analyze(CodeGen *g);
2020void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
21TypeTableEntry *new_type_table_entry();
2122TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
2223LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);
2324
src/codegen.cpp+6-6
......@@ -781,12 +781,12 @@ static void do_code_gen(CodeGen *g) {
781781static void define_primitive_types(CodeGen *g) {
782782 {
783783 // 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();
785785 buf_init_from_str(&entry->name, "(invalid)");
786786 g->builtin_types.entry_invalid = entry;
787787 }
788788 {
789 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
789 TypeTableEntry *entry = new_type_table_entry();
790790 entry->type_ref = LLVMInt1Type();
791791 buf_init_from_str(&entry->name, "bool");
792792 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 1, 8,
......@@ -795,7 +795,7 @@ static void define_primitive_types(CodeGen *g) {
795795 g->builtin_types.entry_bool = entry;
796796 }
797797 {
798 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
798 TypeTableEntry *entry = new_type_table_entry();
799799 entry->type_ref = LLVMInt8Type();
800800 buf_init_from_str(&entry->name, "u8");
801801 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8,
......@@ -805,7 +805,7 @@ static void define_primitive_types(CodeGen *g) {
805805 }
806806 g->builtin_types.entry_string_literal = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
807807 {
808 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
808 TypeTableEntry *entry = new_type_table_entry();
809809 entry->type_ref = LLVMInt32Type();
810810 buf_init_from_str(&entry->name, "i32");
811811 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32,
......@@ -814,7 +814,7 @@ static void define_primitive_types(CodeGen *g) {
814814 g->builtin_types.entry_i32 = entry;
815815 }
816816 {
817 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
817 TypeTableEntry *entry = new_type_table_entry();
818818 entry->type_ref = LLVMVoidType();
819819 buf_init_from_str(&entry->name, "void");
820820 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0,
......@@ -823,7 +823,7 @@ static void define_primitive_types(CodeGen *g) {
823823 g->builtin_types.entry_void = entry;
824824 }
825825 {
826 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
826 TypeTableEntry *entry = new_type_table_entry();
827827 entry->type_ref = LLVMVoidType();
828828 buf_init_from_str(&entry->name, "unreachable");
829829 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) {
180180 ast_print(node->data.type.child_type, indent + 2);
181181 break;
182182 }
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 }
183190 }
184191 break;
185192 case NodeTypeReturnExpr:
......@@ -448,8 +455,9 @@ static void ast_parse_directives(ParseContext *pc, int *token_index,
448455
449456
450457/*
451Type : token(Symbol) | PointerType | token(Unreachable)
452PointerType : token(Star) token(Const) Type | token(Star) token(Mut) Type;
458Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType
459PointerType : token(Star) (token(Const) | token(Mut)) Type
460ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket)
453461*/
454462static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token_index) {
455463 Token *token = &pc->tokens->at(token_index);
......@@ -463,12 +471,6 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token
463471 } else if (token->id == TokenIdKeywordVoid) {
464472 node->data.type.type = AstNodeTypeTypePrimitive;
465473 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");
472474 } else if (token->id == TokenIdSymbol) {
473475 node->data.type.type = AstNodeTypeTypePrimitive;
474476 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
485487 }
486488
487489 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);
488504 } else {
489505 ast_invalid_token_error(pc, token);
490506 }
......@@ -494,8 +510,7 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token
494510}
495511
496512/*
497ParamDecl<node> : token(Symbol) token(Colon) Type {
498};
513ParamDecl : token(Symbol) token(Colon) Type
499514*/
500515static AstNode *ast_parse_param_decl(ParseContext *pc, int token_index, int *new_token_index) {
501516 Token *param_name = &pc->tokens->at(token_index);
src/parser.hpp+2
......@@ -81,12 +81,14 @@ struct AstNodeParamDecl {
8181enum AstNodeTypeType {
8282 AstNodeTypeTypePrimitive,
8383 AstNodeTypeTypePointer,
84 AstNodeTypeTypeArray,
8485};
8586
8687struct AstNodeType {
8788 AstNodeTypeType type;
8889 Buf primitive_name;
8990 AstNode *child_type;
91 AstNode *array_size;
9092 bool is_const;
9193};
9294
src/semantic_info.hpp+3
......@@ -23,8 +23,11 @@ struct TypeTableEntry {
2323 bool pointer_is_const;
2424 int user_defined_id;
2525 Buf name;
26
27 // use these fields to make sure we don't duplicate type table entries for the same type
2628 TypeTableEntry *pointer_const_parent;
2729 TypeTableEntry *pointer_mut_parent;
30 HashMap<int, TypeTableEntry *, int_hash, int_eq> arrays_by_size;
2831};
2932
3033struct ImportTableEntry {
src/tokenizer.cpp+10
......@@ -259,6 +259,14 @@ void tokenize(Buf *buf, Tokenization *out) {
259259 begin_token(&t, TokenIdRBrace);
260260 end_token(&t);
261261 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;
262270 case ';':
263271 begin_token(&t, TokenIdSemicolon);
264272 end_token(&t);
......@@ -601,6 +609,8 @@ static const char * token_name(Token *token) {
601609 case TokenIdStar: return "Star";
602610 case TokenIdLBrace: return "LBrace";
603611 case TokenIdRBrace: return "RBrace";
612 case TokenIdLBracket: return "LBracket";
613 case TokenIdRBracket: return "RBracket";
604614 case TokenIdStringLiteral: return "StringLiteral";
605615 case TokenIdSemicolon: return "Semicolon";
606616 case TokenIdNumberLiteral: return "NumberLiteral";
src/tokenizer.hpp+2
......@@ -36,6 +36,8 @@ enum TokenId {
3636 TokenIdStar,
3737 TokenIdLBrace,
3838 TokenIdRBrace,
39 TokenIdLBracket,
40 TokenIdRBracket,
3941 TokenIdStringLiteral,
4042 TokenIdSemicolon,
4143 TokenIdNumberLiteral,
src/util.cpp+7
......@@ -19,3 +19,10 @@ void zig_panic(const char *format, ...) {
1919 va_end(ap);
2020 abort();
2121}
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 @@
99#define ZIG_UTIL_HPP
1010
1111#include <stdlib.h>
12#include <stdint.h>
1213#include <string.h>
1314#include <assert.h>
1415
......@@ -78,4 +79,7 @@ static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str)
7879 return memcmp(mem, str, mem_len) == 0;
7980}
8081
82uint32_t int_hash(int i);
83bool int_eq(int a, int b);
84
8185#endif