authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-20 17:03:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-20 17:04:11-07:00
loga62db38d905ad4962c3b37e013c8745ed6ecbfb9
tree5b1bc8f9f44b3937d2a0ce9f408539aa9f2bf2ad
parent458c4b6fc69df38fe119b3213efb56cb0e454193

AstGen: implement defer for `break`


3 files changed, 19 insertions(+), 10 deletions(-)

BRANCH_TODO+1-2
...@@ -1,5 +1,3 @@...@@ -1,5 +1,3 @@
1 * defer
2 - `break`
3 * nested function decl: how to refer to params?1 * nested function decl: how to refer to params?
4 * look for cached zir code2 * look for cached zir code
5 * save zir code to cache3 * save zir code to cache
...@@ -11,6 +9,7 @@...@@ -11,6 +9,7 @@
119
12 * get rid of failed_root_src_file10 * get rid of failed_root_src_file
13 * get rid of Scope.DeclRef11 * get rid of Scope.DeclRef
12 * get rid of optional_type_from_ptr_elem
14 * handle decl collision with usingnamespace13 * handle decl collision with usingnamespace
15 * the decl doing the looking up needs to create a decl dependency14 * the decl doing the looking up needs to create a decl dependency
16 on each usingnamespace decl15 on each usingnamespace decl
src/AstGen.zig+17-7
...@@ -822,7 +822,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -822,7 +822,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
822 .@"await" => return astgen.failNode(node, "async and related features are not yet supported", .{}),822 .@"await" => return astgen.failNode(node, "async and related features are not yet supported", .{}),
823 .@"resume" => return astgen.failNode(node, "async and related features are not yet supported", .{}),823 .@"resume" => return astgen.failNode(node, "async and related features are not yet supported", .{}),
824824
825 .@"try" => return tryExpr(gz, scope, rl, node_datas[node].lhs),825 .@"try" => return tryExpr(gz, scope, rl, node, node_datas[node].lhs),
826826
827 .array_init_one, .array_init_one_comma => {827 .array_init_one, .array_init_one_comma => {
828 var elements: [1]ast.Node.Index = undefined;828 var elements: [1]ast.Node.Index = undefined;
...@@ -1247,8 +1247,13 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn...@@ -1247,8 +1247,13 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn
1247 },1247 },
1248 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,1248 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1249 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,1249 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1250 .defer_normal => @panic("TODO break/defer"),1250 .defer_normal => {
1251 .defer_error => @panic("TODO break/defer"),1251 const defer_scope = scope.cast(Scope.Defer).?;
1252 scope = defer_scope.parent;
1253 const expr_node = node_datas[defer_scope.defer_node].rhs;
1254 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
1255 },
1256 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1252 else => if (break_label != 0) {1257 else => if (break_label != 0) {
1253 const label_name = try astgen.identifierTokenString(break_label);1258 const label_name = try astgen.identifierTokenString(break_label);
1254 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});1259 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
...@@ -1300,7 +1305,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)...@@ -1300,7 +1305,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
1300 const expr_node = node_datas[defer_scope.defer_node].rhs;1305 const expr_node = node_datas[defer_scope.defer_node].rhs;
1301 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);1306 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
1302 },1307 },
1303 .defer_error => scope = scope.cast(Scope.LocalPtr).?.parent,1308 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1304 else => if (break_label != 0) {1309 else => if (break_label != 0) {
1305 const label_name = try astgen.identifierTokenString(break_label);1310 const label_name = try astgen.identifierTokenString(break_label);
1306 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});1311 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
...@@ -3291,10 +3296,15 @@ fn tryExpr(...@@ -3291,10 +3296,15 @@ fn tryExpr(
3291 scope: *Scope,3296 scope: *Scope,
3292 rl: ResultLoc,3297 rl: ResultLoc,
3293 node: ast.Node.Index,3298 node: ast.Node.Index,
3299 operand_node: ast.Node.Index,
3294) InnerError!Zir.Inst.Ref {3300) InnerError!Zir.Inst.Ref {
3295 const astgen = parent_gz.astgen;3301 const astgen = parent_gz.astgen;
3296 const tree = &astgen.file.tree;3302 const tree = &astgen.file.tree;
32973303
3304 const fn_block = astgen.fn_block orelse {
3305 return astgen.failNode(node, "invalid 'try' outside function scope", .{});
3306 };
3307
3298 var block_scope: GenZir = .{3308 var block_scope: GenZir = .{
3299 .parent = scope,3309 .parent = scope,
3300 .decl_node_index = parent_gz.decl_node_index,3310 .decl_node_index = parent_gz.decl_node_index,
...@@ -3320,7 +3330,7 @@ fn tryExpr(...@@ -3320,7 +3330,7 @@ fn tryExpr(
3320 // We cannot use `block_scope.break_result_loc` because that has the bare3330 // We cannot use `block_scope.break_result_loc` because that has the bare
3321 // type, whereas this expression has the optional type. Later we make3331 // type, whereas this expression has the optional type. Later we make
3322 // up for this fact by calling rvalue on the else branch.3332 // up for this fact by calling rvalue on the else branch.
3323 const operand = try expr(&block_scope, &block_scope.base, operand_rl, node);3333 const operand = try expr(&block_scope, &block_scope.base, operand_rl, operand_node);
3324 const cond = try block_scope.addUnNode(err_ops[0], operand, node);3334 const cond = try block_scope.addUnNode(err_ops[0], operand, node);
3325 const condbr = try block_scope.addCondBr(.condbr, node);3335 const condbr = try block_scope.addCondBr(.condbr, node);
33263336
...@@ -3339,7 +3349,7 @@ fn tryExpr(...@@ -3339,7 +3349,7 @@ fn tryExpr(
3339 defer then_scope.instructions.deinit(astgen.gpa);3349 defer then_scope.instructions.deinit(astgen.gpa);
33403350
3341 const err_code = try then_scope.addUnNode(err_ops[1], operand, node);3351 const err_code = try then_scope.addUnNode(err_ops[1], operand, node);
3342 try genDefers(&then_scope, &astgen.fn_block.?.base, scope, err_code);3352 try genDefers(&then_scope, &fn_block.base, scope, err_code);
3343 const then_result = try then_scope.addUnNode(.ret_node, err_code, node);3353 const then_result = try then_scope.addUnNode(.ret_node, err_code, node);
33443354
3345 var else_scope: GenZir = .{3355 var else_scope: GenZir = .{
...@@ -3406,7 +3416,7 @@ fn orelseCatchExpr(...@@ -3406,7 +3416,7 @@ fn orelseCatchExpr(
3406 block_scope.setBreakResultLoc(rl);3416 block_scope.setBreakResultLoc(rl);
3407 defer block_scope.instructions.deinit(astgen.gpa);3417 defer block_scope.instructions.deinit(astgen.gpa);
34083418
3409 // TODO handle catch3419 // TODO get rid of optional_type_from_ptr_elem
3410 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {3420 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
3411 .ref => .ref,3421 .ref => .ref,
3412 .discard, .none, .none_or_ref, .block_ptr, .inferred_ptr => .none,3422 .discard, .none, .none_or_ref, .block_ptr, .inferred_ptr => .none,
src/Module.zig+1-1
...@@ -1813,7 +1813,7 @@ pub const SrcLoc = struct {...@@ -1813,7 +1813,7 @@ pub const SrcLoc = struct {
1813 pub fn byteOffset(src_loc: SrcLoc) !u32 {1813 pub fn byteOffset(src_loc: SrcLoc) !u32 {
1814 switch (src_loc.lazy) {1814 switch (src_loc.lazy) {
1815 .unneeded => unreachable,1815 .unneeded => unreachable,
1816 .entire_file => unreachable,1816 .entire_file => return 0,
18171817
1818 .byte_abs => |byte_index| return byte_index,1818 .byte_abs => |byte_index| return byte_index,
18191819