From f4b69eb87ca61f408323ab9d24938859f7c4ceb3 Mon Sep 17 00:00:00 2001 From: Jonas Maier Date: Fri, 8 May 2026 19:00:39 +0200 Subject: while loops --- src/run/mod.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 13 deletions(-) (limited to 'src/run') diff --git a/src/run/mod.rs b/src/run/mod.rs index 106e22c..8c45548 100644 --- a/src/run/mod.rs +++ b/src/run/mod.rs @@ -103,6 +103,18 @@ enum SpawnedCmd { Pipeline(SpawnedPipeline), } +trait IsSuccessful { + fn is_successful(&self) -> bool; +} +impl IsSuccessful for Result<(), ExecError> { + fn is_successful(&self) -> bool { + match self { + Ok(_) | Err(ExecError::ExecError(0)) => true, + _ => false, + } + } +} + impl SpawnedCmd { fn join(self) -> Result<(), ExecError> { match self { @@ -244,12 +256,7 @@ impl Executor { ) -> SpawnedCmd { let mut this = self.clone(); let handle = wait::spawn(move || -> Result<(), ExecError> { - for cmd in block.commands { - let cmd = cmd.expand(&mut this)?; - this.execute(cmd, stdin.try_clone()?, stdout.try_clone()?) - .join()?; - } - Ok(()) + this.execute_block_inner(&block, stdin, stdout) }); SpawnedCmd::Fun(handle) } @@ -320,6 +327,7 @@ impl Executor { Ast::VarAssign(va) => self.execute_var_assign(va), Ast::Pipes(pipes) => self.execute_pipeline(pipes, stdin, stdout), Ast::If(cond) => self.execute_if(cond, stdin, stdout), + Ast::While(w) => self.execute_while(w, stdin, stdout), } } @@ -347,6 +355,20 @@ impl Executor { this.exec_loop(cmd, &mut [c1, c2]) } + fn execute_block_inner( + &mut self, + block: &Block, + stdin: InputReader, + stdout: OutputWriter, + ) -> Result<(), ExecError> { + for cmd in block.commands.iter() { + let cmd = cmd.clone().expand(self)?; + self.execute(cmd, stdin.try_clone()?, stdout.try_clone()?) + .join()?; + } + Ok(()) + } + fn execute_if( &mut self, cond: parse::If, @@ -358,14 +380,32 @@ impl Executor { let res = this .execute_pipeline(cond.condition, stdin.try_clone()?, stdout.try_clone()?) .join(); - let block = match res { - Ok(_) | Err(ExecError::ExecError(0)) => cond.true_block, - Err(_) => cond.false_block, + let block = if res.is_successful() { + cond.true_block + } else { + cond.false_block }; - for cmd in block.commands { - let cmd = cmd.expand(&mut this)?; - this.execute(cmd, stdin.try_clone()?, stdout.try_clone()?) - .join()?; + this.execute_block_inner(&block, stdin.try_clone()?, stdout.try_clone()?) + }); + SpawnedCmd::Fun(handle) + } + + fn execute_while( + &mut self, + w: parse::While, + stdin: InputReader, + stdout: OutputWriter, + ) -> SpawnedCmd { + let mut this = self.clone(); + let parse::While { condition, block } = w; + let handle = wait::spawn(move || -> Result<(), ExecError> { + while { + let condition = condition.clone().expand(&mut this)?; + this.execute_pipeline(condition, stdin.try_clone()?, stdout.try_clone()?) + .join() + .is_successful() + } { + this.execute_block_inner(&block, stdin.try_clone()?, stdout.try_clone()?)?; } Ok(()) }); -- cgit v1.2.3