aboutsummaryrefslogtreecommitdiffstats
path: root/src/run/mod.rs
diff options
context:
space:
mode:
authorJonas Maier <jonas@x77.dev>2026-05-08 19:00:39 +0200
committerJonas Maier <jonas@x77.dev>2026-05-08 19:00:39 +0200
commitf4b69eb87ca61f408323ab9d24938859f7c4ceb3 (patch)
treed74bdb4869eb7ce0ee2899ec92244a484ff5b4f4 /src/run/mod.rs
parent5697ecb492579413a7ce9589df6847a3e205c647 (diff)
downloadpish-f4b69eb87ca61f408323ab9d24938859f7c4ceb3.tar.gz
while loops
Diffstat (limited to 'src/run/mod.rs')
-rw-r--r--src/run/mod.rs66
1 files changed, 53 insertions, 13 deletions
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<PostExpansion>,
@@ -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(())
});