authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-14 23:49:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-14 23:49:56-07:00
log4dc2b8250638efda3a9990182f46ad57c403b28b
tree25ced26eb3a257753ac0b877326eea82697960d1
parent83b68c9f13c90dfbbd2735cde4ef570ac50476c0

constant initializers allow simple expressions


4 files changed, 56 insertions(+), 19 deletions(-)

src/analyze.cpp+19-15
...@@ -1027,8 +1027,8 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -1027,8 +1027,8 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
1027 {1027 {
1028 AstNode *op1 = node->data.bin_op_expr.op1;1028 AstNode *op1 = node->data.bin_op_expr.op1;
1029 AstNode *op2 = node->data.bin_op_expr.op2;1029 AstNode *op2 = node->data.bin_op_expr.op2;
1030 TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1);1030 TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1);
1031 TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2);1031 TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2);
10321032
1033 TypeTableEntry *return_type = nullptr;1033 TypeTableEntry *return_type = nullptr;
10341034
...@@ -1191,21 +1191,25 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -1191,21 +1191,25 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
11911191
1192 case NodeTypeReturnExpr:1192 case NodeTypeReturnExpr:
1193 {1193 {
1194 TypeTableEntry *expected_return_type = get_return_type(context);1194 if (context->fn_entry) {
1195 TypeTableEntry *actual_return_type;1195 TypeTableEntry *expected_return_type = get_return_type(context);
1196 if (node->data.return_expr.expr) {1196 TypeTableEntry *actual_return_type;
1197 actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);1197 if (node->data.return_expr.expr) {
1198 } else {1198 actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
1199 actual_return_type = g->builtin_types.entry_void;1199 } else {
1200 }1200 actual_return_type = g->builtin_types.entry_void;
1201 }
12011202
1202 if (actual_return_type->id == TypeTableEntryIdUnreachable) {1203 if (actual_return_type->id == TypeTableEntryIdUnreachable) {
1203 // "return exit(0)" should just be "exit(0)".1204 // "return exit(0)" should just be "exit(0)".
1204 add_node_error(g, node, buf_sprintf("returning is unreachable"));1205 add_node_error(g, node, buf_sprintf("returning is unreachable"));
1205 actual_return_type = g->builtin_types.entry_invalid;1206 actual_return_type = g->builtin_types.entry_invalid;
1206 }1207 }
12071208
1208 check_type_compatibility(g, node, expected_return_type, actual_return_type);1209 check_type_compatibility(g, node, expected_return_type, actual_return_type);
1210 } else {
1211 add_node_error(g, node, buf_sprintf("return expression outside function definition"));
1212 }
1209 return_type = g->builtin_types.entry_unreachable;1213 return_type = g->builtin_types.entry_unreachable;
1210 break;1214 break;
1211 }1215 }
src/analyze.hpp+5
...@@ -270,6 +270,10 @@ struct NumberLiteralNode {...@@ -270,6 +270,10 @@ struct NumberLiteralNode {
270 TypeTableEntry *resolved_type;270 TypeTableEntry *resolved_type;
271};271};
272272
273struct VarDeclNode {
274 TypeTableEntry *type;
275};
276
273struct CodeGenNode {277struct CodeGenNode {
274 union {278 union {
275 TypeNode type_node; // for NodeTypeType279 TypeNode type_node; // for NodeTypeType
...@@ -282,6 +286,7 @@ struct CodeGenNode {...@@ -282,6 +286,7 @@ struct CodeGenNode {
282 FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr286 FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr
283 CastNode cast_node; // for NodeTypeCastExpr287 CastNode cast_node; // for NodeTypeCastExpr
284 NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral288 NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral
289 VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration
285 } data;290 } data;
286 ExprNode expr_node; // for all the expression nodes291 ExprNode expr_node; // for all the expression nodes
287};292};
src/codegen.cpp+10-4
...@@ -103,6 +103,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {...@@ -103,6 +103,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {
103}103}
104104
105static void add_debug_source_node(CodeGen *g, AstNode *node) {105static void add_debug_source_node(CodeGen *g, AstNode *node) {
106 if (!g->cur_block_context)
107 return;
106 LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1,108 LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1,
107 g->cur_block_context->di_scope);109 g->cur_block_context->di_scope);
108}110}
...@@ -1040,12 +1042,16 @@ static void do_code_gen(CodeGen *g) {...@@ -1040,12 +1042,16 @@ static void do_code_gen(CodeGen *g) {
1040 for (int i = 0; i < g->global_vars.length; i += 1) {1042 for (int i = 0; i < g->global_vars.length; i += 1) {
1041 VariableTableEntry *var = g->global_vars.at(i);1043 VariableTableEntry *var = g->global_vars.at(i);
10421044
1043 LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr);
1044
1045 // TODO if the global is exported, set external linkage1045 // TODO if the global is exported, set external linkage
1046 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");1046 LLVMValueRef global_value = LLVMAddGlobal(g->module, var->type->type_ref, "");
1047 LLVMSetLinkage(global_value, LLVMPrivateLinkage);1047 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
1048 LLVMSetInitializer(global_value, init_val);1048
1049 if (var->is_const) {
1050 LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr);
1051 LLVMSetInitializer(global_value, init_val);
1052 } else {
1053 LLVMSetInitializer(global_value, LLVMConstNull(var->type->type_ref));
1054 }
1049 LLVMSetGlobalConstant(global_value, var->is_const);1055 LLVMSetGlobalConstant(global_value, var->is_const);
1050 LLVMSetUnnamedAddr(global_value, true);1056 LLVMSetUnnamedAddr(global_value, true);
10511057
test/run_tests.cpp+22
...@@ -496,6 +496,21 @@ fn test_foo(foo : Foo) {...@@ -496,6 +496,21 @@ fn test_foo(foo : Foo) {
496 if foo.b {496 if foo.b {
497 print_str("OK\n" as string);497 print_str("OK\n" as string);
498 }498 }
499}
500 )SOURCE", "OK\n");
501
502 add_simple_case("global variables", R"SOURCE(
503use "std.zig";
504
505const g1 : i32 = 1233 + 1;
506var g2 : i32;
507
508export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
509 if g2 != 0 { print_str("BAD\n" as string); }
510 g2 = g1;
511 if g2 != 1234 { print_str("BAD\n" as string); }
512 print_str("OK\n" as string);
513 return 0;
499}514}
500 )SOURCE", "OK\n");515 )SOURCE", "OK\n");
501}516}
...@@ -682,6 +697,13 @@ fn f() {...@@ -682,6 +697,13 @@ fn f() {
682 add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(697 add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
683fn f(...) {}698fn f(...) {}
684 )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");699 )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
700
701 add_compile_fail_case("write to const global variable", R"SOURCE(
702const x : i32 = 99;
703fn f() {
704 x = 1;
705}
706 )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant variable");
685}707}
686708
687static void print_compiler_invocation(TestCase *test_case) {709static void print_compiler_invocation(TestCase *test_case) {