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