parent
fdadab40c6
commit
32642ac9cb
|
@ -474,6 +474,7 @@ struct AstNodeWhileExpr {
|
|||
// populated by semantic analyzer
|
||||
bool condition_always_true;
|
||||
bool contains_break;
|
||||
bool contains_continue;
|
||||
Expr resolved_expr;
|
||||
BlockContext *block_context;
|
||||
};
|
||||
|
@ -486,6 +487,7 @@ struct AstNodeForExpr {
|
|||
|
||||
// populated by semantic analyzer
|
||||
bool contains_break;
|
||||
bool contains_continue;
|
||||
Expr resolved_expr;
|
||||
VariableTableEntry *elem_var;
|
||||
VariableTableEntry *index_var;
|
||||
|
|
|
@ -3354,6 +3354,7 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
|
|||
}
|
||||
|
||||
BlockContext *child_context = new_block_context(node, context);
|
||||
child_context->parent_loop_node = node;
|
||||
|
||||
AstNode *elem_var_node = node->data.for_expr.elem_node;
|
||||
elem_var_node->block_context = child_context;
|
||||
|
@ -3385,8 +3386,13 @@ static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import,
|
|||
|
||||
AstNode *loop_node = context->parent_loop_node;
|
||||
if (loop_node) {
|
||||
assert(loop_node->type == NodeTypeWhileExpr);
|
||||
loop_node->data.while_expr.contains_break = true;
|
||||
if (loop_node->type == NodeTypeWhileExpr) {
|
||||
loop_node->data.while_expr.contains_break = true;
|
||||
} else if (loop_node->type == NodeTypeForExpr) {
|
||||
loop_node->data.for_expr.contains_break = true;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, node, buf_sprintf("'break' expression outside loop"));
|
||||
}
|
||||
|
@ -3396,7 +3402,16 @@ static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import,
|
|||
static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
TypeTableEntry *expected_type, AstNode *node)
|
||||
{
|
||||
if (!context->parent_loop_node) {
|
||||
AstNode *loop_node = context->parent_loop_node;
|
||||
if (loop_node) {
|
||||
if (loop_node->type == NodeTypeWhileExpr) {
|
||||
loop_node->data.while_expr.contains_continue = true;
|
||||
} else if (loop_node->type == NodeTypeForExpr) {
|
||||
loop_node->data.for_expr.contains_continue = true;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, node, buf_sprintf("'continue' expression outside loop"));
|
||||
}
|
||||
return g->builtin_types.entry_unreachable;
|
||||
|
|
|
@ -2089,6 +2089,7 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
|
|||
LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForCond");
|
||||
LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForBody");
|
||||
LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForEnd");
|
||||
LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForContinue");
|
||||
|
||||
LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr);
|
||||
add_debug_source_node(g, node);
|
||||
|
@ -2122,17 +2123,21 @@ static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
|
|||
gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val,
|
||||
elem_var->type, child_type);
|
||||
g->break_block_stack.append(end_block);
|
||||
g->continue_block_stack.append(cond_block);
|
||||
g->continue_block_stack.append(continue_block);
|
||||
gen_expr(g, node->data.for_expr.body);
|
||||
g->break_block_stack.pop();
|
||||
g->continue_block_stack.pop();
|
||||
if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) {
|
||||
add_debug_source_node(g, node);
|
||||
LLVMValueRef new_index_val = LLVMBuildAdd(g->builder, index_val, one_const, "");
|
||||
LLVMBuildStore(g->builder, new_index_val, index_ptr);
|
||||
LLVMBuildBr(g->builder, cond_block);
|
||||
LLVMBuildBr(g->builder, continue_block);
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, continue_block);
|
||||
add_debug_source_node(g, node);
|
||||
LLVMValueRef new_index_val = LLVMBuildAdd(g->builder, index_val, one_const, "");
|
||||
LLVMBuildStore(g->builder, new_index_val, index_ptr);
|
||||
LLVMBuildBr(g->builder, cond_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, end_block);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -52,17 +52,33 @@ error SecondError;
|
|||
#attribute("test")
|
||||
fn constant_enum_with_payload() {
|
||||
should_be_empty(AnEnumWithPayload.Empty);
|
||||
should_be_13(AnEnumWithPayload.Full(13));
|
||||
should_be_not_empty(AnEnumWithPayload.Full(13));
|
||||
}
|
||||
|
||||
fn should_be_empty(x: AnEnumWithPayload) {
|
||||
if (x != AnEnumWithPayload.Empty) unreachable{}
|
||||
}
|
||||
|
||||
fn should_be_13(x: AnEnumWithPayload) {
|
||||
fn should_be_not_empty(x: AnEnumWithPayload) {
|
||||
if (x == AnEnumWithPayload.Empty) unreachable{}
|
||||
}
|
||||
|
||||
enum AnEnumWithPayload {
|
||||
Empty,
|
||||
Full: i32,
|
||||
}
|
||||
|
||||
|
||||
#attribute("test")
|
||||
fn continue_in_for_loop() {
|
||||
const array = []i32 {1, 2, 3, 4, 5};
|
||||
var sum : i32 = 0;
|
||||
for (x, array) {
|
||||
sum += x;
|
||||
if (x < 3) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (sum != 6) unreachable{}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue