Add KCL importing relative to where you're importing from (#7125)
* add test Signed-off-by: Jess Frazelle <github@jessfraz.com> * Add importing relative to where you're importing from * Update output * Remove runtime panics * Change to debug_assert --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -86,7 +86,7 @@ impl ExecutorContext {
|
|||||||
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
|
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
|
||||||
crate::log::log(format!("enter module {path} {}", exec_state.stack()));
|
crate::log::log(format!("enter module {path} {}", exec_state.stack()));
|
||||||
|
|
||||||
let mut local_state = ModuleState::new(path.std_path(), exec_state.stack().memory.clone(), Some(module_id));
|
let mut local_state = ModuleState::new(path.clone(), exec_state.stack().memory.clone(), Some(module_id));
|
||||||
if !preserve_mem {
|
if !preserve_mem {
|
||||||
std::mem::swap(&mut exec_state.mod_local, &mut local_state);
|
std::mem::swap(&mut exec_state.mod_local, &mut local_state);
|
||||||
}
|
}
|
||||||
@ -139,8 +139,13 @@ impl ExecutorContext {
|
|||||||
|
|
||||||
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_path = ModulePath::from_import_path(
|
||||||
|
&import_stmt.path,
|
||||||
|
&self.settings.project_directory,
|
||||||
|
&exec_state.mod_local.path,
|
||||||
|
)?;
|
||||||
let module_id = self
|
let module_id = self
|
||||||
.open_module(&import_stmt.path, attrs, exec_state, source_range)
|
.open_module(&import_stmt.path, attrs, &module_path, exec_state, source_range)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
match &import_stmt.selector {
|
match &import_stmt.selector {
|
||||||
@ -298,9 +303,9 @@ impl ExecutorContext {
|
|||||||
let impl_kind = annotations::get_impl(&ty.outer_attrs, metadata.source_range)?.unwrap_or_default();
|
let impl_kind = annotations::get_impl(&ty.outer_attrs, metadata.source_range)?.unwrap_or_default();
|
||||||
match impl_kind {
|
match impl_kind {
|
||||||
annotations::Impl::Rust => {
|
annotations::Impl::Rust => {
|
||||||
let std_path = match &exec_state.mod_local.std_path {
|
let std_path = match &exec_state.mod_local.path {
|
||||||
Some(p) => p,
|
ModulePath::Std { value } => value,
|
||||||
None => {
|
ModulePath::Local { .. } | ModulePath::Main => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails::new(
|
return Err(KclError::Semantic(KclErrorDetails::new(
|
||||||
"User-defined types are not yet supported.".to_owned(),
|
"User-defined types are not yet supported.".to_owned(),
|
||||||
vec![metadata.source_range],
|
vec![metadata.source_range],
|
||||||
@ -420,16 +425,15 @@ impl ExecutorContext {
|
|||||||
&self,
|
&self,
|
||||||
path: &ImportPath,
|
path: &ImportPath,
|
||||||
attrs: &[Node<Annotation>],
|
attrs: &[Node<Annotation>],
|
||||||
|
resolved_path: &ModulePath,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
) -> Result<ModuleId, KclError> {
|
) -> Result<ModuleId, KclError> {
|
||||||
let resolved_path = ModulePath::from_import_path(path, &self.settings.project_directory);
|
|
||||||
|
|
||||||
match path {
|
match path {
|
||||||
ImportPath::Kcl { .. } => {
|
ImportPath::Kcl { .. } => {
|
||||||
exec_state.global.mod_loader.cycle_check(&resolved_path, source_range)?;
|
exec_state.global.mod_loader.cycle_check(resolved_path, source_range)?;
|
||||||
|
|
||||||
if let Some(id) = exec_state.id_for_module(&resolved_path) {
|
if let Some(id) = exec_state.id_for_module(resolved_path) {
|
||||||
return Ok(id);
|
return Ok(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,12 +444,12 @@ impl ExecutorContext {
|
|||||||
exec_state.add_id_to_source(id, source.clone());
|
exec_state.add_id_to_source(id, source.clone());
|
||||||
// TODO handle parsing errors properly
|
// TODO handle parsing errors properly
|
||||||
let parsed = crate::parsing::parse_str(&source.source, id).parse_errs_as_err()?;
|
let parsed = crate::parsing::parse_str(&source.source, id).parse_errs_as_err()?;
|
||||||
exec_state.add_module(id, resolved_path, ModuleRepr::Kcl(parsed, None));
|
exec_state.add_module(id, resolved_path.clone(), ModuleRepr::Kcl(parsed, None));
|
||||||
|
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
ImportPath::Foreign { .. } => {
|
ImportPath::Foreign { .. } => {
|
||||||
if let Some(id) = exec_state.id_for_module(&resolved_path) {
|
if let Some(id) = exec_state.id_for_module(resolved_path) {
|
||||||
return Ok(id);
|
return Ok(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,11 +459,11 @@ impl ExecutorContext {
|
|||||||
exec_state.add_path_to_source_id(resolved_path.clone(), id);
|
exec_state.add_path_to_source_id(resolved_path.clone(), id);
|
||||||
let format = super::import::format_from_annotations(attrs, path, source_range)?;
|
let format = super::import::format_from_annotations(attrs, path, source_range)?;
|
||||||
let geom = super::import::import_foreign(path, format, exec_state, self, source_range).await?;
|
let geom = super::import::import_foreign(path, format, exec_state, self, source_range).await?;
|
||||||
exec_state.add_module(id, resolved_path, ModuleRepr::Foreign(geom, None));
|
exec_state.add_module(id, resolved_path.clone(), ModuleRepr::Foreign(geom, None));
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
ImportPath::Std { .. } => {
|
ImportPath::Std { .. } => {
|
||||||
if let Some(id) = exec_state.id_for_module(&resolved_path) {
|
if let Some(id) = exec_state.id_for_module(resolved_path) {
|
||||||
return Ok(id);
|
return Ok(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +475,7 @@ impl ExecutorContext {
|
|||||||
let parsed = crate::parsing::parse_str(&source.source, id)
|
let parsed = crate::parsing::parse_str(&source.source, id)
|
||||||
.parse_errs_as_err()
|
.parse_errs_as_err()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
exec_state.add_module(id, resolved_path, ModuleRepr::Kcl(parsed, None));
|
exec_state.add_module(id, resolved_path.clone(), ModuleRepr::Kcl(parsed, None));
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,7 +636,7 @@ impl ExecutorContext {
|
|||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if rust_impl {
|
if rust_impl {
|
||||||
if let Some(std_path) = &exec_state.mod_local.std_path {
|
if let ModulePath::Std { value: std_path } = &exec_state.mod_local.path {
|
||||||
let (func, props) = crate::std::std_fn(std_path, statement_kind.expect_name());
|
let (func, props) = crate::std::std_fn(std_path, statement_kind.expect_name());
|
||||||
KclValue::Function {
|
KclValue::Function {
|
||||||
value: FunctionSource::Std {
|
value: FunctionSource::Std {
|
||||||
|
@ -1044,6 +1044,7 @@ impl ExecutorContext {
|
|||||||
|
|
||||||
let root_imports = crate::walk::import_universe(
|
let root_imports = crate::walk::import_universe(
|
||||||
self,
|
self,
|
||||||
|
&ModulePath::Main,
|
||||||
&ModuleRepr::Kcl(program.ast.clone(), None),
|
&ModuleRepr::Kcl(program.ast.clone(), None),
|
||||||
&mut universe,
|
&mut universe,
|
||||||
exec_state,
|
exec_state,
|
||||||
@ -1211,15 +1212,10 @@ impl ExecutorContext {
|
|||||||
/// SAFETY: the current thread must have sole access to the memory referenced in exec_state.
|
/// SAFETY: the current thread must have sole access to the memory referenced in exec_state.
|
||||||
async fn eval_prelude(&self, exec_state: &mut ExecState, source_range: SourceRange) -> Result<(), KclError> {
|
async fn eval_prelude(&self, exec_state: &mut ExecState, source_range: SourceRange) -> Result<(), KclError> {
|
||||||
if exec_state.stack().memory.requires_std() {
|
if exec_state.stack().memory.requires_std() {
|
||||||
|
let path = vec!["std".to_owned(), "prelude".to_owned()];
|
||||||
|
let resolved_path = ModulePath::from_std_import_path(&path)?;
|
||||||
let id = self
|
let id = self
|
||||||
.open_module(
|
.open_module(&ImportPath::Std { path }, &[], &resolved_path, exec_state, source_range)
|
||||||
&ImportPath::Std {
|
|
||||||
path: vec!["std".to_owned(), "prelude".to_owned()],
|
|
||||||
},
|
|
||||||
&[],
|
|
||||||
exec_state,
|
|
||||||
source_range,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
let (module_memory, _) = self.exec_module_for_items(id, exec_state, source_range).await?;
|
let (module_memory, _) = self.exec_module_for_items(id, exec_state, source_range).await?;
|
||||||
|
|
||||||
|
@ -85,14 +85,14 @@ pub(super) struct ModuleState {
|
|||||||
/// Settings specified from annotations.
|
/// Settings specified from annotations.
|
||||||
pub settings: MetaSettings,
|
pub settings: MetaSettings,
|
||||||
pub(super) explicit_length_units: bool,
|
pub(super) explicit_length_units: bool,
|
||||||
pub(super) std_path: Option<String>,
|
pub(super) path: ModulePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExecState {
|
impl ExecState {
|
||||||
pub fn new(exec_context: &super::ExecutorContext) -> Self {
|
pub fn new(exec_context: &super::ExecutorContext) -> Self {
|
||||||
ExecState {
|
ExecState {
|
||||||
global: GlobalState::new(&exec_context.settings),
|
global: GlobalState::new(&exec_context.settings),
|
||||||
mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
|
mod_local: ModuleState::new(ModulePath::Main, ProgramMemory::new(), Default::default()),
|
||||||
exec_context: Some(exec_context.clone()),
|
exec_context: Some(exec_context.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ impl ExecState {
|
|||||||
|
|
||||||
*self = ExecState {
|
*self = ExecState {
|
||||||
global,
|
global,
|
||||||
mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
|
mod_local: ModuleState::new(self.mod_local.path.clone(), ProgramMemory::new(), Default::default()),
|
||||||
exec_context: Some(exec_context.clone()),
|
exec_context: Some(exec_context.clone()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -337,14 +337,14 @@ impl GlobalState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleState {
|
impl ModuleState {
|
||||||
pub(super) fn new(std_path: Option<String>, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
|
pub(super) fn new(path: ModulePath, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
|
||||||
ModuleState {
|
ModuleState {
|
||||||
id_generator: IdGenerator::new(module_id),
|
id_generator: IdGenerator::new(module_id),
|
||||||
stack: memory.new_stack(),
|
stack: memory.new_stack(),
|
||||||
pipe_value: Default::default(),
|
pipe_value: Default::default(),
|
||||||
module_exports: Default::default(),
|
module_exports: Default::default(),
|
||||||
explicit_length_units: false,
|
explicit_length_units: false,
|
||||||
std_path,
|
path,
|
||||||
settings: MetaSettings {
|
settings: MetaSettings {
|
||||||
default_length_units: Default::default(),
|
default_length_units: Default::default(),
|
||||||
default_angle_units: Default::default(),
|
default_angle_units: Default::default(),
|
||||||
|
@ -153,13 +153,6 @@ impl ModulePath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn std_path(&self) -> Option<String> {
|
|
||||||
match self {
|
|
||||||
ModulePath::Std { value: p } => Some(p.clone()),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn source(&self, fs: &FileManager, source_range: SourceRange) -> Result<ModuleSource, KclError> {
|
pub(crate) async fn source(&self, fs: &FileManager, source_range: SourceRange) -> Result<ModuleSource, KclError> {
|
||||||
match self {
|
match self {
|
||||||
ModulePath::Local { value: p } => Ok(ModuleSource {
|
ModulePath::Local { value: p } => Ok(ModuleSource {
|
||||||
@ -181,24 +174,52 @@ impl ModulePath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_import_path(path: &ImportPath, project_directory: &Option<TypedPath>) -> Self {
|
pub(crate) fn from_import_path(
|
||||||
|
path: &ImportPath,
|
||||||
|
project_directory: &Option<TypedPath>,
|
||||||
|
import_from: &ModulePath,
|
||||||
|
) -> Result<Self, KclError> {
|
||||||
match path {
|
match path {
|
||||||
ImportPath::Kcl { filename: path } | ImportPath::Foreign { path } => {
|
ImportPath::Kcl { filename: path } | ImportPath::Foreign { path } => {
|
||||||
let resolved_path = if let Some(project_dir) = project_directory {
|
let resolved_path = match import_from {
|
||||||
|
ModulePath::Main => {
|
||||||
|
if let Some(project_dir) = project_directory {
|
||||||
project_dir.join_typed(path)
|
project_dir.join_typed(path)
|
||||||
} else {
|
} else {
|
||||||
path.clone()
|
path.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModulePath::Local { value } => {
|
||||||
|
let import_from_dir = value.parent();
|
||||||
|
let base = import_from_dir.as_ref().or(project_directory.as_ref());
|
||||||
|
if let Some(dir) = base {
|
||||||
|
dir.join_typed(path)
|
||||||
|
} else {
|
||||||
|
path.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModulePath::Std { .. } => {
|
||||||
|
let message = format!("Cannot import a non-std KCL file from std: {path}.");
|
||||||
|
debug_assert!(false, "{}", &message);
|
||||||
|
return Err(KclError::Internal(KclErrorDetails::new(message, vec![])));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ModulePath::Local { value: resolved_path }
|
|
||||||
}
|
|
||||||
ImportPath::Std { path } => {
|
|
||||||
// For now we only support importing from singly-nested modules inside std.
|
|
||||||
assert_eq!(path.len(), 2);
|
|
||||||
assert_eq!(&path[0], "std");
|
|
||||||
|
|
||||||
ModulePath::Std { value: path[1].clone() }
|
Ok(ModulePath::Local { value: resolved_path })
|
||||||
|
}
|
||||||
|
ImportPath::Std { path } => Self::from_std_import_path(path),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_std_import_path(path: &[String]) -> Result<Self, KclError> {
|
||||||
|
// For now we only support importing from singly-nested modules inside std.
|
||||||
|
if path.len() != 2 || path[0] != "std" {
|
||||||
|
let message = format!("Invalid std import path: {path:?}.");
|
||||||
|
debug_assert!(false, "{}", &message);
|
||||||
|
return Err(KclError::Internal(KclErrorDetails::new(message, vec![])));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ModulePath::Std { value: path[1].clone() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3360,6 +3360,27 @@ mod nested_windows_main_kcl {
|
|||||||
super::execute(TEST_NAME, true).await
|
super::execute(TEST_NAME, true).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mod nested_assembly {
|
||||||
|
const TEST_NAME: &str = "nested_assembly";
|
||||||
|
|
||||||
|
/// Test parsing KCL.
|
||||||
|
#[test]
|
||||||
|
fn parse() {
|
||||||
|
super::parse(TEST_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that parsing and unparsing KCL produces the original KCL input.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn unparse() {
|
||||||
|
super::unparse(TEST_NAME).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test that KCL is executed correctly.
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn kcl_test_execute() {
|
||||||
|
super::execute(TEST_NAME, true).await
|
||||||
|
}
|
||||||
|
}
|
||||||
mod subtract_regression11 {
|
mod subtract_regression11 {
|
||||||
const TEST_NAME: &str = "subtract_regression11";
|
const TEST_NAME: &str = "subtract_regression11";
|
||||||
|
|
||||||
|
@ -34,9 +34,9 @@ pub(crate) type Universe = HashMap<String, DependencyInfo>;
|
|||||||
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, (_, _, _, repr)) in progs.iter() {
|
for (name, (_, _, path, repr)) in progs.iter() {
|
||||||
graph.extend(
|
graph.extend(
|
||||||
import_dependencies(repr, ctx)?
|
import_dependencies(path, repr, ctx)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(dependency, _, _)| (name.clone(), dependency))
|
.map(|(dependency, _, _)| (name.clone(), dependency))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
@ -120,17 +120,26 @@ fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>, KclEr
|
|||||||
|
|
||||||
type ImportDependencies = Vec<(String, AstNode<ImportStatement>, ModulePath)>;
|
type ImportDependencies = Vec<(String, AstNode<ImportStatement>, ModulePath)>;
|
||||||
|
|
||||||
pub(crate) fn import_dependencies(repr: &ModuleRepr, ctx: &ExecutorContext) -> Result<ImportDependencies, KclError> {
|
pub(crate) fn import_dependencies(
|
||||||
|
path: &ModulePath,
|
||||||
|
repr: &ModuleRepr,
|
||||||
|
ctx: &ExecutorContext,
|
||||||
|
) -> Result<ImportDependencies, KclError> {
|
||||||
let ModuleRepr::Kcl(prog, _) = repr else {
|
let ModuleRepr::Kcl(prog, _) = repr else {
|
||||||
// It has no dependencies, so return an empty list.
|
// It has no dependencies, so return an empty list.
|
||||||
return Ok(vec![]);
|
return Ok(vec![]);
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret = Arc::new(Mutex::new(vec![]));
|
let ret = Arc::new(Mutex::new(vec![]));
|
||||||
fn walk(ret: Arc<Mutex<ImportDependencies>>, node: Node<'_>, ctx: &ExecutorContext) -> Result<(), KclError> {
|
fn walk(
|
||||||
|
ret: Arc<Mutex<ImportDependencies>>,
|
||||||
|
node: Node<'_>,
|
||||||
|
import_from: &ModulePath,
|
||||||
|
ctx: &ExecutorContext,
|
||||||
|
) -> Result<(), KclError> {
|
||||||
if let Node::ImportStatement(is) = node {
|
if let Node::ImportStatement(is) = node {
|
||||||
// We only care about Kcl and Foreign imports for now.
|
// We only care about Kcl and Foreign imports for now.
|
||||||
let resolved_path = ModulePath::from_import_path(&is.path, &ctx.settings.project_directory);
|
let resolved_path = ModulePath::from_import_path(&is.path, &ctx.settings.project_directory, import_from)?;
|
||||||
match &is.path {
|
match &is.path {
|
||||||
ImportPath::Kcl { filename } => {
|
ImportPath::Kcl { filename } => {
|
||||||
// We need to lock the mutex to push the dependency.
|
// We need to lock the mutex to push the dependency.
|
||||||
@ -160,13 +169,13 @@ pub(crate) fn import_dependencies(repr: &ModuleRepr, ctx: &ExecutorContext) -> R
|
|||||||
}
|
}
|
||||||
|
|
||||||
for child in node.children().iter() {
|
for child in node.children().iter() {
|
||||||
walk(ret.clone(), *child, ctx)?;
|
walk(ret.clone(), *child, import_from, ctx)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
walk(ret.clone(), prog.into(), ctx)?;
|
walk(ret.clone(), prog.into(), path, ctx)?;
|
||||||
|
|
||||||
let ret = ret.lock().map_err(|err| {
|
let ret = ret.lock().map_err(|err| {
|
||||||
KclError::Internal(KclErrorDetails::new(
|
KclError::Internal(KclErrorDetails::new(
|
||||||
@ -182,11 +191,12 @@ pub(crate) fn import_dependencies(repr: &ModuleRepr, ctx: &ExecutorContext) -> R
|
|||||||
/// only `repr`'s non-transitive imports.
|
/// only `repr`'s non-transitive imports.
|
||||||
pub(crate) async fn import_universe(
|
pub(crate) async fn import_universe(
|
||||||
ctx: &ExecutorContext,
|
ctx: &ExecutorContext,
|
||||||
|
path: &ModulePath,
|
||||||
repr: &ModuleRepr,
|
repr: &ModuleRepr,
|
||||||
out: &mut Universe,
|
out: &mut Universe,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
) -> Result<UniverseMap, KclError> {
|
) -> Result<UniverseMap, KclError> {
|
||||||
let modules = import_dependencies(repr, ctx)?;
|
let modules = import_dependencies(path, repr, ctx)?;
|
||||||
let mut module_imports = HashMap::new();
|
let mut module_imports = HashMap::new();
|
||||||
for (filename, import_stmt, module_path) in modules {
|
for (filename, import_stmt, module_path) in modules {
|
||||||
match &module_path {
|
match &module_path {
|
||||||
@ -208,7 +218,7 @@ pub(crate) async fn import_universe(
|
|||||||
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 = ctx
|
let module_id = ctx
|
||||||
.open_module(&import_stmt.path, attrs, exec_state, source_range)
|
.open_module(&import_stmt.path, attrs, &module_path, exec_state, source_range)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let repr = {
|
let repr = {
|
||||||
@ -221,8 +231,8 @@ pub(crate) async fn import_universe(
|
|||||||
module_info.repr.clone()
|
module_info.repr.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
out.insert(filename, (import_stmt, module_id, module_path, repr.clone()));
|
out.insert(filename, (import_stmt, module_id, module_path.clone(), repr.clone()));
|
||||||
Box::pin(import_universe(ctx, &repr, out, exec_state)).await?;
|
Box::pin(import_universe(ctx, &module_path, &repr, out, exec_state)).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(module_imports)
|
Ok(module_imports)
|
||||||
|
184
rust/kcl-lib/tests/nested_assembly/artifact_commands.snap
Normal file
184
rust/kcl-lib/tests/nested_assembly/artifact_commands.snap
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Artifact commands nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "edge_lines_visible",
|
||||||
|
"hidden": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_visible",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_visible",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "make_plane",
|
||||||
|
"origin": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"x_axis": {
|
||||||
|
"x": 1.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"y_axis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 1.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"size": 60.0,
|
||||||
|
"clobber": false,
|
||||||
|
"hide": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "close_path",
|
||||||
|
"path_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "enable_sketch_mode",
|
||||||
|
"entity_id": "[uuid]",
|
||||||
|
"ortho": false,
|
||||||
|
"animated": false,
|
||||||
|
"adjust_camera": false,
|
||||||
|
"planar_normal": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "extend_path",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"segment": {
|
||||||
|
"type": "arc",
|
||||||
|
"center": {
|
||||||
|
"x": 15.0,
|
||||||
|
"y": 0.0
|
||||||
|
},
|
||||||
|
"radius": 5.0,
|
||||||
|
"start": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 0.0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 360.0
|
||||||
|
},
|
||||||
|
"relative": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "move_path_pen",
|
||||||
|
"path": "[uuid]",
|
||||||
|
"to": {
|
||||||
|
"x": 20.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "sketch_mode_disable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "start_path"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "object_bring_to_front",
|
||||||
|
"object_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "revolve",
|
||||||
|
"target": "[uuid]",
|
||||||
|
"origin": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 0.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"axis": {
|
||||||
|
"x": 0.0,
|
||||||
|
"y": 1.0,
|
||||||
|
"z": 0.0
|
||||||
|
},
|
||||||
|
"axis_is_2d": true,
|
||||||
|
"angle": {
|
||||||
|
"unit": "degrees",
|
||||||
|
"value": 360.0
|
||||||
|
},
|
||||||
|
"tolerance": 0.0000001,
|
||||||
|
"opposite": "None"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_adjacency_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "solid3d_get_extrusion_face_info",
|
||||||
|
"object_id": "[uuid]",
|
||||||
|
"edge_id": "[uuid]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Artifact graph flowchart nested_assembly.kcl
|
||||||
|
extension: md
|
||||||
|
snapshot_kind: binary
|
||||||
|
---
|
@ -0,0 +1,23 @@
|
|||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
subgraph path2 [Path]
|
||||||
|
2["Path<br>[43, 81, 2]"]
|
||||||
|
3["Segment<br>[43, 81, 2]"]
|
||||||
|
4[Solid2d]
|
||||||
|
end
|
||||||
|
1["Plane<br>[18, 35, 2]"]
|
||||||
|
5["Sweep Revolve<br>[89, 142, 2]"]
|
||||||
|
6[Wall]
|
||||||
|
%% face_code_ref=Missing NodePath
|
||||||
|
7["SweepEdge Adjacent"]
|
||||||
|
1 --- 2
|
||||||
|
2 --- 3
|
||||||
|
2 --- 4
|
||||||
|
2 ---- 5
|
||||||
|
5 <--x 3
|
||||||
|
3 --- 6
|
||||||
|
3 --- 7
|
||||||
|
5 --- 6
|
||||||
|
5 --- 7
|
||||||
|
6 --- 7
|
||||||
|
```
|
73
rust/kcl-lib/tests/nested_assembly/ast.snap
Normal file
73
rust/kcl-lib/tests/nested_assembly/ast.snap
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of parsing nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"Ok": {
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"path": {
|
||||||
|
"type": "Kcl",
|
||||||
|
"filename": "nested/foo/bar/main.kcl"
|
||||||
|
},
|
||||||
|
"selector": {
|
||||||
|
"type": "None",
|
||||||
|
"alias": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "bar",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "ImportStatement",
|
||||||
|
"type": "ImportStatement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"expression": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "bar",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"start": 0,
|
||||||
|
"type": "ExpressionStatement",
|
||||||
|
"type": "ExpressionStatement"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {
|
||||||
|
"0": [
|
||||||
|
{
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "NonCodeNode",
|
||||||
|
"value": {
|
||||||
|
"type": "newLine"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"startNodes": []
|
||||||
|
},
|
||||||
|
"start": 0
|
||||||
|
}
|
||||||
|
}
|
3
rust/kcl-lib/tests/nested_assembly/input.kcl
Normal file
3
rust/kcl-lib/tests/nested_assembly/input.kcl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import "nested/foo/bar/main.kcl" as bar
|
||||||
|
|
||||||
|
bar
|
@ -0,0 +1,7 @@
|
|||||||
|
// A donut shape.
|
||||||
|
startSketchOn(XY)
|
||||||
|
|> circle( center = [15, 0], radius = 5 )
|
||||||
|
|> revolve(
|
||||||
|
angle = 360,
|
||||||
|
axis = Y,
|
||||||
|
)
|
@ -0,0 +1,3 @@
|
|||||||
|
import "imported.kcl" as imported
|
||||||
|
|
||||||
|
imported
|
18
rust/kcl-lib/tests/nested_assembly/ops.snap
Normal file
18
rust/kcl-lib/tests/nested_assembly/ops.snap
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Operations executed nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "GroupBegin",
|
||||||
|
"group": {
|
||||||
|
"type": "ModuleInstance",
|
||||||
|
"name": "main.kcl",
|
||||||
|
"moduleId": 0
|
||||||
|
},
|
||||||
|
"sourceRange": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GroupEnd"
|
||||||
|
}
|
||||||
|
]
|
10
rust/kcl-lib/tests/nested_assembly/program_memory.snap
Normal file
10
rust/kcl-lib/tests/nested_assembly/program_memory.snap
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Variables in memory after executing nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"bar": {
|
||||||
|
"type": "Module",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
}
|
BIN
rust/kcl-lib/tests/nested_assembly/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/nested_assembly/rendered_model.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
7
rust/kcl-lib/tests/nested_assembly/unparsed.snap
Normal file
7
rust/kcl-lib/tests/nested_assembly/unparsed.snap
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing nested_main_kcl.kcl
|
||||||
|
---
|
||||||
|
import "nested/foo/bar/main.kcl" as bar
|
||||||
|
|
||||||
|
bar
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing tests/nested_assembly/nested/foo/bar/imported.kcl
|
||||||
|
---
|
||||||
|
// A donut shape.
|
||||||
|
startSketchOn(XY)
|
||||||
|
|> circle(center = [15, 0], radius = 5)
|
||||||
|
|> revolve(angle = 360, axis = Y)
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
source: kcl-lib/src/simulation_tests.rs
|
||||||
|
description: Result of unparsing tests/nested_assembly/nested/foo/bar/main.kcl
|
||||||
|
---
|
||||||
|
import "imported.kcl" as imported
|
||||||
|
|
||||||
|
imported
|
Reference in New Issue
Block a user