| ... | @@ -614,11 +614,16 @@ const CondKind = union(enum) { | ... | @@ -614,11 +614,16 @@ const CondKind = union(enum) { |
| 614 | const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr); | 614 | const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr); |
| 615 | return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result); | 615 | return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result); |
| 616 | }, | 616 | }, |
| 617 | .err_union => unreachable, | 617 | .err_union => { |
| | 618 | const err_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node); |
| | 619 | self.* = .{ .err_union = err_ptr }; |
| | 620 | const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, err_ptr); |
| | 621 | return try addZIRUnOp(mod, &block_scope.base, src, .iserr, result); |
| | 622 | }, |
| 618 | } | 623 | } |
| 619 | } | 624 | } |
| 620 | | 625 | |
| 621 | fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, payload_node: ?*ast.Node) !*Scope { | 626 | fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, src: usize, payload_node: ?*ast.Node) !*Scope { |
| 622 | if (self == .bool) return &then_scope.base; | 627 | if (self == .bool) return &then_scope.base; |
| 623 | | 628 | |
| 624 | const payload = payload_node.?.castTag(.PointerPayload).?; | 629 | const payload = payload_node.?.castTag(.PointerPayload).?; |
| ... | @@ -633,6 +638,21 @@ const CondKind = union(enum) { | ... | @@ -633,6 +638,21 @@ const CondKind = union(enum) { |
| 633 | | 638 | |
| 634 | return mod.failNode(&then_scope.base, payload.value_symbol, "TODO implement payload symbols", .{}); | 639 | return mod.failNode(&then_scope.base, payload.value_symbol, "TODO implement payload symbols", .{}); |
| 635 | } | 640 | } |
| | 641 | |
| | 642 | fn elseSubScope(self: CondKind, mod: *Module, else_scope: *Scope.GenZIR, src: usize, payload_node: ?*ast.Node) !*Scope { |
| | 643 | if (self != .err_union) return &else_scope.base; |
| | 644 | |
| | 645 | const payload_ptr = try addZIRUnOp(mod, &else_scope.base, src, .unwrap_err_unsafe, self.err_union.?); |
| | 646 | |
| | 647 | const payload = payload_node.?.castTag(.Payload).?; |
| | 648 | const ident_node = payload.error_symbol.castTag(.Identifier).?; |
| | 649 | const ident_name = try identifierTokenString(mod, &else_scope.base, ident_node.token); |
| | 650 | if (mem.eql(u8, ident_name, "_")) { |
| | 651 | return &else_scope.base; |
| | 652 | } |
| | 653 | |
| | 654 | return mod.failNode(&else_scope.base, payload.error_symbol, "TODO implement payload symbols", .{}); |
| | 655 | } |
| 636 | }; | 656 | }; |
| 637 | | 657 | |
| 638 | fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) InnerError!*zir.Inst { | 658 | fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) InnerError!*zir.Inst { |
| ... | @@ -643,7 +663,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -643,7 +663,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 643 | if (cond_kind != .optional) { | 663 | if (cond_kind != .optional) { |
| 644 | return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{}); | 664 | return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{}); |
| 645 | } | 665 | } |
| 646 | return mod.failNode(scope, payload, "TODO implement astgen.IfExpr for error unions", .{}); | 666 | cond_kind = .{ .err_union = null }; |
| 647 | } | 667 | } |
| 648 | } | 668 | } |
| 649 | var block_scope: Scope.GenZIR = .{ | 669 | var block_scope: Scope.GenZIR = .{ |
| ... | @@ -667,6 +687,8 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -667,6 +687,8 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 667 | const block = try addZIRInstBlock(mod, scope, if_src, .{ | 687 | const block = try addZIRInstBlock(mod, scope, if_src, .{ |
| 668 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), | 688 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), |
| 669 | }); | 689 | }); |
| | 690 | |
| | 691 | const then_src = tree.token_locs[if_node.body.lastToken()].start; |
| 670 | var then_scope: Scope.GenZIR = .{ | 692 | var then_scope: Scope.GenZIR = .{ |
| 671 | .parent = scope, | 693 | .parent = scope, |
| 672 | .decl = block_scope.decl, | 694 | .decl = block_scope.decl, |
| ... | @@ -676,7 +698,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -676,7 +698,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 676 | defer then_scope.instructions.deinit(mod.gpa); | 698 | defer then_scope.instructions.deinit(mod.gpa); |
| 677 | | 699 | |
| 678 | // declare payload to the then_scope | 700 | // declare payload to the then_scope |
| 679 | const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, if_node.payload); | 701 | const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, if_node.payload); |
| 680 | | 702 | |
| 681 | // Most result location types can be forwarded directly; however | 703 | // Most result location types can be forwarded directly; however |
| 682 | // if we need to write to a pointer which has an inferred type, | 704 | // if we need to write to a pointer which has an inferred type, |
| ... | @@ -689,7 +711,6 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -689,7 +711,6 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 689 | | 711 | |
| 690 | const then_result = try expr(mod, then_sub_scope, branch_rl, if_node.body); | 712 | const then_result = try expr(mod, then_sub_scope, branch_rl, if_node.body); |
| 691 | if (!then_result.tag.isNoReturn()) { | 713 | if (!then_result.tag.isNoReturn()) { |
| 692 | const then_src = tree.token_locs[if_node.body.lastToken()].start; | | |
| 693 | _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{ | 714 | _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{ |
| 694 | .block = block, | 715 | .block = block, |
| 695 | .operand = then_result, | 716 | .operand = then_result, |
| ... | @@ -708,10 +729,13 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -708,10 +729,13 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 708 | defer else_scope.instructions.deinit(mod.gpa); | 729 | defer else_scope.instructions.deinit(mod.gpa); |
| 709 | | 730 | |
| 710 | if (if_node.@"else") |else_node| { | 731 | if (if_node.@"else") |else_node| { |
| 711 | const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body); | 732 | const else_src = tree.token_locs[else_node.body.lastToken()].start; |
| | 733 | // declare payload to the then_scope |
| | 734 | const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload); |
| | 735 | |
| | 736 | const else_result = try expr(mod, else_sub_scope, branch_rl, else_node.body); |
| 712 | if (!else_result.tag.isNoReturn()) { | 737 | if (!else_result.tag.isNoReturn()) { |
| 713 | const else_src = tree.token_locs[else_node.body.lastToken()].start; | 738 | _ = try addZIRInst(mod, else_sub_scope, else_src, zir.Inst.Break, .{ |
| 714 | _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{ | | |
| 715 | .block = block, | 739 | .block = block, |
| 716 | .operand = else_result, | 740 | .operand = else_result, |
| 717 | }, .{}); | 741 | }, .{}); |
| ... | @@ -739,7 +763,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -739,7 +763,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 739 | if (cond_kind != .optional) { | 763 | if (cond_kind != .optional) { |
| 740 | return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{}); | 764 | return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{}); |
| 741 | } | 765 | } |
| 742 | return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for error unions", .{}); | 766 | cond_kind = .{ .err_union = null }; |
| 743 | } | 767 | } |
| 744 | } | 768 | } |
| 745 | | 769 | |
| ... | @@ -796,6 +820,8 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -796,6 +820,8 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 796 | const while_block = try addZIRInstBlock(mod, scope, while_src, .{ | 820 | const while_block = try addZIRInstBlock(mod, scope, while_src, .{ |
| 797 | .instructions = try expr_scope.arena.dupe(*zir.Inst, expr_scope.instructions.items), | 821 | .instructions = try expr_scope.arena.dupe(*zir.Inst, expr_scope.instructions.items), |
| 798 | }); | 822 | }); |
| | 823 | |
| | 824 | const then_src = tree.token_locs[while_node.body.lastToken()].start; |
| 799 | var then_scope: Scope.GenZIR = .{ | 825 | var then_scope: Scope.GenZIR = .{ |
| 800 | .parent = &continue_scope.base, | 826 | .parent = &continue_scope.base, |
| 801 | .decl = continue_scope.decl, | 827 | .decl = continue_scope.decl, |
| ... | @@ -805,7 +831,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -805,7 +831,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 805 | defer then_scope.instructions.deinit(mod.gpa); | 831 | defer then_scope.instructions.deinit(mod.gpa); |
| 806 | | 832 | |
| 807 | // declare payload to the then_scope | 833 | // declare payload to the then_scope |
| 808 | const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, while_node.payload); | 834 | const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload); |
| 809 | | 835 | |
| 810 | // Most result location types can be forwarded directly; however | 836 | // Most result location types can be forwarded directly; however |
| 811 | // if we need to write to a pointer which has an inferred type, | 837 | // if we need to write to a pointer which has an inferred type, |
| ... | @@ -818,7 +844,6 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -818,7 +844,6 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 818 | | 844 | |
| 819 | const then_result = try expr(mod, then_sub_scope, branch_rl, while_node.body); | 845 | const then_result = try expr(mod, then_sub_scope, branch_rl, while_node.body); |
| 820 | if (!then_result.tag.isNoReturn()) { | 846 | if (!then_result.tag.isNoReturn()) { |
| 821 | const then_src = tree.token_locs[while_node.body.lastToken()].start; | | |
| 822 | _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{ | 847 | _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{ |
| 823 | .block = cond_block, | 848 | .block = cond_block, |
| 824 | .operand = then_result, | 849 | .operand = then_result, |
| ... | @@ -837,10 +862,13 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -837,10 +862,13 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 837 | defer else_scope.instructions.deinit(mod.gpa); | 862 | defer else_scope.instructions.deinit(mod.gpa); |
| 838 | | 863 | |
| 839 | if (while_node.@"else") |else_node| { | 864 | if (while_node.@"else") |else_node| { |
| 840 | const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body); | 865 | const else_src = tree.token_locs[else_node.body.lastToken()].start; |
| | 866 | // declare payload to the then_scope |
| | 867 | const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload); |
| | 868 | |
| | 869 | const else_result = try expr(mod, else_sub_scope, branch_rl, else_node.body); |
| 841 | if (!else_result.tag.isNoReturn()) { | 870 | if (!else_result.tag.isNoReturn()) { |
| 842 | const else_src = tree.token_locs[else_node.body.lastToken()].start; | 871 | _ = try addZIRInst(mod, else_sub_scope, else_src, zir.Inst.Break, .{ |
| 843 | _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{ | | |
| 844 | .block = while_block, | 872 | .block = while_block, |
| 845 | .operand = else_result, | 873 | .operand = else_result, |
| 846 | }, .{}); | 874 | }, .{}); |