summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-17 18:06:14 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-17 18:06:14 -0500
commitb95a6415d5c85fcbbc5dfc5983838530fdcff190 (patch)
tree7682b731a00180501ae4807eafe6a100ebeafc11
parent1d73e2c9cd196b6bbcda085e4db5ca25d615fb47 (diff)
downloadnbsh-b95a6415d5c85fcbbc5dfc5983838530fdcff190.tar.gz
nbsh-b95a6415d5c85fcbbc5dfc5983838530fdcff190.zip
make eval async
-rw-r--r--src/parse/ast.rs38
-rw-r--r--src/parse/test_ast.rs7
-rw-r--r--src/runner/mod.rs13
3 files changed, 36 insertions, 22 deletions
diff --git a/src/parse/ast.rs b/src/parse/ast.rs
index 089c9f8..b7716df 100644
--- a/src/parse/ast.rs
+++ b/src/parse/ast.rs
@@ -90,13 +90,15 @@ pub struct Pipeline {
}
impl Pipeline {
- pub fn eval(self, env: &Env) -> anyhow::Result<super::Pipeline> {
+ pub async fn eval(self, env: &Env) -> anyhow::Result<super::Pipeline> {
Ok(super::Pipeline {
exes: self
.exes
.into_iter()
.map(|exe| exe.eval(env))
- .collect::<Result<_, _>>()?,
+ .collect::<futures_util::stream::FuturesOrdered<_>>()
+ .collect::<Result<_, _>>()
+ .await?,
})
}
@@ -122,8 +124,8 @@ struct Exe {
}
impl Exe {
- fn eval(self, env: &Env) -> anyhow::Result<super::Exe> {
- let exe = self.exe.eval(env)?;
+ async fn eval(self, env: &Env) -> anyhow::Result<super::Exe> {
+ let exe = self.exe.eval(env).await?;
assert_eq!(exe.len(), 1); // TODO
let exe = &exe[0];
Ok(super::Exe {
@@ -131,8 +133,12 @@ impl Exe {
args: self
.args
.into_iter()
- .map(|arg| arg.eval(env).map(IntoIterator::into_iter))
- .collect::<Result<Vec<_>, _>>()?
+ .map(|arg| async {
+ arg.eval(env).await.map(IntoIterator::into_iter)
+ })
+ .collect::<futures_util::stream::FuturesOrdered<_>>()
+ .collect::<Result<Vec<_>, _>>()
+ .await?
.into_iter()
.flatten()
.collect(),
@@ -140,7 +146,9 @@ impl Exe {
.redirects
.into_iter()
.map(|arg| arg.eval(env))
- .collect::<Result<_, _>>()?,
+ .collect::<futures_util::stream::FuturesOrdered<_>>()
+ .collect::<Result<_, _>>()
+ .await?,
})
}
@@ -218,7 +226,7 @@ impl Word {
}
}
- pub fn eval(self, env: &Env) -> anyhow::Result<Vec<String>> {
+ pub async fn eval(self, env: &Env) -> anyhow::Result<Vec<String>> {
let mut opts = glob::MatchOptions::new();
opts.require_literal_separator = true;
opts.require_literal_leading_dot = true;
@@ -264,7 +272,7 @@ impl Word {
match part {
WordPart::Alternation(_) => unreachable!(),
WordPart::Bareword(_) => {
- let part = part.eval(env);
+ let part = part.eval(env).await;
s.push_str(&part);
pat.push_str(&part);
if part.contains(&['*', '?', '['][..]) {
@@ -274,7 +282,7 @@ impl Word {
WordPart::Var(_)
| WordPart::DoubleQuoted(_)
| WordPart::SingleQuoted(_) => {
- let part = part.eval(env);
+ let part = part.eval(env).await;
s.push_str(&part);
pat.push_str(&glob::Pattern::escape(&part));
}
@@ -357,7 +365,7 @@ impl WordPart {
})
}
- fn eval(self, env: &Env) -> String {
+ async fn eval(self, env: &Env) -> String {
match self {
Self::Alternation(_) => unreachable!(),
Self::Var(name) => {
@@ -399,25 +407,25 @@ impl Redirect {
Self { from, to, dir }
}
- fn eval(self, env: &Env) -> anyhow::Result<super::Redirect> {
+ async fn eval(self, env: &Env) -> anyhow::Result<super::Redirect> {
let to = if self.to.parts.len() == 1 {
if let WordPart::Bareword(s) = &self.to.parts[0] {
if let Some(fd) = s.strip_prefix('&') {
super::RedirectTarget::Fd(parse_fd(fd))
} else {
- let to = self.to.eval(env)?;
+ let to = self.to.eval(env).await?;
assert_eq!(to.len(), 1); // TODO
let to = &to[0];
super::RedirectTarget::File(std::path::PathBuf::from(to))
}
} else {
- let to = self.to.eval(env)?;
+ let to = self.to.eval(env).await?;
assert_eq!(to.len(), 1); // TODO
let to = &to[0];
super::RedirectTarget::File(std::path::PathBuf::from(to))
}
} else {
- let to = self.to.eval(env)?;
+ let to = self.to.eval(env).await?;
assert_eq!(to.len(), 1); // TODO
let to = &to[0];
super::RedirectTarget::File(std::path::PathBuf::from(to))
diff --git a/src/parse/test_ast.rs b/src/parse/test_ast.rs
index f762615..09d772b 100644
--- a/src/parse/test_ast.rs
+++ b/src/parse/test_ast.rs
@@ -156,7 +156,10 @@ macro_rules! eval_eq {
| Command::While(p) => p,
_ => continue,
};
- assert_eq!(pipeline.eval(&$env).unwrap(), expected.remove(0));
+ assert_eq!(
+ async_std::task::block_on(pipeline.eval(&$env)).unwrap(),
+ expected.remove(0)
+ );
}
}};
}
@@ -172,7 +175,7 @@ macro_rules! eval_fails {
}
_ => continue,
};
- if pipeline.eval(&$env).is_err() {
+ if async_std::task::block_on(pipeline.eval(&$env)).is_err() {
fail = true;
}
}
diff --git a/src/runner/mod.rs b/src/runner/mod.rs
index 6d3710e..1633ba0 100644
--- a/src/runner/mod.rs
+++ b/src/runner/mod.rs
@@ -147,10 +147,13 @@ async fn run_commands(
if stack.should_execute() {
list.clone()
.into_iter()
- .map(|w| {
- w.eval(env).map(IntoIterator::into_iter)
+ .map(|w| async {
+ w.eval(env)
+ .await
+ .map(IntoIterator::into_iter)
})
- .collect::<Result<Vec<_>, _>>()?
+ .collect::<futures_util::stream::FuturesOrdered<_>>()
+ .collect::<Result<Vec<_>, _>>().await?
.into_iter()
.flatten()
.collect()
@@ -247,6 +250,7 @@ async fn run_pipeline(
io.set_stderr(stderr);
let pwd = env.pwd().to_path_buf();
+ let pipeline = pipeline.eval(env).await?;
let (children, pg) = spawn_children(pipeline, env, &io)?;
let status = wait_children(children, pg, env, &io, shell_write).await;
set_foreground_pg(nix::unistd::getpid())?;
@@ -270,11 +274,10 @@ async fn write_event(
}
fn spawn_children<'a>(
- pipeline: crate::parse::ast::Pipeline,
+ pipeline: crate::parse::Pipeline,
env: &'a Env,
io: &builtins::Io,
) -> anyhow::Result<(Vec<Child<'a>>, Option<nix::unistd::Pid>)> {
- let pipeline = pipeline.eval(env)?;
let mut cmds: Vec<_> = pipeline
.into_exes()
.map(|exe| Command::new(exe, io.clone()))