This commit is contained in:
Paul R. Tagliamonte
2025-03-13 11:17:22 -04:00
parent a590ed99cf
commit 8debbc5241
2 changed files with 92 additions and 29 deletions

View File

@ -144,15 +144,23 @@ impl ExecutorContext {
/// Execute an AST's program. /// Execute an AST's program.
#[async_recursion] #[async_recursion]
pub(super) async fn load_all_modules<'a>( pub(super) async fn preload_all_modules<'a>(
&'a self, &'a self,
modules: &mut HashMap<String, crate::parsing::ast::types::Program>, modules: &mut HashMap<String, Program>,
program: NodeRef<'a, crate::parsing::ast::types::Program>, program: NodeRef<'a, Program>,
exec_state: &mut ExecState, exec_state: &mut ExecState,
) -> Result<(), KclError> { ) -> Result<(), KclError> {
for statement in &program.body { for statement in &program.body {
match statement { match statement {
BodyItem::ImportStatement(import_stmt) => { BodyItem::ImportStatement(import_stmt) => {
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 source_range = SourceRange::from(import_stmt);
let attrs = &import_stmt.outer_attrs; let attrs = &import_stmt.outer_attrs;
let module_id = self let module_id = self
@ -176,7 +184,9 @@ impl ExecutorContext {
progn.clone() progn.clone()
}; };
self.load_all_modules(modules, &progn, exec_state).await?; modules.insert(path_str, progn.clone().inner);
self.preload_all_modules(modules, &progn, exec_state).await?;
} }
_ => {} _ => {}
}; };
@ -188,7 +198,7 @@ impl ExecutorContext {
#[async_recursion] #[async_recursion]
pub(super) async fn exec_block<'a>( pub(super) async fn exec_block<'a>(
&'a self, &'a self,
program: NodeRef<'a, crate::parsing::ast::types::Program>, program: NodeRef<'a, Program>,
exec_state: &mut ExecState, exec_state: &mut ExecState,
body_type: BodyType, body_type: BodyType,
) -> Result<Option<KclValue>, KclError> { ) -> Result<Option<KclValue>, KclError> {
@ -2007,9 +2017,11 @@ impl FunctionSource {
mod test { mod test {
use super::*; use super::*;
use crate::{ use crate::{
execution::{memory::Stack, parse_execute}, execution::{memory::Stack, parse_execute, ContextType},
parsing::ast::types::{DefaultParamVal, Identifier, Parameter}, parsing::ast::types::{DefaultParamVal, Identifier, Parameter},
}; };
use std::sync::Arc;
use tokio::task::JoinSet;
#[test] #[test]
fn test_assign_args_to_params() { fn test_assign_args_to_params() {
@ -2118,7 +2130,7 @@ mod test {
// Run each test. // Run each test.
let func_expr = &Node::no_src(FunctionExpression { let func_expr = &Node::no_src(FunctionExpression {
params, params,
body: crate::parsing::ast::types::Program::empty(), body: Program::empty(),
return_type: None, return_type: None,
digest: None, digest: None,
}); });
@ -2214,7 +2226,7 @@ a = foo()
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn load_all_modules() { async fn load_all_modules() {
let mut universe = HashMap::<String, NodeRef<'_, Program>>::new(); let mut universe = HashMap::<String, Node<Program>>::new();
// program a.kcl // program a.kcl
let programa = r#" let programa = r#"
@ -2223,7 +2235,7 @@ a = 1
let programa = crate::parsing::parse_str(&programa, ModuleId::default()) let programa = crate::parsing::parse_str(&programa, ModuleId::default())
.parse_errs_as_err() .parse_errs_as_err()
.unwrap(); .unwrap();
universe.insert("a.kcl".to_owned(), (&programa).into()); universe.insert("a.kcl".to_owned(), programa);
// program b.kcl // program b.kcl
let programb = r#" let programb = r#"
@ -2232,7 +2244,7 @@ import 'a.kcl' as x
let programb = crate::parsing::parse_str(&programb, ModuleId::default()) let programb = crate::parsing::parse_str(&programb, ModuleId::default())
.parse_errs_as_err() .parse_errs_as_err()
.unwrap(); .unwrap();
universe.insert("b.kcl".to_owned(), (&programb).into()); universe.insert("b.kcl".to_owned(), programb);
// program c.kcl // program c.kcl
let programc = r#" let programc = r#"
@ -2241,13 +2253,64 @@ import 'a.kcl'
let programc = crate::parsing::parse_str(&programc, ModuleId::default()) let programc = crate::parsing::parse_str(&programc, ModuleId::default())
.parse_errs_as_err() .parse_errs_as_err()
.unwrap(); .unwrap();
universe.insert("c.kcl".to_owned(), (&programc).into()); universe.insert("c.kcl".to_owned(), programc);
// ok we have all the "files" loaded, let's do a sort and concurrent // ok we have all the "files" loaded, let's do a sort and concurrent
// run here. // run here.
for modules in crate::walk::import_graph(universe).into_iter() { let exec_ctxt = ExecutorContext {
// engine: Arc::new(Box::new(
crate::engine::conn_mock::EngineConnection::new()
.await
.map_err(|err| {
KclError::Internal(crate::errors::KclErrorDetails {
message: format!("Failed to create mock engine connection: {}", err),
source_ranges: vec![SourceRange::default()],
})
})
.unwrap(),
)),
fs: Arc::new(crate::fs::FileManager::new()),
stdlib: Arc::new(crate::std::StdLib::new()),
settings: Default::default(),
context_type: ContextType::Mock,
};
let mut exec_state = ExecState::new(&exec_ctxt.settings);
eprintln!("{:?}", universe);
for modules in crate::walk::import_graph(&universe).unwrap().into_iter() {
eprintln!("Spawning {:?}", modules);
let mut set = JoinSet::new();
for module in modules {
eprintln!("{:?}", universe.get(&module));
let program = universe.get(&module).unwrap().clone();
let module = module.clone();
let mut exec_state = exec_state.clone();
let exec_ctxt = exec_ctxt.clone();
set.spawn(async move {
let module = module;
let mut exec_state = exec_state;
let exec_ctxt = exec_ctxt;
let program = program;
// do we need to do anything with the result here?
let _ = exec_ctxt
.run(
&crate::Program {
ast: program.clone(),
original_file_contents: "".to_owned(),
},
&mut exec_state,
)
.await
.unwrap();
});
}
set.join_all().await;
} }
} }
} }

View File

@ -6,7 +6,7 @@ use std::{
use anyhow::Result; use anyhow::Result;
use crate::{ use crate::{
parsing::ast::types::{ImportPath, NodeRef, Program}, parsing::ast::types::{ImportPath, Node as AstNode, NodeRef, Program},
walk::{Node, Visitable}, walk::{Node, Visitable},
}; };
@ -23,7 +23,7 @@ type Graph = Vec<Dependency>;
/// run concurrently. Each "stage" is blocking in this model, which will /// run concurrently. Each "stage" is blocking in this model, which will
/// change in the future. Don't use this function widely, yet. /// change in the future. Don't use this function widely, yet.
#[allow(clippy::iter_over_hash_type)] #[allow(clippy::iter_over_hash_type)]
pub fn import_graph(progs: HashMap<String, NodeRef<'_, Program>>) -> Result<Vec<Vec<String>>> { pub fn import_graph(progs: &HashMap<String, AstNode<Program>>) -> Result<Vec<Vec<String>>> {
let mut graph = Graph::new(); let mut graph = Graph::new();
for (name, program) in progs.iter() { for (name, program) in progs.iter() {
@ -101,7 +101,7 @@ fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>> {
Ok(order) Ok(order)
} }
pub(crate) fn import_dependencies(prog: NodeRef<'_, Program>) -> Result<Vec<String>> { pub(crate) fn import_dependencies(prog: NodeRef<Program>) -> Result<Vec<String>> {
let ret = Arc::new(Mutex::new(vec![])); let ret = Arc::new(Mutex::new(vec![]));
fn walk(ret: Arc<Mutex<Vec<String>>>, node: Node<'_>) { fn walk(ret: Arc<Mutex<Vec<String>>>, node: Node<'_>) {
@ -140,16 +140,16 @@ mod tests {
let mut modules = HashMap::new(); let mut modules = HashMap::new();
let a = kcl!(""); let a = kcl!("");
modules.insert("a.kcl".to_owned(), &a); modules.insert("a.kcl".to_owned(), a);
let b = kcl!( let b = kcl!(
" "
import \"a.kcl\" import \"a.kcl\"
" "
); );
modules.insert("b.kcl".to_owned(), &b); modules.insert("b.kcl".to_owned(), b);
let order = import_graph(modules).unwrap(); let order = import_graph(&modules).unwrap();
assert_eq!(vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned()]], order); assert_eq!(vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned()]], order);
} }
@ -162,16 +162,16 @@ import \"a.kcl\"
y = 2 y = 2
" "
); );
modules.insert("a.kcl".to_owned(), &a); modules.insert("a.kcl".to_owned(), a);
let b = kcl!( let b = kcl!(
" "
x = 1 x = 1
" "
); );
modules.insert("b.kcl".to_owned(), &b); modules.insert("b.kcl".to_owned(), b);
let order = import_graph(modules).unwrap(); let order = import_graph(&modules).unwrap();
assert_eq!(vec![vec!["a.kcl".to_owned(), "b.kcl".to_owned()]], order); assert_eq!(vec![vec!["a.kcl".to_owned(), "b.kcl".to_owned()]], order);
} }
@ -180,23 +180,23 @@ x = 1
let mut modules = HashMap::new(); let mut modules = HashMap::new();
let a = kcl!(""); let a = kcl!("");
modules.insert("a.kcl".to_owned(), &a); modules.insert("a.kcl".to_owned(), a);
let b = kcl!( let b = kcl!(
" "
import \"a.kcl\" import \"a.kcl\"
" "
); );
modules.insert("b.kcl".to_owned(), &b); modules.insert("b.kcl".to_owned(), b);
let c = kcl!( let c = kcl!(
" "
import \"a.kcl\" import \"a.kcl\"
" "
); );
modules.insert("c.kcl".to_owned(), &c); modules.insert("c.kcl".to_owned(), c);
let order = import_graph(modules).unwrap(); let order = import_graph(&modules).unwrap();
assert_eq!( assert_eq!(
vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned(), "c.kcl".to_owned()]], vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned(), "c.kcl".to_owned()]],
order order
@ -212,15 +212,15 @@ import \"a.kcl\"
import \"b.kcl\" import \"b.kcl\"
" "
); );
modules.insert("a.kcl".to_owned(), &a); modules.insert("a.kcl".to_owned(), a);
let b = kcl!( let b = kcl!(
" "
import \"a.kcl\" import \"a.kcl\"
" "
); );
modules.insert("b.kcl".to_owned(), &b); modules.insert("b.kcl".to_owned(), b);
import_graph(modules).unwrap_err(); import_graph(&modules).unwrap_err();
} }
} }