| ... | ... | @@ -553,6 +553,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 553 | 553 | mod, |
| 554 | 554 | scope, |
| 555 | 555 | rl, |
| 556 | node, |
| 556 | 557 | node_datas[node].lhs, |
| 557 | 558 | main_tokens[node], |
| 558 | 559 | .is_null_ptr, |
| ... | ... | @@ -565,6 +566,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 565 | 566 | mod, |
| 566 | 567 | scope, |
| 567 | 568 | rl, |
| 569 | node, |
| 568 | 570 | node_datas[node].lhs, |
| 569 | 571 | main_tokens[node], |
| 570 | 572 | .is_null, |
| ... | ... | @@ -1633,6 +1635,7 @@ fn orelseCatchExpr( |
| 1633 | 1635 | mod: *Module, |
| 1634 | 1636 | scope: *Scope, |
| 1635 | 1637 | rl: ResultLoc, |
| 1638 | node: ast.Node.Index, |
| 1636 | 1639 | lhs: ast.Node.Index, |
| 1637 | 1640 | op_token: ast.TokenIndex, |
| 1638 | 1641 | cond_op: zir.Inst.Tag, |
| ... | ... | @@ -1641,16 +1644,11 @@ fn orelseCatchExpr( |
| 1641 | 1644 | rhs: ast.Node.Index, |
| 1642 | 1645 | payload_token: ?ast.TokenIndex, |
| 1643 | 1646 | ) InnerError!zir.Inst.Ref { |
| 1644 | | if (true) @panic("TODO update for zir-memory-layout"); |
| 1645 | | |
| 1646 | | const gz = scope.getGenZir(); |
| 1647 | | const tree = gz.tree(); |
| 1648 | | |
| 1647 | const parent_gz = scope.getGenZir(); |
| 1649 | 1648 | var block_scope: Scope.GenZir = .{ |
| 1650 | 1649 | .parent = scope, |
| 1651 | | .decl = scope.ownerDecl().?, |
| 1652 | | .arena = scope.arena(), |
| 1653 | | .force_comptime = gz.force_comptime, |
| 1650 | .zir_code = parent_gz.zir_code, |
| 1651 | .force_comptime = parent_gz.force_comptime, |
| 1654 | 1652 | .instructions = .{}, |
| 1655 | 1653 | }; |
| 1656 | 1654 | setBlockResultLoc(&block_scope, rl); |
| ... | ... | @@ -1661,62 +1659,73 @@ fn orelseCatchExpr( |
| 1661 | 1659 | // type, whereas this expression has the optional type. Later we make |
| 1662 | 1660 | // up for this fact by calling rvalue on the else branch. |
| 1663 | 1661 | block_scope.break_count += 1; |
| 1664 | | const operand_rl = try makeOptionalTypeResultLoc(mod, &block_scope.base, src, block_scope.break_result_loc); |
| 1662 | |
| 1663 | // TODO handle catch |
| 1664 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 1665 | .ref => .ref, |
| 1666 | .discard, .none, .block_ptr, .inferred_ptr, .bitcasted_ptr => .none, |
| 1667 | .ty => |elem_ty| blk: { |
| 1668 | const wrapped_ty = try block_scope.addUnNode(.optional_type, elem_ty, node); |
| 1669 | break :blk .{ .ty = wrapped_ty }; |
| 1670 | }, |
| 1671 | .ptr => |ptr_ty| blk: { |
| 1672 | const wrapped_ty = try block_scope.addUnNode(.optional_type_from_ptr_elem, ptr_ty, node); |
| 1673 | break :blk .{ .ty = wrapped_ty }; |
| 1674 | }, |
| 1675 | }; |
| 1665 | 1676 | const operand = try expr(mod, &block_scope.base, operand_rl, lhs); |
| 1666 | | const cond = try addZIRUnOp(mod, &block_scope.base, src, cond_op, operand); |
| 1677 | const cond = try block_scope.addUnTok(cond_op, operand, op_token); |
| 1667 | 1678 | |
| 1668 | | const condbr = try addZIRInstSpecial(mod, &block_scope.base, src, zir.Inst.CondBr, .{ |
| 1669 | | .condition = cond, |
| 1670 | | .then_body = undefined, // populated below |
| 1671 | | .else_body = undefined, // populated below |
| 1672 | | }, .{}); |
| 1679 | const condbr = try block_scope.addCondBr(node); |
| 1673 | 1680 | |
| 1674 | | const block = try addZIRInstBlock(mod, scope, src, .block, .{ |
| 1675 | | .instructions = try block_scope.arena.dupe(zir.Inst.Ref, block_scope.instructions.items), |
| 1676 | | }); |
| 1681 | const block = try parent_gz.addBlock(.block, node); |
| 1682 | try parent_gz.instructions.append(mod.gpa, block); |
| 1683 | try block_scope.setBlockBody(block); |
| 1677 | 1684 | |
| 1678 | 1685 | var then_scope: Scope.GenZir = .{ |
| 1679 | | .parent = &block_scope.base, |
| 1680 | | .decl = block_scope.decl, |
| 1681 | | .arena = block_scope.arena, |
| 1686 | .parent = scope, |
| 1687 | .zir_code = parent_gz.zir_code, |
| 1682 | 1688 | .force_comptime = block_scope.force_comptime, |
| 1683 | 1689 | .instructions = .{}, |
| 1684 | 1690 | }; |
| 1685 | 1691 | defer then_scope.instructions.deinit(mod.gpa); |
| 1686 | 1692 | |
| 1687 | | var err_val_scope: Scope.LocalVal = undefined; |
| 1688 | | const then_sub_scope = blk: { |
| 1689 | | const payload = payload_token orelse break :blk &then_scope.base; |
| 1690 | | if (mem.eql(u8, tree.tokenSlice(payload), "_")) { |
| 1691 | | return mod.failTok(&then_scope.base, payload, "discard of error capture; omit it instead", .{}); |
| 1692 | | } |
| 1693 | | const err_name = try mod.identifierTokenString(scope, payload); |
| 1694 | | err_val_scope = .{ |
| 1695 | | .parent = &then_scope.base, |
| 1696 | | .gen_zir = &then_scope, |
| 1697 | | .name = err_name, |
| 1698 | | .inst = try addZIRUnOp(mod, &then_scope.base, src, unwrap_code_op, operand), |
| 1699 | | }; |
| 1700 | | break :blk &err_val_scope.base; |
| 1701 | | }; |
| 1693 | if (payload_token != null) @panic("TODO handle catch"); |
| 1694 | // var err_val_scope: Scope.LocalVal = undefined; |
| 1695 | // const then_sub_scope = blk: { |
| 1696 | // const payload = payload_token orelse break :blk &then_scope.base; |
| 1697 | // if (mem.eql(u8, tree.tokenSlice(payload), "_")) { |
| 1698 | // return mod.failTok(&then_scope.base, payload, "discard of error capture; omit it instead", .{}); |
| 1699 | // } |
| 1700 | // const err_name = try mod.identifierTokenString(scope, payload); |
| 1701 | // err_val_scope = .{ |
| 1702 | // .parent = &then_scope.base, |
| 1703 | // .gen_zir = &then_scope, |
| 1704 | // .name = err_name, |
| 1705 | // .inst = try addZIRUnOp(mod, &then_scope.base, src, unwrap_code_op, operand), |
| 1706 | // }; |
| 1707 | // break :blk &err_val_scope.base; |
| 1708 | // }; |
| 1702 | 1709 | |
| 1703 | 1710 | block_scope.break_count += 1; |
| 1704 | | const then_result = try expr(mod, then_sub_scope, block_scope.break_result_loc, rhs); |
| 1711 | const then_result = try expr(mod, &then_scope.base, block_scope.break_result_loc, rhs); |
| 1712 | // We hold off on the break instructions as well as copying the then/else |
| 1713 | // instructions into place until we know whether to keep store_to_block_ptr |
| 1714 | // instructions or not. |
| 1705 | 1715 | |
| 1706 | 1716 | var else_scope: Scope.GenZir = .{ |
| 1707 | | .parent = &block_scope.base, |
| 1708 | | .decl = block_scope.decl, |
| 1709 | | .arena = block_scope.arena, |
| 1717 | .parent = scope, |
| 1718 | .zir_code = parent_gz.zir_code, |
| 1710 | 1719 | .force_comptime = block_scope.force_comptime, |
| 1711 | 1720 | .instructions = .{}, |
| 1712 | 1721 | }; |
| 1713 | 1722 | defer else_scope.instructions.deinit(mod.gpa); |
| 1714 | 1723 | |
| 1715 | 1724 | // This could be a pointer or value depending on `unwrap_op`. |
| 1716 | | const unwrapped_payload = try addZIRUnOp(mod, &else_scope.base, src, unwrap_op, operand); |
| 1725 | const unwrapped_payload = try else_scope.addUnNode(unwrap_op, operand, node); |
| 1717 | 1726 | const else_result = switch (rl) { |
| 1718 | 1727 | .ref => unwrapped_payload, |
| 1719 | | else => try rvalue(mod, &else_scope.base, block_scope.break_result_loc, unwrapped_payload), |
| 1728 | else => try rvalue(mod, &else_scope.base, block_scope.break_result_loc, unwrapped_payload, node), |
| 1720 | 1729 | }; |
| 1721 | 1730 | |
| 1722 | 1731 | return finishThenElseBlock( |
| ... | ... | @@ -1729,8 +1738,8 @@ fn orelseCatchExpr( |
| 1729 | 1738 | &else_scope, |
| 1730 | 1739 | condbr, |
| 1731 | 1740 | cond, |
| 1732 | | src, |
| 1733 | | src, |
| 1741 | node, |
| 1742 | node, |
| 1734 | 1743 | then_result, |
| 1735 | 1744 | else_result, |
| 1736 | 1745 | block, |