| ... | @@ -1887,10 +1887,12 @@ fn copyBodyNoEliding(body: *zir.Body, scope: Module.Scope.GenZIR) !void { | ... | @@ -1887,10 +1887,12 @@ fn copyBodyNoEliding(body: *zir.Body, scope: Module.Scope.GenZIR) !void { |
| 1887 | }; | 1887 | }; |
| 1888 | } | 1888 | } |
| 1889 | | 1889 | |
| 1890 | fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.While) InnerError!*zir.Inst { | 1890 | fn whileExpr( |
| 1891 | if (true) { | 1891 | mod: *Module, |
| 1892 | @panic("TODO reimplement this"); | 1892 | scope: *Scope, |
| 1893 | } | 1893 | rl: ResultLoc, |
| | 1894 | while_node: *ast.Node.While, |
| | 1895 | ) InnerError!*zir.Inst { |
| 1894 | var cond_kind: CondKind = .bool; | 1896 | var cond_kind: CondKind = .bool; |
| 1895 | if (while_node.payload) |_| cond_kind = .{ .optional = null }; | 1897 | if (while_node.payload) |_| cond_kind = .{ .optional = null }; |
| 1896 | if (while_node.@"else") |else_node| { | 1898 | if (while_node.@"else") |else_node| { |
| ... | @@ -1912,6 +1914,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -1912,6 +1914,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 1912 | .arena = scope.arena(), | 1914 | .arena = scope.arena(), |
| 1913 | .instructions = .{}, | 1915 | .instructions = .{}, |
| 1914 | }; | 1916 | }; |
| | 1917 | setBlockResultLoc(&expr_scope, rl); |
| 1915 | defer expr_scope.instructions.deinit(mod.gpa); | 1918 | defer expr_scope.instructions.deinit(mod.gpa); |
| 1916 | | 1919 | |
| 1917 | var loop_scope: Scope.GenZIR = .{ | 1920 | var loop_scope: Scope.GenZIR = .{ |
| ... | @@ -1981,25 +1984,8 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -1981,25 +1984,8 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 1981 | // declare payload to the then_scope | 1984 | // declare payload to the then_scope |
| 1982 | const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload); | 1985 | const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, then_src, while_node.payload); |
| 1983 | | 1986 | |
| 1984 | // Most result location types can be forwarded directly; however | 1987 | expr_scope.break_count += 1; |
| 1985 | // if we need to write to a pointer which has an inferred type, | 1988 | const then_result = try expr(mod, then_sub_scope, expr_scope.break_result_loc, while_node.body); |
| 1986 | // proper type inference requires peer type resolution on the while's | | |
| 1987 | // branches. | | |
| 1988 | const branch_rl: ResultLoc = switch (rl) { | | |
| 1989 | .discard, .none, .ty, .ptr, .ref => rl, | | |
| 1990 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block }, | | |
| 1991 | }; | | |
| 1992 | | | |
| 1993 | const then_result = try expr(mod, then_sub_scope, branch_rl, while_node.body); | | |
| 1994 | if (!then_result.tag.isNoReturn()) { | | |
| 1995 | _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{ | | |
| 1996 | .block = cond_block, | | |
| 1997 | .operand = then_result, | | |
| 1998 | }, .{}); | | |
| 1999 | } | | |
| 2000 | condbr.positionals.then_body = .{ | | |
| 2001 | .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items), | | |
| 2002 | }; | | |
| 2003 | | 1989 | |
| 2004 | var else_scope: Scope.GenZIR = .{ | 1990 | var else_scope: Scope.GenZIR = .{ |
| 2005 | .parent = &continue_scope.base, | 1991 | .parent = &continue_scope.base, |
| ... | @@ -2009,33 +1995,40 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -2009,33 +1995,40 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 2009 | }; | 1995 | }; |
| 2010 | defer else_scope.instructions.deinit(mod.gpa); | 1996 | defer else_scope.instructions.deinit(mod.gpa); |
| 2011 | | 1997 | |
| 2012 | if (while_node.@"else") |else_node| { | 1998 | var else_src: usize = undefined; |
| 2013 | const else_src = tree.token_locs[else_node.body.lastToken()].start; | 1999 | var else_sub_scope: *Module.Scope = undefined; |
| | 2000 | const else_result: ?*zir.Inst = if (while_node.@"else") |else_node| blk: { |
| | 2001 | else_src = tree.token_locs[else_node.body.lastToken()].start; |
| 2014 | // declare payload to the then_scope | 2002 | // declare payload to the then_scope |
| 2015 | const else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload); | 2003 | else_sub_scope = try cond_kind.elseSubScope(mod, &else_scope, else_src, else_node.payload); |
| 2016 | | 2004 | |
| 2017 | const else_result = try expr(mod, else_sub_scope, branch_rl, else_node.body); | 2005 | expr_scope.break_count += 1; |
| 2018 | if (!else_result.tag.isNoReturn()) { | 2006 | break :blk try expr(mod, else_sub_scope, expr_scope.break_result_loc, else_node.body); |
| 2019 | _ = try addZIRInst(mod, else_sub_scope, else_src, zir.Inst.Break, .{ | 2007 | } else blk: { |
| 2020 | .block = while_block, | 2008 | else_src = tree.token_locs[while_node.lastToken()].start; |
| 2021 | .operand = else_result, | 2009 | else_sub_scope = &else_scope.base; |
| 2022 | }, .{}); | 2010 | break :blk null; |
| 2023 | } | | |
| 2024 | } else { | | |
| 2025 | const else_src = tree.token_locs[while_node.lastToken()].start; | | |
| 2026 | _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{ | | |
| 2027 | .block = while_block, | | |
| 2028 | }, .{}); | | |
| 2029 | } | | |
| 2030 | condbr.positionals.else_body = .{ | | |
| 2031 | .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items), | | |
| 2032 | }; | 2011 | }; |
| 2033 | if (loop_scope.label) |some| { | 2012 | if (loop_scope.label) |some| { |
| 2034 | if (!some.used) { | 2013 | if (!some.used) { |
| 2035 | return mod.fail(scope, tree.token_locs[some.token].start, "unused while label", .{}); | 2014 | return mod.fail(scope, tree.token_locs[some.token].start, "unused while label", .{}); |
| 2036 | } | 2015 | } |
| 2037 | } | 2016 | } |
| 2038 | return &while_block.base; | 2017 | return finishThenElseBlock( |
| | 2018 | mod, |
| | 2019 | scope, |
| | 2020 | rl, |
| | 2021 | &expr_scope, |
| | 2022 | &then_scope, |
| | 2023 | &else_scope, |
| | 2024 | &condbr.positionals.then_body, |
| | 2025 | &condbr.positionals.else_body, |
| | 2026 | then_src, |
| | 2027 | else_src, |
| | 2028 | then_result, |
| | 2029 | else_result, |
| | 2030 | while_block, |
| | 2031 | ); |
| 2039 | } | 2032 | } |
| 2040 | | 2033 | |
| 2041 | fn forExpr( | 2034 | fn forExpr( |