| ... | @@ -277,10 +277,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr | ... | @@ -277,10 +277,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 277 | .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?), | 277 | .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?), |
| 278 | .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?), | 278 | .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?), |
| 279 | .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?), | 279 | .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?), |
| | 280 | .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?), |
| 280 | | 281 | |
| 281 | .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), | 282 | .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), |
| 282 | .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}), | 283 | .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}), |
| 283 | .OrElse => return mod.failNode(scope, node, "TODO implement astgen.expr for .OrElse", .{}), | | |
| 284 | .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}), | 284 | .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}), |
| 285 | .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}), | 285 | .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}), |
| 286 | .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), | 286 | .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), |
| ... | @@ -790,13 +790,31 @@ fn errorType(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!* | ... | @@ -790,13 +790,31 @@ fn errorType(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!* |
| 790 | } | 790 | } |
| 791 | | 791 | |
| 792 | fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch) InnerError!*zir.Inst { | 792 | fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch) InnerError!*zir.Inst { |
| | 793 | return orelseCatchExpr(mod, scope, rl, node.lhs, node.op_token, .iserr, .unwrap_err_unsafe, node.rhs, node.payload); |
| | 794 | } |
| | 795 | |
| | 796 | fn orelseExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { |
| | 797 | return orelseCatchExpr(mod, scope, rl, node.lhs, node.op_token, .isnull, .unwrap_optional_unsafe, node.rhs, null); |
| | 798 | } |
| | 799 | |
| | 800 | fn orelseCatchExpr( |
| | 801 | mod: *Module, |
| | 802 | scope: *Scope, |
| | 803 | rl: ResultLoc, |
| | 804 | lhs: *ast.Node, |
| | 805 | op_token: ast.TokenIndex, |
| | 806 | cond_op: zir.Inst.Tag, |
| | 807 | unwrap_op: zir.Inst.Tag, |
| | 808 | rhs: *ast.Node, |
| | 809 | payload_node: ?*ast.Node, |
| | 810 | ) InnerError!*zir.Inst { |
| 793 | const tree = scope.tree(); | 811 | const tree = scope.tree(); |
| 794 | const src = tree.token_locs[node.op_token].start; | 812 | const src = tree.token_locs[op_token].start; |
| 795 | | 813 | |
| 796 | const err_union_ptr = try expr(mod, scope, .ref, node.lhs); | 814 | const operand_ptr = try expr(mod, scope, .ref, lhs); |
| 797 | // TODO we could avoid an unnecessary copy if .iserr took a pointer | 815 | // TODO we could avoid an unnecessary copy if .iserr, .isnull took a pointer |
| 798 | const err_union = try addZIRUnOp(mod, scope, src, .deref, err_union_ptr); | 816 | const err_union = try addZIRUnOp(mod, scope, src, .deref, operand_ptr); |
| 799 | const cond = try addZIRUnOp(mod, scope, src, .iserr, err_union); | 817 | const cond = try addZIRUnOp(mod, scope, src, cond_op, err_union); |
| 800 | | 818 | |
| 801 | var block_scope: Scope.GenZIR = .{ | 819 | var block_scope: Scope.GenZIR = .{ |
| 802 | .parent = scope, | 820 | .parent = scope, |
| ... | @@ -825,55 +843,55 @@ fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch) | ... | @@ -825,55 +843,55 @@ fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch) |
| 825 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block }, | 843 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block }, |
| 826 | }; | 844 | }; |
| 827 | | 845 | |
| 828 | var err_scope: Scope.GenZIR = .{ | 846 | var then_scope: Scope.GenZIR = .{ |
| 829 | .parent = scope, | 847 | .parent = scope, |
| 830 | .decl = block_scope.decl, | 848 | .decl = block_scope.decl, |
| 831 | .arena = block_scope.arena, | 849 | .arena = block_scope.arena, |
| 832 | .instructions = .{}, | 850 | .instructions = .{}, |
| 833 | }; | 851 | }; |
| 834 | defer err_scope.instructions.deinit(mod.gpa); | 852 | defer then_scope.instructions.deinit(mod.gpa); |
| 835 | | 853 | |
| 836 | var err_val_scope: Scope.LocalVal = undefined; | 854 | var err_val_scope: Scope.LocalVal = undefined; |
| 837 | const err_sub_scope = blk: { | 855 | const then_sub_scope = blk: { |
| 838 | const payload = node.payload orelse | 856 | const payload = payload_node orelse |
| 839 | break :blk &err_scope.base; | 857 | break :blk &then_scope.base; |
| 840 | | 858 | |
| 841 | const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken()); | 859 | const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken()); |
| 842 | if (mem.eql(u8, err_name, "_")) | 860 | if (mem.eql(u8, err_name, "_")) |
| 843 | break :blk &err_scope.base; | 861 | break :blk &then_scope.base; |
| 844 | | 862 | |
| 845 | const unwrapped_err_ptr = try addZIRUnOp(mod, &err_scope.base, src, .unwrap_err_code, err_union_ptr); | 863 | const unwrapped_err_ptr = try addZIRUnOp(mod, &then_scope.base, src, .unwrap_err_code, operand_ptr); |
| 846 | err_val_scope = .{ | 864 | err_val_scope = .{ |
| 847 | .parent = &err_scope.base, | 865 | .parent = &then_scope.base, |
| 848 | .gen_zir = &err_scope, | 866 | .gen_zir = &then_scope, |
| 849 | .name = err_name, | 867 | .name = err_name, |
| 850 | .inst = try addZIRUnOp(mod, &err_scope.base, src, .deref, unwrapped_err_ptr), | 868 | .inst = try addZIRUnOp(mod, &then_scope.base, src, .deref, unwrapped_err_ptr), |
| 851 | }; | 869 | }; |
| 852 | break :blk &err_val_scope.base; | 870 | break :blk &err_val_scope.base; |
| 853 | }; | 871 | }; |
| 854 | | 872 | |
| 855 | _ = try addZIRInst(mod, &err_scope.base, src, zir.Inst.Break, .{ | 873 | _ = try addZIRInst(mod, &then_scope.base, src, zir.Inst.Break, .{ |
| 856 | .block = block, | 874 | .block = block, |
| 857 | .operand = try expr(mod, err_sub_scope, branch_rl, node.rhs), | 875 | .operand = try expr(mod, then_sub_scope, branch_rl, rhs), |
| 858 | }, .{}); | 876 | }, .{}); |
| 859 | | 877 | |
| 860 | var not_err_scope: Scope.GenZIR = .{ | 878 | var else_scope: Scope.GenZIR = .{ |
| 861 | .parent = scope, | 879 | .parent = scope, |
| 862 | .decl = block_scope.decl, | 880 | .decl = block_scope.decl, |
| 863 | .arena = block_scope.arena, | 881 | .arena = block_scope.arena, |
| 864 | .instructions = .{}, | 882 | .instructions = .{}, |
| 865 | }; | 883 | }; |
| 866 | defer not_err_scope.instructions.deinit(mod.gpa); | 884 | defer else_scope.instructions.deinit(mod.gpa); |
| 867 | | 885 | |
| 868 | const unwrapped_payload = try addZIRUnOp(mod, &not_err_scope.base, src, .unwrap_err_unsafe, err_union_ptr); | 886 | const unwrapped_payload = try addZIRUnOp(mod, &else_scope.base, src, unwrap_op, operand_ptr); |
| 869 | _ = try addZIRInst(mod, &not_err_scope.base, src, zir.Inst.Break, .{ | 887 | _ = try addZIRInst(mod, &else_scope.base, src, zir.Inst.Break, .{ |
| 870 | .block = block, | 888 | .block = block, |
| 871 | .operand = unwrapped_payload, | 889 | .operand = unwrapped_payload, |
| 872 | }, .{}); | 890 | }, .{}); |
| 873 | | 891 | |
| 874 | condbr.positionals.then_body = .{ .instructions = try err_scope.arena.dupe(*zir.Inst, err_scope.instructions.items) }; | 892 | condbr.positionals.then_body = .{ .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items) }; |
| 875 | condbr.positionals.else_body = .{ .instructions = try not_err_scope.arena.dupe(*zir.Inst, not_err_scope.instructions.items) }; | 893 | condbr.positionals.else_body = .{ .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items) }; |
| 876 | return rlWrap(mod, scope, rl, &block.base); | 894 | return rlWrapPtr(mod, scope, rl, &block.base); |
| 877 | } | 895 | } |
| 878 | | 896 | |
| 879 | /// Return whether the identifier names of two tokens are equal. Resolves @"" tokens without allocating. | 897 | /// Return whether the identifier names of two tokens are equal. Resolves @"" tokens without allocating. |