mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
constant initializers allow simple expressions
This commit is contained in:
parent
83b68c9f13
commit
4dc2b82506
4 changed files with 56 additions and 19 deletions
|
|
@ -1027,8 +1027,8 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
|
|||
{
|
||||
AstNode *op1 = node->data.bin_op_expr.op1;
|
||||
AstNode *op2 = node->data.bin_op_expr.op2;
|
||||
TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1);
|
||||
TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2);
|
||||
TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1);
|
||||
TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2);
|
||||
|
||||
TypeTableEntry *return_type = nullptr;
|
||||
|
||||
|
|
@ -1191,21 +1191,25 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
|||
|
||||
case NodeTypeReturnExpr:
|
||||
{
|
||||
TypeTableEntry *expected_return_type = get_return_type(context);
|
||||
TypeTableEntry *actual_return_type;
|
||||
if (node->data.return_expr.expr) {
|
||||
actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
|
||||
if (context->fn_entry) {
|
||||
TypeTableEntry *expected_return_type = get_return_type(context);
|
||||
TypeTableEntry *actual_return_type;
|
||||
if (node->data.return_expr.expr) {
|
||||
actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
|
||||
} else {
|
||||
actual_return_type = g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
if (actual_return_type->id == TypeTableEntryIdUnreachable) {
|
||||
// "return exit(0)" should just be "exit(0)".
|
||||
add_node_error(g, node, buf_sprintf("returning is unreachable"));
|
||||
actual_return_type = g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
check_type_compatibility(g, node, expected_return_type, actual_return_type);
|
||||
} else {
|
||||
actual_return_type = g->builtin_types.entry_void;
|
||||
add_node_error(g, node, buf_sprintf("return expression outside function definition"));
|
||||
}
|
||||
|
||||
if (actual_return_type->id == TypeTableEntryIdUnreachable) {
|
||||
// "return exit(0)" should just be "exit(0)".
|
||||
add_node_error(g, node, buf_sprintf("returning is unreachable"));
|
||||
actual_return_type = g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
check_type_compatibility(g, node, expected_return_type, actual_return_type);
|
||||
return_type = g->builtin_types.entry_unreachable;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,6 +270,10 @@ struct NumberLiteralNode {
|
|||
TypeTableEntry *resolved_type;
|
||||
};
|
||||
|
||||
struct VarDeclNode {
|
||||
TypeTableEntry *type;
|
||||
};
|
||||
|
||||
struct CodeGenNode {
|
||||
union {
|
||||
TypeNode type_node; // for NodeTypeType
|
||||
|
|
@ -282,6 +286,7 @@ struct CodeGenNode {
|
|||
FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr
|
||||
CastNode cast_node; // for NodeTypeCastExpr
|
||||
NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral
|
||||
VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration
|
||||
} data;
|
||||
ExprNode expr_node; // for all the expression nodes
|
||||
};
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {
|
|||
}
|
||||
|
||||
static void add_debug_source_node(CodeGen *g, AstNode *node) {
|
||||
if (!g->cur_block_context)
|
||||
return;
|
||||
LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1,
|
||||
g->cur_block_context->di_scope);
|
||||
}
|
||||
|
|
@ -1040,12 +1042,16 @@ static void do_code_gen(CodeGen *g) {
|
|||
for (int i = 0; i < g->global_vars.length; i += 1) {
|
||||
VariableTableEntry *var = g->global_vars.at(i);
|
||||
|
||||
LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr);
|
||||
|
||||
// TODO if the global is exported, set external linkage
|
||||
LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");
|
||||
LLVMValueRef global_value = LLVMAddGlobal(g->module, var->type->type_ref, "");
|
||||
LLVMSetLinkage(global_value, LLVMPrivateLinkage);
|
||||
LLVMSetInitializer(global_value, init_val);
|
||||
|
||||
if (var->is_const) {
|
||||
LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr);
|
||||
LLVMSetInitializer(global_value, init_val);
|
||||
} else {
|
||||
LLVMSetInitializer(global_value, LLVMConstNull(var->type->type_ref));
|
||||
}
|
||||
LLVMSetGlobalConstant(global_value, var->is_const);
|
||||
LLVMSetUnnamedAddr(global_value, true);
|
||||
|
||||
|
|
|
|||
|
|
@ -496,6 +496,21 @@ fn test_foo(foo : Foo) {
|
|||
if foo.b {
|
||||
print_str("OK\n" as string);
|
||||
}
|
||||
}
|
||||
)SOURCE", "OK\n");
|
||||
|
||||
add_simple_case("global variables", R"SOURCE(
|
||||
use "std.zig";
|
||||
|
||||
const g1 : i32 = 1233 + 1;
|
||||
var g2 : i32;
|
||||
|
||||
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
||||
if g2 != 0 { print_str("BAD\n" as string); }
|
||||
g2 = g1;
|
||||
if g2 != 1234 { print_str("BAD\n" as string); }
|
||||
print_str("OK\n" as string);
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "OK\n");
|
||||
}
|
||||
|
|
@ -682,6 +697,13 @@ fn f() {
|
|||
add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
|
||||
fn f(...) {}
|
||||
)SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
|
||||
|
||||
add_compile_fail_case("write to const global variable", R"SOURCE(
|
||||
const x : i32 = 99;
|
||||
fn f() {
|
||||
x = 1;
|
||||
}
|
||||
)SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant variable");
|
||||
}
|
||||
|
||||
static void print_compiler_invocation(TestCase *test_case) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue