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
.execute(TestScriptArgs {
msg: "'Hello World'".to_string(), 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,8 +94,12 @@ impl NuExecutor {
) )
.into_diagnostic()?; .into_diagnostic()?;
let args = mem::take(&mut self.args);
// block in a different thread to be able to execute scripts in parallel
tokio::task::spawn_blocking(move || {
// TODO: Create the AST for the call here instead of parsing it from a string // TODO: Create the AST for the call here instead of parsing it from a string
let args = format!("main {}", self.args.join(" ")); let args = format!("main {}", args.join(" "));
nu_cli::eval_source( nu_cli::eval_source(
&mut engine_state, &mut engine_state,
&mut stack, &mut stack,
@ -101,6 +107,8 @@ impl NuExecutor {
"<commandline>", "<commandline>",
input, 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)| {
(
working_set.add_variable(
name.as_bytes().to_vec(), name.as_bytes().to_vec(),
Span::new(0, 0), Span::new(0, 0),
nu_protocol::Type::String, nu_protocol::Type::String,
); ),
stack.add_var(var_id, value); 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