mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
add break expression
This commit is contained in:
parent
ffc593b808
commit
5ceaae288c
@ -146,7 +146,7 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)
|
||||
|
||||
PrefixOp : token(Not) | token(Dash) | token(Tilde) | (token(Ampersand) option(token(Const)))
|
||||
|
||||
PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | BlockExpression | token(Symbol) | StructValueExpression
|
||||
PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | Break | BlockExpression | token(Symbol) | StructValueExpression
|
||||
|
||||
StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)
|
||||
|
||||
@ -154,6 +154,8 @@ StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression
|
||||
|
||||
Goto: token(Goto) token(Symbol)
|
||||
|
||||
Break: token(Break)
|
||||
|
||||
GroupedExpression : token(LParen) Expression token(RParen)
|
||||
|
||||
KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False)
|
||||
|
||||
@ -48,6 +48,7 @@ static AstNode *first_executing_node(AstNode *node) {
|
||||
case NodeTypeIfExpr:
|
||||
case NodeTypeLabel:
|
||||
case NodeTypeGoto:
|
||||
case NodeTypeBreak:
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeFieldAccessExpr:
|
||||
case NodeTypeStructDecl:
|
||||
@ -530,6 +531,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
|
||||
case NodeTypeWhileExpr:
|
||||
case NodeTypeLabel:
|
||||
case NodeTypeGoto:
|
||||
case NodeTypeBreak:
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeFieldAccessExpr:
|
||||
case NodeTypeStructField:
|
||||
@ -598,6 +600,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||
case NodeTypeWhileExpr:
|
||||
case NodeTypeLabel:
|
||||
case NodeTypeGoto:
|
||||
case NodeTypeBreak:
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeFieldAccessExpr:
|
||||
case NodeTypeStructField:
|
||||
@ -1360,6 +1363,12 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
|
||||
return g->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
TypeTableEntry *expected_type, AstNode *node)
|
||||
{
|
||||
return g->builtin_types.entry_unreachable;
|
||||
}
|
||||
|
||||
static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||
TypeTableEntry *expected_type, AstNode *node)
|
||||
{
|
||||
@ -1439,6 +1448,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
return_type = g->builtin_types.entry_unreachable;
|
||||
break;
|
||||
}
|
||||
case NodeTypeBreak:
|
||||
return_type = analyze_break_expr(g, import, context, expected_type, node);
|
||||
break;
|
||||
case NodeTypeAsmExpr:
|
||||
{
|
||||
node->data.asm_expr.return_count = 0;
|
||||
@ -1792,6 +1804,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
|
||||
case NodeTypeWhileExpr:
|
||||
case NodeTypeLabel:
|
||||
case NodeTypeGoto:
|
||||
case NodeTypeBreak:
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeFieldAccessExpr:
|
||||
case NodeTypeStructField:
|
||||
|
||||
@ -196,6 +196,7 @@ struct CodeGen {
|
||||
FnTableEntry *cur_fn;
|
||||
LLVMBasicBlockRef cur_basic_block;
|
||||
BlockContext *cur_block_context;
|
||||
LLVMBasicBlockRef cur_break_block;
|
||||
bool c_stdint_used;
|
||||
AstNode *root_export_decl;
|
||||
int version_major;
|
||||
|
||||
@ -1024,13 +1024,23 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
|
||||
LLVMBuildCondBr(g->builder, cond_val, body_block, end_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, body_block);
|
||||
g->cur_break_block = end_block;
|
||||
gen_expr(g, node->data.while_expr.body);
|
||||
g->cur_break_block = nullptr;
|
||||
LLVMBuildBr(g->builder, cond_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, end_block);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
|
||||
assert(node->type == NodeTypeBreak);
|
||||
assert(g->cur_break_block);
|
||||
|
||||
add_debug_source_node(g, node);
|
||||
return LLVMBuildBr(g->builder, g->cur_break_block);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
||||
switch (node->type) {
|
||||
case NodeTypeBinOpExpr:
|
||||
@ -1160,6 +1170,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
||||
case NodeTypeGoto:
|
||||
add_debug_source_node(g, node);
|
||||
return LLVMBuildBr(g->builder, node->codegen_node->data.label_entry->basic_block);
|
||||
case NodeTypeBreak:
|
||||
return gen_break(g, node);
|
||||
case NodeTypeLabel:
|
||||
{
|
||||
LabelTableEntry *label_entry = node->codegen_node->data.label_entry;
|
||||
|
||||
@ -122,6 +122,8 @@ const char *node_type_str(NodeType node_type) {
|
||||
return "Label";
|
||||
case NodeTypeGoto:
|
||||
return "Goto";
|
||||
case NodeTypeBreak:
|
||||
return "Break";
|
||||
case NodeTypeAsmExpr:
|
||||
return "AsmExpr";
|
||||
case NodeTypeFieldAccessExpr:
|
||||
@ -336,6 +338,9 @@ void ast_print(AstNode *node, int indent) {
|
||||
case NodeTypeGoto:
|
||||
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.go_to.name));
|
||||
break;
|
||||
case NodeTypeBreak:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
case NodeTypeAsmExpr:
|
||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||
break;
|
||||
@ -1102,7 +1107,7 @@ static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {
|
||||
}
|
||||
|
||||
/*
|
||||
PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | BlockExpression | token(Symbol) | StructValueExpression
|
||||
PrimaryExpression : token(Number) | token(String) | KeywordLiteral | GroupedExpression | Goto | Break | BlockExpression | token(Symbol) | StructValueExpression
|
||||
*/
|
||||
static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
@ -1156,6 +1161,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
|
||||
|
||||
ast_buf_from_token(pc, dest_symbol, &node->data.go_to.name);
|
||||
return node;
|
||||
} else if (token->id == TokenIdKeywordBreak) {
|
||||
AstNode *node = ast_create_node(pc, NodeTypeBreak, token);
|
||||
*token_index += 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
|
||||
|
||||
@ -48,6 +48,7 @@ enum NodeType {
|
||||
NodeTypeWhileExpr,
|
||||
NodeTypeLabel,
|
||||
NodeTypeGoto,
|
||||
NodeTypeBreak,
|
||||
NodeTypeAsmExpr,
|
||||
NodeTypeStructDecl,
|
||||
NodeTypeStructField,
|
||||
|
||||
@ -656,6 +656,21 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
||||
i += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "loop\nloop\nloop\nloop\n");
|
||||
|
||||
add_simple_case("break out of while loop", R"SOURCE(
|
||||
use "std.zig";
|
||||
export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
|
||||
var i : i32 = 0;
|
||||
while true {
|
||||
if i >= 4 {
|
||||
break;
|
||||
}
|
||||
print_str("loop\n");
|
||||
i += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "loop\nloop\nloop\nloop\n");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user