authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-01 14:41:03-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-01 14:41:03-07:00
logc6a9ab107bb383759f3627ed828ea2a779844f2b
tree1bcca15a80247cf083a53a1c51c70a6d3b753064
parentab327344b671bff7f874f24691d7e3f19176167c

string literals have type *const u8


6 files changed, 56 insertions(+), 38 deletions(-)

example/hello_world/hello.zig+1-1
......@@ -2,7 +2,7 @@ export executable "hello";
22
33#link("c")
44extern {
5 fn puts(s: *mut u8) -> i32;
5 fn puts(s: *const u8) -> i32;
66 fn exit(code: i32) -> unreachable;
77}
88
src/analyze.cpp+46-33
......@@ -54,6 +54,26 @@ static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node)
5454 }
5555}
5656
57TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
58 TypeTableEntry **parent_pointer = is_const ?
59 &child_type->pointer_const_parent :
60 &child_type->pointer_mut_parent;
61 const char *const_or_mut_str = is_const ? "const" : "mut";
62 if (*parent_pointer) {
63 return *parent_pointer;
64 } else {
65 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
66 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
67 buf_resize(&entry->name, 0);
68 buf_appendf(&entry->name, "*%s %s", const_or_mut_str, buf_ptr(&child_type->name));
69 entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
70 g->pointer_size_bytes * 8, g->pointer_size_bytes * 8, buf_ptr(&entry->name));
71 g->type_table.put(&entry->name, entry);
72 *parent_pointer = entry;
73 return entry;
74 }
75}
76
5777static void resolve_type(CodeGen *g, AstNode *node) {
5878 assert(!node->codegen_node);
5979 node->codegen_node = allocate<CodeGenNode>(1);
......@@ -75,28 +95,12 @@ static void resolve_type(CodeGen *g, AstNode *node) {
7595 case AstNodeTypeTypePointer:
7696 {
7797 resolve_type(g, node->data.type.child_type);
78 TypeNode *child_type_node = &node->data.type.child_type->codegen_node->data.type_node;
79 if (child_type_node->entry == g->builtin_types.entry_unreachable) {
98 TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry;
99 if (child_type == g->builtin_types.entry_unreachable) {
80100 add_node_error(g, node,
81101 buf_create_from_str("pointer to unreachable not allowed"));
82102 }
83 TypeTableEntry **parent_pointer = node->data.type.is_const ?
84 &child_type_node->entry->pointer_const_parent :
85 &child_type_node->entry->pointer_mut_parent;
86 const char *const_or_mut_str = node->data.type.is_const ? "const" : "mut";
87 if (*parent_pointer) {
88 type_node->entry = *parent_pointer;
89 } else {
90 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
91 entry->type_ref = LLVMPointerType(child_type_node->entry->type_ref, 0);
92 buf_resize(&entry->name, 0);
93 buf_appendf(&entry->name, "*%s %s", const_or_mut_str, buf_ptr(&child_type_node->entry->name));
94 entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type_node->entry->di_type,
95 g->pointer_size_bytes * 8, g->pointer_size_bytes * 8, buf_ptr(&entry->name));
96 g->type_table.put(&entry->name, entry);
97 type_node->entry = entry;
98 *parent_pointer = entry;
99 }
103 type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const);
100104 break;
101105 }
102106 }
......@@ -284,23 +288,26 @@ static TypeTableEntry * get_return_type(BlockContext *context) {
284288}
285289
286290static void check_type_compatibility(CodeGen *g, AstNode *node, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
291 if (expected_type == nullptr)
292 return; // anything will do
287293 if (expected_type == actual_type)
288 return; // good
294 return; // match
289295 if (expected_type == g->builtin_types.entry_invalid || actual_type == g->builtin_types.entry_invalid)
290296 return; // already complained
291297 if (actual_type == g->builtin_types.entry_unreachable)
292298 return; // TODO: is this true?
293299
294300 // TODO better error message
295 add_node_error(g, node, buf_sprintf("type mismatch."));
301 add_node_error(g, node, buf_sprintf("type mismatch. expected %s. got %s", buf_ptr(&expected_type->name), buf_ptr(&actual_type->name)));
296302}
297303
298304static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node) {
305 TypeTableEntry *return_type = nullptr;
299306 switch (node->type) {
300307 case NodeTypeBlock:
301308 {
302309 // TODO: nested block scopes
303 TypeTableEntry *return_type = g->builtin_types.entry_void;
310 return_type = g->builtin_types.entry_void;
304311 for (int i = 0; i < node->data.block.statements.length; i += 1) {
305312 AstNode *child = node->data.block.statements.at(i);
306313 if (return_type == g->builtin_types.entry_unreachable) {
......@@ -310,7 +317,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
310317 }
311318 return_type = analyze_expression(g, import, context, nullptr, child);
312319 }
313 return return_type;
320 break;
314321 }
315322
316323 case NodeTypeReturnExpr:
......@@ -330,7 +337,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
330337 }
331338
332339 check_type_compatibility(g, node, expected_return_type, actual_return_type);
333 return g->builtin_types.entry_unreachable;
340 return_type = g->builtin_types.entry_unreachable;
341 break;
334342 }
335343
336344 case NodeTypeBinOpExpr:
......@@ -338,7 +346,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
338346 // TODO: think about expected types
339347 analyze_expression(g, import, context, expected_type, node->data.bin_op_expr.op1);
340348 analyze_expression(g, import, context, expected_type, node->data.bin_op_expr.op2);
341 return expected_type;
349 return_type = expected_type;
350 break;
342351 }
343352
344353 case NodeTypeFnCallExpr:
......@@ -358,7 +367,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
358367 analyze_expression(g, import, context, nullptr, child);
359368 }
360369
361 return g->builtin_types.entry_invalid;
370 return_type = g->builtin_types.entry_invalid;
362371 } else {
363372 FnTableEntry *fn_table_entry = entry->value;
364373 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
......@@ -388,21 +397,23 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
388397 analyze_expression(g, import, context, expected_param_type, child);
389398 }
390399
391 TypeTableEntry *return_type = fn_proto->return_type->codegen_node->data.type_node.entry;
392 check_type_compatibility(g, node, expected_type, return_type);
393 return return_type;
400 return_type = fn_proto->return_type->codegen_node->data.type_node.entry;
394401 }
402 break;
395403 }
396404
397405 case NodeTypeNumberLiteral:
398406 // TODO: generic literal int type
399 return g->builtin_types.entry_i32;
407 return_type = g->builtin_types.entry_i32;
408 break;
400409
401410 case NodeTypeStringLiteral:
402 zig_panic("TODO: string literal");
411 return_type = g->builtin_types.entry_string_literal;
412 break;
403413
404414 case NodeTypeUnreachable:
405 return g->builtin_types.entry_unreachable;
415 return_type = g->builtin_types.entry_unreachable;
416 break;
406417
407418 case NodeTypeSymbol:
408419 // look up symbol in symbol table
......@@ -423,7 +434,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
423434 case NodeTypeUse:
424435 zig_unreachable();
425436 }
426 zig_unreachable();
437 assert(return_type);
438 check_type_compatibility(g, node, expected_type, return_type);
439 return return_type;
427440}
428441
429442static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
src/analyze.hpp+3
......@@ -12,7 +12,10 @@ struct CodeGen;
1212struct AstNode;
1313struct Buf;
1414
15struct TypeTableEntry;
16
1517void semantic_analyze(CodeGen *g);
1618void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
19TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
1720
1821#endif
src/codegen.cpp+1
......@@ -589,6 +589,7 @@ static void define_primitive_types(CodeGen *g) {
589589 g->type_table.put(&entry->name, entry);
590590 g->builtin_types.entry_u8 = entry;
591591 }
592 g->builtin_types.entry_string_literal = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
592593 {
593594 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
594595 entry->type_ref = LLVMInt32Type();
src/semantic_info.hpp+1
......@@ -65,6 +65,7 @@ struct CodeGen {
6565 struct {
6666 TypeTableEntry *entry_u8;
6767 TypeTableEntry *entry_i32;
68 TypeTableEntry *entry_string_literal;
6869 TypeTableEntry *entry_void;
6970 TypeTableEntry *entry_unreachable;
7071 TypeTableEntry *entry_invalid;
test/run_tests.cpp+4-4
......@@ -99,7 +99,7 @@ static void add_compiling_test_cases(void) {
9999 add_simple_case("hello world with libc", R"SOURCE(
100100 #link("c")
101101 extern {
102 fn puts(s: *mut u8) -> i32;
102 fn puts(s: *const u8) -> i32;
103103 fn exit(code: i32) -> unreachable;
104104 }
105105
......@@ -112,7 +112,7 @@ static void add_compiling_test_cases(void) {
112112 add_simple_case("function call", R"SOURCE(
113113 #link("c")
114114 extern {
115 fn puts(s: *mut u8) -> i32;
115 fn puts(s: *const u8) -> i32;
116116 fn exit(code: i32) -> unreachable;
117117 }
118118
......@@ -134,7 +134,7 @@ static void add_compiling_test_cases(void) {
134134 add_simple_case("comments", R"SOURCE(
135135 #link("c")
136136 extern {
137 fn puts(s: *mut u8) -> i32;
137 fn puts(s: *const u8) -> i32;
138138 fn exit(code: i32) -> unreachable;
139139 }
140140
......@@ -169,7 +169,7 @@ static void add_compiling_test_cases(void) {
169169 add_source_file(tc, "libc.zig", R"SOURCE(
170170 #link("c")
171171 extern {
172 pub fn puts(s: *mut u8) -> i32;
172 pub fn puts(s: *const u8) -> i32;
173173 pub fn exit(code: i32) -> unreachable;
174174 }
175175 )SOURCE");