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 *op1 = node->data.bin_op_expr.op1;
|
||||||
AstNode *op2 = node->data.bin_op_expr.op2;
|
AstNode *op2 = node->data.bin_op_expr.op2;
|
||||||
TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1);
|
TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1);
|
||||||
TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2);
|
TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2);
|
||||||
|
|
||||||
TypeTableEntry *return_type = nullptr;
|
TypeTableEntry *return_type = nullptr;
|
||||||
|
|
||||||
|
|
@ -1191,21 +1191,25 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||||
|
|
||||||
case NodeTypeReturnExpr:
|
case NodeTypeReturnExpr:
|
||||||
{
|
{
|
||||||
TypeTableEntry *expected_return_type = get_return_type(context);
|
if (context->fn_entry) {
|
||||||
TypeTableEntry *actual_return_type;
|
TypeTableEntry *expected_return_type = get_return_type(context);
|
||||||
if (node->data.return_expr.expr) {
|
TypeTableEntry *actual_return_type;
|
||||||
actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
|
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 {
|
} 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;
|
return_type = g->builtin_types.entry_unreachable;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -270,6 +270,10 @@ struct NumberLiteralNode {
|
||||||
TypeTableEntry *resolved_type;
|
TypeTableEntry *resolved_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VarDeclNode {
|
||||||
|
TypeTableEntry *type;
|
||||||
|
};
|
||||||
|
|
||||||
struct CodeGenNode {
|
struct CodeGenNode {
|
||||||
union {
|
union {
|
||||||
TypeNode type_node; // for NodeTypeType
|
TypeNode type_node; // for NodeTypeType
|
||||||
|
|
@ -282,6 +286,7 @@ struct CodeGenNode {
|
||||||
FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr
|
FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr
|
||||||
CastNode cast_node; // for NodeTypeCastExpr
|
CastNode cast_node; // for NodeTypeCastExpr
|
||||||
NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral
|
NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral
|
||||||
|
VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration
|
||||||
} data;
|
} data;
|
||||||
ExprNode expr_node; // for all the expression nodes
|
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) {
|
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,
|
LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1,
|
||||||
g->cur_block_context->di_scope);
|
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) {
|
for (int i = 0; i < g->global_vars.length; i += 1) {
|
||||||
VariableTableEntry *var = g->global_vars.at(i);
|
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
|
// 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);
|
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);
|
LLVMSetGlobalConstant(global_value, var->is_const);
|
||||||
LLVMSetUnnamedAddr(global_value, true);
|
LLVMSetUnnamedAddr(global_value, true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -496,6 +496,21 @@ fn test_foo(foo : Foo) {
|
||||||
if foo.b {
|
if foo.b {
|
||||||
print_str("OK\n" as string);
|
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");
|
)SOURCE", "OK\n");
|
||||||
}
|
}
|
||||||
|
|
@ -682,6 +697,13 @@ fn f() {
|
||||||
add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
|
add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
|
||||||
fn f(...) {}
|
fn f(...) {}
|
||||||
)SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
|
)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) {
|
static void print_compiler_invocation(TestCase *test_case) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue