diff --git a/rust/kcl-lib/src/execution/mod.rs b/rust/kcl-lib/src/execution/mod.rs index dfac69ba5..71ed3d770 100644 --- a/rust/kcl-lib/src/execution/mod.rs +++ b/rust/kcl-lib/src/execution/mod.rs @@ -748,7 +748,7 @@ impl ExecutorContext { ) = tokio::sync::mpsc::channel(1); for module in modules { - let Some((module_id, module_path, program)) = universe.get(&module) else { + let Some((import_stmt, 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(), @@ -760,6 +760,7 @@ impl ExecutorContext { let exec_state = exec_state.clone(); let exec_ctxt = self.clone(); let results_tx = results_tx.clone(); + let source_range = SourceRange::from(import_stmt); #[cfg(target_arch = "wasm32")] { @@ -769,13 +770,7 @@ impl ExecutorContext { let exec_ctxt = exec_ctxt; let result = exec_ctxt - .exec_module_from_ast( - &program, - module_id, - &module_path, - &mut exec_state, - Default::default(), - ) + .exec_module_from_ast(&program, module_id, &module_path, &mut exec_state, source_range) .await; results_tx @@ -791,13 +786,7 @@ impl ExecutorContext { let exec_ctxt = exec_ctxt; let result = exec_ctxt - .exec_module_from_ast( - &program, - module_id, - &module_path, - &mut exec_state, - Default::default(), - ) + .exec_module_from_ast(&program, module_id, &module_path, &mut exec_state, source_range) .await; results_tx diff --git a/rust/kcl-lib/src/walk/import_graph.rs b/rust/kcl-lib/src/walk/import_graph.rs index ec90c6bb1..8a63b6ef8 100644 --- a/rust/kcl-lib/src/walk/import_graph.rs +++ b/rust/kcl-lib/src/walk/import_graph.rs @@ -8,19 +8,20 @@ use anyhow::Result; use crate::{ errors::KclErrorDetails, modules::{ModulePath, ModuleRepr}, - parsing::ast::types::{ImportPath, Node as AstNode, NodeRef, Program}, + parsing::ast::types::{ImportPath, ImportStatement, Node as AstNode, NodeRef, Program}, walk::{Node, Visitable}, ExecState, ExecutorContext, KclError, ModuleId, }; -/// Specific dependency between two modules. The 0th element of this tuple +/// Specific dependency between two modules. The 0th element of this info /// is the "importing" module, the 1st is the "imported" module. The 0th /// module *depends on* the 1st module. type Dependency = (String, String); type Graph = Vec; -type Universe = HashMap)>; +type DependencyInfo = (AstNode, ModuleId, ModulePath, AstNode); +type Universe = HashMap; /// Process a number of programs, returning the graph of dependencies. /// @@ -31,7 +32,7 @@ type Universe = HashMap)>; pub fn import_graph(progs: &Universe, ctx: &ExecutorContext) -> Result>, KclError> { let mut graph = Graph::new(); - for (name, (_, _, program)) in progs.iter() { + for (name, (_, _, _, program)) in progs.iter() { graph.extend( import_dependencies(program, ctx)? .into_iter() @@ -112,17 +113,15 @@ fn topsort(all_modules: &[&str], graph: Graph) -> Result>, KclEr Ok(order) } +type ImportDependencies = Vec<(String, AstNode, ModulePath)>; + pub(crate) fn import_dependencies( prog: NodeRef, ctx: &ExecutorContext, -) -> Result, KclError> { +) -> Result { let ret = Arc::new(Mutex::new(vec![])); - fn walk( - ret: Arc>>, - node: Node<'_>, - ctx: &ExecutorContext, - ) -> Result<(), KclError> { + fn walk(ret: Arc>, node: Node<'_>, ctx: &ExecutorContext) -> Result<(), KclError> { if let Node::ImportStatement(is) = node { // We only care about Kcl imports for now. if let ImportPath::Kcl { filename } = &is.path { @@ -137,7 +136,7 @@ pub(crate) fn import_dependencies( source_ranges: Default::default(), }) })? - .push((filename.to_string(), is.path.clone(), resolved_path)); + .push((filename.to_string(), is.clone(), resolved_path)); } } @@ -167,13 +166,13 @@ pub(crate) async fn import_universe( exec_state: &mut ExecState, ) -> Result<(), KclError> { let modules = import_dependencies(prog, ctx)?; - for (filename, import_path, module_path) in modules { + for (filename, import_stmt, module_path) in modules { if out.contains_key(&filename) { continue; } let module_id = ctx - .open_module(&import_path, &[], exec_state, Default::default()) + .open_module(&import_stmt.path, &[], exec_state, Default::default()) .await?; let program = { @@ -192,7 +191,10 @@ pub(crate) async fn import_universe( program.clone() }; - out.insert(filename.clone(), (module_id, module_path.clone(), program.clone())); + out.insert( + filename.clone(), + (import_stmt.clone(), module_id, module_path.clone(), program.clone()), + ); Box::pin(import_universe(ctx, &program, out, exec_state)).await?; } @@ -202,6 +204,7 @@ pub(crate) async fn import_universe( #[cfg(test)] mod tests { use super::*; + use crate::parsing::ast::types::ImportSelector; macro_rules! kcl { ( $kcl:expr ) => {{ @@ -209,8 +212,18 @@ mod tests { }}; } - fn into_module_tuple(program: AstNode) -> (ModuleId, ModulePath, AstNode) { - (ModuleId::default(), ModulePath::Local { value: "".into() }, program) + fn into_module_info(program: AstNode) -> DependencyInfo { + ( + AstNode::no_src(ImportStatement { + selector: ImportSelector::None { alias: None }, + path: ImportPath::Kcl { filename: "".into() }, + visibility: Default::default(), + digest: None, + }), + ModuleId::default(), + ModulePath::Local { value: "".into() }, + program, + ) } #[tokio::test] @@ -218,14 +231,14 @@ mod tests { let mut modules = HashMap::new(); let a = kcl!(""); - modules.insert("a.kcl".to_owned(), into_module_tuple(a)); + modules.insert("a.kcl".to_owned(), into_module_info(a)); let b = kcl!( " import \"a.kcl\" " ); - modules.insert("b.kcl".to_owned(), into_module_tuple(b)); + modules.insert("b.kcl".to_owned(), into_module_info(b)); let ctx = ExecutorContext::new_mock().await; let order = import_graph(&modules, &ctx).unwrap(); @@ -241,14 +254,14 @@ import \"a.kcl\" y = 2 " ); - modules.insert("a.kcl".to_owned(), into_module_tuple(a)); + modules.insert("a.kcl".to_owned(), into_module_info(a)); let b = kcl!( " x = 1 " ); - modules.insert("b.kcl".to_owned(), into_module_tuple(b)); + modules.insert("b.kcl".to_owned(), into_module_info(b)); let ctx = ExecutorContext::new_mock().await; let order = import_graph(&modules, &ctx).unwrap(); @@ -260,21 +273,21 @@ x = 1 let mut modules = HashMap::new(); let a = kcl!(""); - modules.insert("a.kcl".to_owned(), into_module_tuple(a)); + modules.insert("a.kcl".to_owned(), into_module_info(a)); let b = kcl!( " import \"a.kcl\" " ); - modules.insert("b.kcl".to_owned(), into_module_tuple(b)); + modules.insert("b.kcl".to_owned(), into_module_info(b)); let c = kcl!( " import \"a.kcl\" " ); - modules.insert("c.kcl".to_owned(), into_module_tuple(c)); + modules.insert("c.kcl".to_owned(), into_module_info(c)); let ctx = ExecutorContext::new_mock().await; let order = import_graph(&modules, &ctx).unwrap(); @@ -293,14 +306,14 @@ import \"a.kcl\" import \"b.kcl\" " ); - modules.insert("a.kcl".to_owned(), into_module_tuple(a)); + modules.insert("a.kcl".to_owned(), into_module_info(a)); let b = kcl!( " import \"a.kcl\" " ); - modules.insert("b.kcl".to_owned(), into_module_tuple(b)); + modules.insert("b.kcl".to_owned(), into_module_info(b)); let ctx = ExecutorContext::new_mock().await; import_graph(&modules, &ctx).unwrap_err();