use crate::Result;
use crate::common::report::report_error;
use crate::common::syntax::{Mode, parse_arguments};
use std::cell::RefCell;
use std::rc::Rc;
use yash_env::Env;
use yash_env::input::Memory;
use yash_env::parser::Config;
#[cfg(doc)]
use yash_env::semantics::ExitStatus;
use yash_env::semantics::{Field, RunReadEvalLoop};
use yash_env::source::Source;
pub async fn main(env: &mut Env, args: Vec<Field>) -> Result {
let args = match parse_arguments(&[], Mode::with_env(env), args) {
Ok((_options, operands)) => operands,
Err(error) => return report_error(env, &error).await,
};
let command = match join(args) {
Some(command) => command,
None => return Result::default(),
};
let RunReadEvalLoop(run_read_eval_loop) = *env
.any
.get()
.expect("`eval` built-in requires `RunReadEvalLoop` in `Env::any`");
let mut config = Config::with_input(Box::new(Memory::new(&command.value)));
config.source = Some(Rc::new(Source::Eval {
original: command.origin,
}));
let divert = run_read_eval_loop(&RefCell::new(env), config).await;
Result::with_exit_status_and_divert(env.exit_status, divert)
}
fn join(args: Vec<Field>) -> Option<Field> {
let mut args = args.into_iter();
let mut command = args.next()?;
command.value.reserve_exact(
args.as_slice()
.iter()
.map(|arg| 1 + arg.value.len())
.sum::<usize>(),
);
for arg in args {
command.value.push(' ');
command.value.push_str(&arg.value);
}
Some(command)
}