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,
10271027 {
10281028 AstNode *op1 = node->data.bin_op_expr.op1;
10291029 AstNode *op2 = node->data.bin_op_expr.op2;
1030 TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1);
1031 TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2);
1030 TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1);
1031 TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2);
10321032
10331033 TypeTableEntry *return_type = nullptr;
10341034
......@@ -1191,21 +1191,25 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
11911191
11921192 case NodeTypeReturnExpr:
11931193 {
1194 TypeTableEntry *expected_return_type = get_return_type(context);
1195 TypeTableEntry *actual_return_type;
1196 if (node->data.return_expr.expr) {
1197 actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
1198 } else {
1199 actual_return_type = g->builtin_types.entry_void;
1200 }
1194 if (context->fn_entry) {
1195 TypeTableEntry *expected_return_type = get_return_type(context);
1196 TypeTableEntry *actual_return_type;
1197 if (node->data.return_expr.expr) {
1198 actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
1199 } else {
1200 actual_return_type = g->builtin_types.entry_void;
1201 }
12011202
1202 if (actual_return_type->id == TypeTableEntryIdUnreachable) {
1203 // "return exit(0)" should just be "exit(0)".
1204 add_node_error(g, node, buf_sprintf("returning is unreachable"));
1205 actual_return_type = g->builtin_types.entry_invalid;
1206 }
1203 if (actual_return_type->id == TypeTableEntryIdUnreachable) {
1204 // "return exit(0)" should just be "exit(0)".
1205 add_node_error(g, node, buf_sprintf("returning is unreachable"));
1206 actual_return_type = g->builtin_types.entry_invalid;
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 }
12091213 return_type = g->builtin_types.entry_unreachable;
12101214 break;
12111215 }
src/analyze.hpp+5
......@@ -270,6 +270,10 @@ struct NumberLiteralNode {
270270 TypeTableEntry *resolved_type;
271271};
272272
273struct VarDeclNode {
274 TypeTableEntry *type;
275};
276
273277struct CodeGenNode {
274278 union {
275279 TypeNode type_node; // for NodeTypeType
......@@ -282,6 +286,7 @@ struct CodeGenNode {
282286 FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr
283287 CastNode cast_node; // for NodeTypeCastExpr
284288 NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral
289 VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration
285290 } data;
286291 ExprNode expr_node; // for all the expression nodes
287292};
src/codegen.cpp+10-4
......@@ -103,6 +103,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {
103103}
104104
105105static void add_debug_source_node(CodeGen *g, AstNode *node) {
106 if (!g->cur_block_context)
107 return;
106108 LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1,
107109 g->cur_block_context->di_scope);
108110}
......@@ -1040,12 +1042,16 @@ static void do_code_gen(CodeGen *g) {
10401042 for (int i = 0; i < g->global_vars.length; i += 1) {
10411043 VariableTableEntry *var = g->global_vars.at(i);
10421044
1043 LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr);
1044
10451045 // 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, "");
10471047 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 }
10491055 LLVMSetGlobalConstant(global_value, var->is_const);
10501056 LLVMSetUnnamedAddr(global_value, true);
10511057
test/run_tests.cpp+22
......@@ -496,6 +496,21 @@ fn test_foo(foo : Foo) {
496496 if foo.b {
497497 print_str("OK\n" as string);
498498 }
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;
499514}
500515 )SOURCE", "OK\n");
501516}
......@@ -682,6 +697,13 @@ fn f() {
682697 add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
683698fn f(...) {}
684699 )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");
685707}
686708
687709static void print_compiler_invocation(TestCase *test_case) {