| ... | ... | @@ -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 { |
| 1891 | | if (true) { |
| 1892 | | @panic("TODO reimplement this"); |
| 1893 | | } |
| 1890 | fn whileExpr( |
| 1891 | mod: *Module, |
| 1892 | scope: *Scope, |
| 1893 | rl: ResultLoc, |
| 1894 | while_node: *ast.Node.While, |
| 1895 | ) InnerError!*zir.Inst { |
| 1894 | 1896 | var cond_kind: CondKind = .bool; |
| 1895 | 1897 | if (while_node.payload) |_| cond_kind = .{ .optional = null }; |
| 1896 | 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 | 1914 | .arena = scope.arena(), |
| 1913 | 1915 | .instructions = .{}, |
| 1914 | 1916 | }; |
| 1917 | setBlockResultLoc(&expr_scope, rl); |
| 1915 | 1918 | defer expr_scope.instructions.deinit(mod.gpa); |
| 1916 | 1919 | |
| 1917 | 1920 | var loop_scope: Scope.GenZIR = .{ |
| ... | ... | @@ -1981,25 +1984,8 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 1981 | 1984 | // declare payload to the then_scope |
| 1982 | 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 |
| 1985 | | // if we need to write to a pointer which has an inferred type, |
| 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 | | }; |
| 1987 | expr_scope.break_count += 1; |
| 1988 | const then_result = try expr(mod, then_sub_scope, expr_scope.break_result_loc, while_node.body); |
| 2003 | 1989 | |
| 2004 | 1990 | var else_scope: Scope.GenZIR = .{ |
| 2005 | 1991 | .parent = &continue_scope.base, |
| ... | ... | @@ -2009,33 +1995,40 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 2009 | 1995 | }; |
| 2010 | 1996 | defer else_scope.instructions.deinit(mod.gpa); |
| 2011 | 1997 | |
| 2012 | | if (while_node.@"else") |else_node| { |
| 2013 | | const else_src = tree.token_locs[else_node.body.lastToken()].start; |
| 1998 | var else_src: usize = undefined; |
| 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 | 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); |
| 2018 | | if (!else_result.tag.isNoReturn()) { |
| 2019 | | _ = try addZIRInst(mod, else_sub_scope, else_src, zir.Inst.Break, .{ |
| 2020 | | .block = while_block, |
| 2021 | | .operand = else_result, |
| 2022 | | }, .{}); |
| 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), |
| 2005 | expr_scope.break_count += 1; |
| 2006 | break :blk try expr(mod, else_sub_scope, expr_scope.break_result_loc, else_node.body); |
| 2007 | } else blk: { |
| 2008 | else_src = tree.token_locs[while_node.lastToken()].start; |
| 2009 | else_sub_scope = &else_scope.base; |
| 2010 | break :blk null; |
| 2032 | 2011 | }; |
| 2033 | 2012 | if (loop_scope.label) |some| { |
| 2034 | 2013 | if (!some.used) { |
| 2035 | 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 | 2034 | fn forExpr( |