Change executor to execute asynchronously

Signed-off-by: trivernis <trivernis@protonmail.com>
init-main
trivernis 2 years ago
parent 27e2f1e810
commit c246a06ce5
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -28,11 +28,13 @@ impl ScriptArgs for TestScriptArgs {
} }
} }
pub fn test_execute() -> AppResult<()> { pub async fn test_execute() -> AppResult<()> {
let loader = ScriptLoader::new(); let loader = ScriptLoader::new();
let test_script = loader.load::<TestScript>()?; let test_script = loader.load::<TestScript>()?;
test_script.execute(TestScriptArgs { test_script
msg: "'Hello World'".to_string(), .execute(TestScriptArgs {
}) msg: "'Hello World'".to_string(),
})
.await
} }

@ -1,4 +1,5 @@
fn main() { #[tokio::main(flavor = "current_thread")]
async fn main() {
color_eyre::install().unwrap(); color_eyre::install().unwrap();
tourmaline::test_execute().unwrap(); tourmaline::test_execute().await.unwrap();
} }

@ -1,10 +1,12 @@
#![allow(unused)] #![allow(unused)]
use std::{ use std::{
collections::HashMap, collections::HashMap,
fs, mem, mem,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use tokio::fs;
use miette::IntoDiagnostic; use miette::IntoDiagnostic;
use nu_protocol::{ use nu_protocol::{
ast::{Block, Call}, ast::{Block, Call},
@ -30,7 +32,7 @@ impl VarValue {
/// An executor for nu scripts /// An executor for nu scripts
pub struct NuExecutor { pub struct NuExecutor {
script_path: String, script_path: PathBuf,
args: Vec<String>, args: Vec<String>,
global_vars: HashMap<String, VarValue>, global_vars: HashMap<String, VarValue>,
} }
@ -38,7 +40,7 @@ pub struct NuExecutor {
impl NuExecutor { impl NuExecutor {
pub fn new<P: AsRef<Path>>(script_path: P) -> Self { pub fn new<P: AsRef<Path>>(script_path: P) -> Self {
Self { Self {
script_path: script_path.as_ref().to_string_lossy().into_owned(), script_path: script_path.as_ref().to_owned(),
args: Vec::new(), args: Vec::new(),
global_vars: HashMap::new(), global_vars: HashMap::new(),
} }
@ -66,7 +68,7 @@ impl NuExecutor {
} }
/// Executes the given script file in a clean nu context. /// Executes the given script file in a clean nu context.
pub fn execute(&mut self) -> AppResult<()> { pub async fn execute(&mut self) -> AppResult<()> {
let mut engine_state = nu_command::create_default_context(); let mut engine_state = nu_command::create_default_context();
let mut stack = nu_protocol::engine::Stack::new(); let mut stack = nu_protocol::engine::Stack::new();
let input = PipelineData::new(Span::new(0, 0)); let input = PipelineData::new(Span::new(0, 0));
@ -80,7 +82,7 @@ impl NuExecutor {
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
add_variables_to_state(vars, &mut engine_state, &mut stack); add_variables_to_state(vars, &mut engine_state, &mut stack);
let block = read_script_file(&self.script_path, &mut engine_state)?; let block = read_script_file(&self.script_path, &mut engine_state).await?;
nu_engine::eval_block( nu_engine::eval_block(
&engine_state, &engine_state,
@ -92,15 +94,21 @@ impl NuExecutor {
) )
.into_diagnostic()?; .into_diagnostic()?;
// TODO: Create the AST for the call here instead of parsing it from a string let args = mem::take(&mut self.args);
let args = format!("main {}", self.args.join(" "));
nu_cli::eval_source( // block in a different thread to be able to execute scripts in parallel
&mut engine_state, tokio::task::spawn_blocking(move || {
&mut stack, // TODO: Create the AST for the call here instead of parsing it from a string
args.as_bytes(), let args = format!("main {}", args.join(" "));
"<commandline>", nu_cli::eval_source(
input, &mut engine_state,
); &mut stack,
args.as_bytes(),
"<commandline>",
input,
);
})
.await;
Ok(()) Ok(())
} }
@ -115,24 +123,36 @@ fn add_variables_to_state(
) { ) {
let state2 = nu_command::create_default_context(); let state2 = nu_command::create_default_context();
let mut working_set = StateWorkingSet::new(&state2); let mut working_set = StateWorkingSet::new(&state2);
for (name, value) in vars { vars.into_iter()
let var_id = working_set.add_variable( .map(|(name, value)| {
name.as_bytes().to_vec(), (
Span::new(0, 0), working_set.add_variable(
nu_protocol::Type::String, name.as_bytes().to_vec(),
); Span::new(0, 0),
stack.add_var(var_id, value); nu_protocol::Type::String,
} ),
value,
)
})
.for_each(|(var_id, value)| stack.add_var(var_id, value));
state.merge_delta(working_set.render()); state.merge_delta(working_set.render());
} }
/// Reads the nu script file and /// Reads the nu script file and
/// returns its root block /// returns its root block
fn read_script_file(path: &str, engine_state: &mut EngineState) -> AppResult<Block> { async fn read_script_file(path: &Path, engine_state: &mut EngineState) -> AppResult<Block> {
let mut working_set = StateWorkingSet::new(engine_state); let mut working_set = StateWorkingSet::new(engine_state);
let script_contents = fs::read(&path).into_diagnostic()?; // TODO: Async
let script_contents = fs::read(&path).await.into_diagnostic()?;
let string_path = path.to_string_lossy().into_owned();
// parse the source file // parse the source file
let (block, err) = nu_parser::parse(&mut working_set, Some(path), &script_contents, false, &[]); let (block, err) = nu_parser::parse(
&mut working_set,
Some(&string_path),
&script_contents,
false,
&[],
);
if let Some(err) = err { if let Some(err) = err {
return Err(AppError::from(err)); return Err(AppError::from(err));

@ -36,7 +36,7 @@ impl<S: Script> NuScript<S> {
} }
/// Executes the script with the given args /// Executes the script with the given args
pub fn execute(&self, args: S::Args) -> AppResult<()> { pub async fn execute(&self, args: S::Args) -> AppResult<()> {
NuExecutor::new(&self.path) NuExecutor::new(&self.path)
.add_args(args.get_args()) .add_args(args.get_args())
.add_global_var("BY_TOURMALINE", VarValue::string("Hello from Tourmaline!")) .add_global_var("BY_TOURMALINE", VarValue::string("Hello from Tourmaline!"))
@ -45,5 +45,6 @@ impl<S: Script> NuScript<S> {
VarValue::string("This variable was provided by tourmaline"), VarValue::string("This variable was provided by tourmaline"),
) )
.execute() .execute()
.await
} }
} }

Loading…
Cancel
Save