@@ -1458,10 +1458,7 @@ impl Interpreter {
14581458 ) ) ;
14591459 }
14601460
1461- let mut stdout = String :: new ( ) ;
1462- let mut stderr = String :: new ( ) ;
1463- let mut exit_code = 0 ;
1464- let mut last_errexit_suppressed = false ;
1461+ let mut acc = state:: LoopAccumulator :: new ( ) ;
14651462
14661463 // Get iteration values: expand fields, then apply brace/glob expansion
14671464 let values: Vec < String > = if let Some ( words) = & for_cmd. words {
@@ -1514,65 +1511,15 @@ impl Interpreter {
15141511 let emit_before = self . output_emit_count ;
15151512 let result = self . execute_command_sequence ( & for_cmd. body ) . await ?;
15161513 self . maybe_emit_output ( & result. stdout , & result. stderr , emit_before) ;
1517- stdout. push_str ( & result. stdout ) ;
1518- stderr. push_str ( & result. stderr ) ;
1519- exit_code = result. exit_code ;
1520- last_errexit_suppressed = result. errexit_suppressed ;
1521-
1522- // Check for break/continue
1523- match result. control_flow {
1524- ControlFlow :: Break ( n) => {
1525- if n <= 1 {
1526- break ;
1527- } else {
1528- // Propagate break with decremented count
1529- return Ok ( ExecResult {
1530- stdout,
1531- stderr,
1532- exit_code,
1533- control_flow : ControlFlow :: Break ( n - 1 ) ,
1534- ..Default :: default ( )
1535- } ) ;
1536- }
1537- }
1538- ControlFlow :: Continue ( n) => {
1539- if n <= 1 {
1540- continue ;
1541- } else {
1542- // Propagate continue with decremented count
1543- return Ok ( ExecResult {
1544- stdout,
1545- stderr,
1546- exit_code,
1547- control_flow : ControlFlow :: Continue ( n - 1 ) ,
1548- ..Default :: default ( )
1549- } ) ;
1550- }
1551- }
1552- ControlFlow :: Return ( code) => {
1553- // Propagate return
1554- return Ok ( ExecResult {
1555- stdout,
1556- stderr,
1557- exit_code : code,
1558- control_flow : ControlFlow :: Return ( code) ,
1559- ..Default :: default ( )
1560- } ) ;
1561- }
1562- ControlFlow :: None => {
1563- // errexit is already handled by execute_command_sequence_impl
1564- }
1514+ match acc. accumulate ( result) {
1515+ state:: LoopAction :: None => { }
1516+ state:: LoopAction :: Break => break ,
1517+ state:: LoopAction :: Continue => continue ,
1518+ state:: LoopAction :: Exit ( r) => return Ok ( r) ,
15651519 }
15661520 }
15671521
1568- Ok ( ExecResult {
1569- stdout,
1570- stderr,
1571- exit_code,
1572- control_flow : ControlFlow :: None ,
1573- errexit_suppressed : last_errexit_suppressed,
1574- ..Default :: default ( )
1575- } )
1522+ Ok ( acc. finish ( ) )
15761523 }
15771524
15781525 /// Execute a select loop: select var in list; do body; done
@@ -1752,10 +1699,7 @@ impl Interpreter {
17521699 & mut self ,
17531700 arith_for : & ArithmeticForCommand ,
17541701 ) -> Result < ExecResult > {
1755- let mut stdout = String :: new ( ) ;
1756- let mut stderr = String :: new ( ) ;
1757- let mut exit_code = 0 ;
1758- let mut last_errexit_suppressed = false ;
1702+ let mut acc = state:: LoopAccumulator :: new ( ) ;
17591703
17601704 // Execute initialization
17611705 if !arith_for. init . is_empty ( ) {
@@ -1781,50 +1725,10 @@ impl Interpreter {
17811725 let emit_before = self . output_emit_count ;
17821726 let result = self . execute_command_sequence ( & arith_for. body ) . await ?;
17831727 self . maybe_emit_output ( & result. stdout , & result. stderr , emit_before) ;
1784- stdout. push_str ( & result. stdout ) ;
1785- stderr. push_str ( & result. stderr ) ;
1786- exit_code = result. exit_code ;
1787- last_errexit_suppressed = result. errexit_suppressed ;
1788-
1789- // Check for break/continue
1790- match result. control_flow {
1791- ControlFlow :: Break ( n) => {
1792- if n <= 1 {
1793- break ;
1794- } else {
1795- return Ok ( ExecResult {
1796- stdout,
1797- stderr,
1798- exit_code,
1799- control_flow : ControlFlow :: Break ( n - 1 ) ,
1800- ..Default :: default ( )
1801- } ) ;
1802- }
1803- }
1804- ControlFlow :: Continue ( n) => {
1805- if n > 1 {
1806- return Ok ( ExecResult {
1807- stdout,
1808- stderr,
1809- exit_code,
1810- control_flow : ControlFlow :: Continue ( n - 1 ) ,
1811- ..Default :: default ( )
1812- } ) ;
1813- }
1814- // n <= 1: continue to next iteration (after step)
1815- }
1816- ControlFlow :: Return ( code) => {
1817- return Ok ( ExecResult {
1818- stdout,
1819- stderr,
1820- exit_code : code,
1821- control_flow : ControlFlow :: Return ( code) ,
1822- ..Default :: default ( )
1823- } ) ;
1824- }
1825- ControlFlow :: None => {
1826- // errexit is already handled by execute_command_sequence_impl
1827- }
1728+ match acc. accumulate ( result) {
1729+ state:: LoopAction :: None | state:: LoopAction :: Continue => { }
1730+ state:: LoopAction :: Break => break ,
1731+ state:: LoopAction :: Exit ( r) => return Ok ( r) ,
18281732 }
18291733
18301734 // Execute step
@@ -1833,14 +1737,7 @@ impl Interpreter {
18331737 }
18341738 }
18351739
1836- Ok ( ExecResult {
1837- stdout,
1838- stderr,
1839- exit_code,
1840- control_flow : ControlFlow :: None ,
1841- errexit_suppressed : last_errexit_suppressed,
1842- ..Default :: default ( )
1843- } )
1740+ Ok ( acc. finish ( ) )
18441741 }
18451742
18461743 /// Execute an arithmetic command ((expression))
@@ -2187,10 +2084,7 @@ impl Interpreter {
21872084 body : & [ Command ] ,
21882085 break_on_zero : bool ,
21892086 ) -> Result < ExecResult > {
2190- let mut stdout = String :: new ( ) ;
2191- let mut stderr = String :: new ( ) ;
2192- let mut exit_code = 0 ;
2193- let mut last_errexit_suppressed = false ;
2087+ let mut acc = state:: LoopAccumulator :: new ( ) ;
21942088
21952089 // Reset loop counter for this loop
21962090 self . counters . reset_loop ( ) ;
@@ -2208,8 +2102,8 @@ impl Interpreter {
22082102 & condition_result. stderr ,
22092103 emit_before_cond,
22102104 ) ;
2211- stdout. push_str ( & condition_result. stdout ) ;
2212- stderr. push_str ( & condition_result. stderr ) ;
2105+ acc . stdout . push_str ( & condition_result. stdout ) ;
2106+ acc . stderr . push_str ( & condition_result. stderr ) ;
22132107 let should_break = if break_on_zero {
22142108 condition_result. exit_code == 0
22152109 } else {
@@ -2223,62 +2117,15 @@ impl Interpreter {
22232117 let emit_before = self . output_emit_count ;
22242118 let result = self . execute_command_sequence ( body) . await ?;
22252119 self . maybe_emit_output ( & result. stdout , & result. stderr , emit_before) ;
2226- stdout. push_str ( & result. stdout ) ;
2227- stderr. push_str ( & result. stderr ) ;
2228- exit_code = result. exit_code ;
2229- last_errexit_suppressed = result. errexit_suppressed ;
2230-
2231- // Check for break/continue
2232- match result. control_flow {
2233- ControlFlow :: Break ( n) => {
2234- if n <= 1 {
2235- break ;
2236- } else {
2237- return Ok ( ExecResult {
2238- stdout,
2239- stderr,
2240- exit_code,
2241- control_flow : ControlFlow :: Break ( n - 1 ) ,
2242- ..Default :: default ( )
2243- } ) ;
2244- }
2245- }
2246- ControlFlow :: Continue ( n) => {
2247- if n <= 1 {
2248- continue ;
2249- } else {
2250- return Ok ( ExecResult {
2251- stdout,
2252- stderr,
2253- exit_code,
2254- control_flow : ControlFlow :: Continue ( n - 1 ) ,
2255- ..Default :: default ( )
2256- } ) ;
2257- }
2258- }
2259- ControlFlow :: Return ( code) => {
2260- return Ok ( ExecResult {
2261- stdout,
2262- stderr,
2263- exit_code : code,
2264- control_flow : ControlFlow :: Return ( code) ,
2265- ..Default :: default ( )
2266- } ) ;
2267- }
2268- ControlFlow :: None => {
2269- // errexit is already handled by execute_command_sequence_impl
2270- }
2120+ match acc. accumulate ( result) {
2121+ state:: LoopAction :: None => { }
2122+ state:: LoopAction :: Break => break ,
2123+ state:: LoopAction :: Continue => continue ,
2124+ state:: LoopAction :: Exit ( r) => return Ok ( r) ,
22712125 }
22722126 }
22732127
2274- Ok ( ExecResult {
2275- stdout,
2276- stderr,
2277- exit_code,
2278- control_flow : ControlFlow :: None ,
2279- errexit_suppressed : last_errexit_suppressed,
2280- ..Default :: default ( )
2281- } )
2128+ Ok ( acc. finish ( ) )
22822129 }
22832130
22842131 /// Execute a case statement
0 commit comments