Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2025-04-05 14:16:27 -07:00
parent e943303434
commit cb2368dc17
4 changed files with 210 additions and 143 deletions

View File

@ -147,55 +147,6 @@ impl ExecutorContext {
result.map(|result| (result, env_ref, local_state.module_exports))
}
/// Execute an AST's program.
#[async_recursion]
pub(super) async fn preload_all_modules<'a>(
&'a self,
modules: &mut HashMap<String, Program>,
program: NodeRef<'a, Program>,
exec_state: &mut ExecState,
) -> Result<(), KclError> {
for statement in &program.body {
if let BodyItem::ImportStatement(import_stmt) = statement {
let path_str = import_stmt.path.to_string();
if modules.contains_key(&path_str) {
// don't waste our time if we've already loaded the
// module.
continue;
}
let source_range = SourceRange::from(import_stmt);
let attrs = &import_stmt.outer_attrs;
let module_id = self
.open_module(&import_stmt.path, attrs, exec_state, source_range)
.await?;
let Some(module) = exec_state.get_module(module_id) else {
crate::log::log("we got back a module id that doesn't exist");
unreachable!();
};
let progn = {
// this dance is to avoid taking out a mut borrow
// below on exec_state after borrowing here. As a
// result, we need to clone (ugh) the program for
// now.
let ModuleRepr::Kcl(ref progn, _) = module.repr else {
// not a kcl file, we can skip this
continue;
};
progn.clone()
};
modules.insert(path_str, progn.clone().inner);
self.preload_all_modules(modules, &progn, exec_state).await?;
};
}
Ok(())
}
/// Execute an AST's program.
#[async_recursion]
pub(super) async fn exec_block<'a>(
@ -460,7 +411,7 @@ impl ExecutorContext {
Ok(last_expr)
}
pub(super) async fn open_module(
pub async fn open_module(
&self,
path: &ImportPath,
attrs: &[Node<Annotation>],
@ -468,6 +419,7 @@ impl ExecutorContext {
source_range: SourceRange,
) -> Result<ModuleId, KclError> {
let resolved_path = ModulePath::from_import_path(path, &self.settings.project_directory);
match path {
ImportPath::Kcl { .. } => {
exec_state.global.mod_loader.cycle_check(&resolved_path, source_range)?;
@ -597,7 +549,7 @@ impl ExecutorContext {
result
}
async fn exec_module_from_ast(
pub async fn exec_module_from_ast(
&self,
program: &Node<Program>,
module_id: ModuleId,
@ -605,6 +557,7 @@ impl ExecutorContext {
exec_state: &mut ExecState,
source_range: SourceRange,
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
println!("exec_module_from_ast {path}");
exec_state.global.mod_loader.enter_module(path);
let result = self.exec_module_body(program, exec_state, false, module_id, path).await;
exec_state.global.mod_loader.leave_module(path);
@ -2658,6 +2611,7 @@ d = b + c
original_file_contents: "".to_owned(),
},
&mut exec_state,
false,
)
.await
.unwrap();

View File

@ -31,14 +31,14 @@ use tokio::task::JoinSet;
use crate::{
engine::EngineManager,
errors::KclError,
errors::{KclError, KclErrorDetails},
execution::{
artifact::build_artifact_graph,
cache::{CacheInformation, CacheResult},
types::{UnitAngle, UnitLen},
},
fs::FileManager,
modules::{ModuleId, ModulePath},
modules::{ModuleId, ModulePath, ModuleRepr},
parsing::ast::types::{Expr, ImportPath, NodeRef},
source_range::SourceRange,
std::StdLib,
@ -671,7 +671,7 @@ impl ExecutorContext {
(program, exec_state, false)
};
let result = self.inner_run(&program, &mut exec_state, preserve_mem).await;
let result = self.run_concurrent(&program, &mut exec_state, preserve_mem).await;
if result.is_err() {
cache::bust_cache().await;
@ -704,7 +704,7 @@ impl ExecutorContext {
program: &crate::Program,
exec_state: &mut ExecState,
) -> Result<(EnvironmentRef, Option<ModelingSessionData>), KclErrorWithOutputs> {
self.run_concurrent(program, exec_state).await
self.run_concurrent(program, exec_state, false).await
}
/// Perform the execution of a program using an (experimental!) concurrent
@ -721,46 +721,112 @@ impl ExecutorContext {
&self,
program: &crate::Program,
exec_state: &mut ExecState,
preserve_mem: bool,
) -> Result<(EnvironmentRef, Option<ModelingSessionData>), KclErrorWithOutputs> {
self.prepare_mem(exec_state).await.unwrap();
let mut universe = std::collections::HashMap::new();
crate::walk::import_universe(self, &program.ast, &mut universe)
crate::walk::import_universe(self, &program.ast, &mut universe, exec_state)
.await
.unwrap();
.map_err(KclErrorWithOutputs::no_outputs)?;
for modules in crate::walk::import_graph(&universe).unwrap().into_iter() {
for modules in crate::walk::import_graph(&universe, self)
.map_err(KclErrorWithOutputs::no_outputs)?
.into_iter()
{
#[cfg(not(target_arch = "wasm32"))]
let mut set = JoinSet::new();
#[allow(clippy::type_complexity)]
let (results_tx, mut results_rx): (
tokio::sync::mpsc::Sender<(
ModuleId,
ModulePath,
Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError>,
)>,
tokio::sync::mpsc::Receiver<_>,
) = tokio::sync::mpsc::channel(1);
for module in modules {
let program = universe.get(&module).unwrap().clone();
let Some((module_id, module_path, program)) = universe.get(&module) else {
return Err(KclErrorWithOutputs::no_outputs(KclError::Internal(KclErrorDetails {
message: format!("Module {module} not found in universe"),
source_ranges: Default::default(),
})));
};
let module_id = *module_id;
let module_path = module_path.clone();
let program = program.clone();
let exec_state = exec_state.clone();
let exec_ctxt = self.clone();
let results_tx = results_tx.clone();
set.spawn(async move {
println!("Running module {module} from run_concurrent");
let mut exec_state = exec_state;
let exec_ctxt = exec_ctxt;
let program = program;
#[cfg(target_arch = "wasm32")]
{
wasm_bindgen_futures::spawn_local(async move {
//set.spawn(async move {
println!("Running module {module} from run_concurrent");
let mut exec_state = exec_state;
let exec_ctxt = exec_ctxt;
exec_ctxt
.inner_run(
&crate::Program {
ast: program.clone(),
original_file_contents: "".to_owned(),
},
&mut exec_state,
false,
)
.await
});
let result = exec_ctxt
.exec_module_from_ast(
&program,
module_id,
&module_path,
&mut exec_state,
Default::default(),
)
.await;
results_tx.send((module_id, module_path, result)).await.unwrap();
});
}
#[cfg(not(target_arch = "wasm32"))]
{
set.spawn(async move {
println!("Running module {module} from run_concurrent");
let mut exec_state = exec_state;
let exec_ctxt = exec_ctxt;
let result = exec_ctxt
.exec_module_from_ast(
&program,
module_id,
&module_path,
&mut exec_state,
Default::default(),
)
.await;
results_tx.send((module_id, module_path, result)).await.unwrap();
});
}
}
set.join_all().await;
drop(results_tx);
while let Some((module_id, _, result)) = results_rx.recv().await {
match result {
Ok((_, session_data, variables)) => {
let mut repr = exec_state.global.module_infos[&module_id].take_repr();
let ModuleRepr::Kcl(_, cache) = &mut repr else {
continue;
};
*cache = Some((session_data, variables.clone()));
exec_state.global.module_infos[&module_id].restore_repr(repr);
}
Err(e) => {
return Err(KclErrorWithOutputs::no_outputs(e));
}
}
}
}
self.inner_run(program, exec_state, false).await
self.inner_run(program, exec_state, preserve_mem).await
}
/// Perform the execution of a program. Accept all possible parameters and
@ -811,11 +877,11 @@ impl ExecutorContext {
)
})?;
/* if !self.is_mock() {
if !self.is_mock() {
let mut mem = exec_state.stack().deep_clone();
mem.restore_env(env_ref);
cache::write_old_memory((mem, exec_state.global.module_infos.clone())).await;
}*/
}
let session_data = self.engine.get_session_data().await;
Ok((env_ref, session_data))
}

View File

@ -228,7 +228,7 @@ impl ExecState {
self.global.module_infos.insert(id, module_info);
}
pub(super) fn get_module(&mut self, id: ModuleId) -> Option<&ModuleInfo> {
pub fn get_module(&mut self, id: ModuleId) -> Option<&ModuleInfo> {
self.global.module_infos.get(&id)
}