Compare commits
1 Commits
v1.0.0
...
franknoiro
Author | SHA1 | Date | |
---|---|---|---|
cac7aa2bee |
@ -70,28 +70,22 @@ test.describe('Point-and-click assemblies tests', () => {
|
||||
await test.step('Setup parts and expect empty assembly scene', async () => {
|
||||
const projectName = 'assembly'
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const projDir = path.join(dir, projectName)
|
||||
const nestedProjDir = path.join(dir, projectName, 'nested', 'twice')
|
||||
await fsp.mkdir(projDir, { recursive: true })
|
||||
await fsp.mkdir(nestedProjDir, { recursive: true })
|
||||
const bracketDir = path.join(dir, projectName)
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
await Promise.all([
|
||||
fsp.copyFile(
|
||||
executorInputPath('cylinder.kcl'),
|
||||
path.join(projDir, 'cylinder.kcl')
|
||||
),
|
||||
fsp.copyFile(
|
||||
executorInputPath('cylinder.kcl'),
|
||||
path.join(nestedProjDir, 'main.kcl')
|
||||
path.join(bracketDir, 'cylinder.kcl')
|
||||
),
|
||||
fsp.copyFile(
|
||||
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
||||
path.join(projDir, 'bracket.kcl')
|
||||
path.join(bracketDir, 'bracket.kcl')
|
||||
),
|
||||
fsp.copyFile(
|
||||
testsInputPath('cube.step'),
|
||||
path.join(projDir, 'cube.step')
|
||||
path.join(bracketDir, 'cube.step')
|
||||
),
|
||||
fsp.writeFile(path.join(projDir, 'main.kcl'), ''),
|
||||
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
|
||||
])
|
||||
})
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
@ -173,25 +167,6 @@ test.describe('Point-and-click assemblies tests', () => {
|
||||
await expect(
|
||||
page.getByText('This file is already imported')
|
||||
).toBeVisible()
|
||||
await cmdBar.closeCmdBar()
|
||||
})
|
||||
|
||||
await test.step('Insert a nested kcl part', async () => {
|
||||
await insertPartIntoAssembly(
|
||||
'nested/twice/main.kcl',
|
||||
'main',
|
||||
toolbar,
|
||||
cmdBar,
|
||||
page
|
||||
)
|
||||
await toolbar.openPane('code')
|
||||
await page.waitForTimeout(10000)
|
||||
await editor.expectEditor.toContain(
|
||||
`
|
||||
import "nested/twice/main.kcl" as main
|
||||
`,
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 82 KiB |
@ -86,7 +86,7 @@ impl ExecutorContext {
|
||||
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
|
||||
crate::log::log(format!("enter module {path} {}", exec_state.stack()));
|
||||
|
||||
let mut local_state = ModuleState::new(path.clone(), exec_state.stack().memory.clone(), Some(module_id));
|
||||
let mut local_state = ModuleState::new(path.std_path(), exec_state.stack().memory.clone(), Some(module_id));
|
||||
if !preserve_mem {
|
||||
std::mem::swap(&mut exec_state.mod_local, &mut local_state);
|
||||
}
|
||||
@ -139,13 +139,8 @@ impl ExecutorContext {
|
||||
|
||||
let source_range = SourceRange::from(import_stmt);
|
||||
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
|
||||
.open_module(&import_stmt.path, attrs, &module_path, exec_state, source_range)
|
||||
.open_module(&import_stmt.path, attrs, exec_state, source_range)
|
||||
.await?;
|
||||
|
||||
match &import_stmt.selector {
|
||||
@ -303,9 +298,9 @@ impl ExecutorContext {
|
||||
let impl_kind = annotations::get_impl(&ty.outer_attrs, metadata.source_range)?.unwrap_or_default();
|
||||
match impl_kind {
|
||||
annotations::Impl::Rust => {
|
||||
let std_path = match &exec_state.mod_local.path {
|
||||
ModulePath::Std { value } => value,
|
||||
ModulePath::Local { .. } | ModulePath::Main => {
|
||||
let std_path = match &exec_state.mod_local.std_path {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
return Err(KclError::Semantic(KclErrorDetails::new(
|
||||
"User-defined types are not yet supported.".to_owned(),
|
||||
vec![metadata.source_range],
|
||||
@ -425,15 +420,16 @@ impl ExecutorContext {
|
||||
&self,
|
||||
path: &ImportPath,
|
||||
attrs: &[Node<Annotation>],
|
||||
resolved_path: &ModulePath,
|
||||
exec_state: &mut ExecState,
|
||||
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)?;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -444,12 +440,12 @@ impl ExecutorContext {
|
||||
exec_state.add_id_to_source(id, source.clone());
|
||||
// TODO handle parsing errors properly
|
||||
let parsed = crate::parsing::parse_str(&source.source, id).parse_errs_as_err()?;
|
||||
exec_state.add_module(id, resolved_path.clone(), ModuleRepr::Kcl(parsed, None));
|
||||
exec_state.add_module(id, resolved_path, ModuleRepr::Kcl(parsed, None));
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@ -459,11 +455,11 @@ impl ExecutorContext {
|
||||
exec_state.add_path_to_source_id(resolved_path.clone(), id);
|
||||
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?;
|
||||
exec_state.add_module(id, resolved_path.clone(), ModuleRepr::Foreign(geom, None));
|
||||
exec_state.add_module(id, resolved_path, ModuleRepr::Foreign(geom, None));
|
||||
Ok(id)
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@ -475,7 +471,7 @@ impl ExecutorContext {
|
||||
let parsed = crate::parsing::parse_str(&source.source, id)
|
||||
.parse_errs_as_err()
|
||||
.unwrap();
|
||||
exec_state.add_module(id, resolved_path.clone(), ModuleRepr::Kcl(parsed, None));
|
||||
exec_state.add_module(id, resolved_path, ModuleRepr::Kcl(parsed, None));
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
@ -636,7 +632,7 @@ impl ExecutorContext {
|
||||
.unwrap_or(false);
|
||||
|
||||
if rust_impl {
|
||||
if let ModulePath::Std { value: std_path } = &exec_state.mod_local.path {
|
||||
if let Some(std_path) = &exec_state.mod_local.std_path {
|
||||
let (func, props) = crate::std::std_fn(std_path, statement_kind.expect_name());
|
||||
KclValue::Function {
|
||||
value: FunctionSource::Std {
|
||||
@ -759,7 +755,7 @@ fn apply_ascription(
|
||||
};
|
||||
KclError::Semantic(KclErrorDetails::new(
|
||||
format!(
|
||||
"could not coerce value of type {} to type {ty}{suggestion}",
|
||||
"could not coerce {} value to type {ty}{suggestion}",
|
||||
value.human_friendly_type()
|
||||
),
|
||||
vec![source_range],
|
||||
@ -1652,7 +1648,7 @@ a = 42: string
|
||||
let err = result.unwrap_err();
|
||||
assert!(
|
||||
err.to_string()
|
||||
.contains("could not coerce value of type number(default units) to type string"),
|
||||
.contains("could not coerce number(default units) value to type string"),
|
||||
"Expected error but found {err:?}"
|
||||
);
|
||||
|
||||
@ -1663,7 +1659,7 @@ a = 42: Plane
|
||||
let err = result.unwrap_err();
|
||||
assert!(
|
||||
err.to_string()
|
||||
.contains("could not coerce value of type number(default units) to type Plane"),
|
||||
.contains("could not coerce number(default units) value to type Plane"),
|
||||
"Expected error but found {err:?}"
|
||||
);
|
||||
|
||||
@ -1673,9 +1669,8 @@ arr = [0]: [string]
|
||||
let result = parse_execute(program).await;
|
||||
let err = result.unwrap_err();
|
||||
assert!(
|
||||
err.to_string().contains(
|
||||
"could not coerce value of type array of number(default units) with 1 value to type [string]"
|
||||
),
|
||||
err.to_string()
|
||||
.contains("could not coerce [any; 1] value to type [string]"),
|
||||
"Expected error but found {err:?}"
|
||||
);
|
||||
|
||||
@ -1686,7 +1681,7 @@ mixedArr = [0, "a"]: [number(mm)]
|
||||
let err = result.unwrap_err();
|
||||
assert!(
|
||||
err.to_string()
|
||||
.contains("could not coerce value of type array of number(default units), string with 2 values to type [number(mm)]"),
|
||||
.contains("could not coerce [any; 2] value to type [number(mm)]"),
|
||||
"Expected error but found {err:?}"
|
||||
);
|
||||
}
|
||||
|
@ -281,34 +281,8 @@ impl KclValue {
|
||||
/// Human readable type name used in error messages. Should not be relied
|
||||
/// on for program logic.
|
||||
pub(crate) fn human_friendly_type(&self) -> String {
|
||||
self.inner_human_friendly_type(1)
|
||||
}
|
||||
|
||||
fn inner_human_friendly_type(&self, max_depth: usize) -> String {
|
||||
if let Some(pt) = self.principal_type() {
|
||||
if max_depth > 0 {
|
||||
// The principal type of an array uses the array's element type,
|
||||
// which is oftentimes `any`, and that's not a helpful message. So
|
||||
// we show the actual elements.
|
||||
if let Some(elements) = self.as_array() {
|
||||
// If it's empty, we want to show the type of the array.
|
||||
if !elements.is_empty() {
|
||||
// A max of 3 is good because it's common to use 3D points.
|
||||
let max = 3;
|
||||
let len = elements.len();
|
||||
let ellipsis = if len > max { ", ..." } else { "" };
|
||||
let element_label = if len == 1 { "value" } else { "values" };
|
||||
let element_tys = elements
|
||||
.iter()
|
||||
.take(max)
|
||||
.map(|elem| elem.inner_human_friendly_type(max_depth - 1))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
return format!("array of {element_tys}{ellipsis} with {len} {element_label}");
|
||||
}
|
||||
}
|
||||
}
|
||||
return pt.to_string();
|
||||
if let Some(t) = self.principal_type() {
|
||||
return t.to_string();
|
||||
}
|
||||
match self {
|
||||
KclValue::Uuid { .. } => "Unique ID (uuid)",
|
||||
@ -670,88 +644,3 @@ impl From<GeometryWithImportedGeometry> for KclValue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_human_friendly_type() {
|
||||
let len = KclValue::Number {
|
||||
value: 1.0,
|
||||
ty: NumericType::Known(UnitType::Length(UnitLen::Unknown)),
|
||||
meta: vec![],
|
||||
};
|
||||
assert_eq!(len.human_friendly_type(), "number(Length)".to_string());
|
||||
|
||||
let unknown = KclValue::Number {
|
||||
value: 1.0,
|
||||
ty: NumericType::Unknown,
|
||||
meta: vec![],
|
||||
};
|
||||
assert_eq!(unknown.human_friendly_type(), "number(unknown units)".to_string());
|
||||
|
||||
let mm = KclValue::Number {
|
||||
value: 1.0,
|
||||
ty: NumericType::Known(UnitType::Length(UnitLen::Mm)),
|
||||
meta: vec![],
|
||||
};
|
||||
assert_eq!(mm.human_friendly_type(), "number(mm)".to_string());
|
||||
|
||||
let array1_mm = KclValue::HomArray {
|
||||
value: vec![mm.clone()],
|
||||
ty: RuntimeType::any(),
|
||||
};
|
||||
assert_eq!(
|
||||
array1_mm.human_friendly_type(),
|
||||
"array of number(mm) with 1 value".to_string()
|
||||
);
|
||||
|
||||
let array2_mm = KclValue::HomArray {
|
||||
value: vec![mm.clone(), mm.clone()],
|
||||
ty: RuntimeType::any(),
|
||||
};
|
||||
assert_eq!(
|
||||
array2_mm.human_friendly_type(),
|
||||
"array of number(mm), number(mm) with 2 values".to_string()
|
||||
);
|
||||
|
||||
let array3_mm = KclValue::HomArray {
|
||||
value: vec![mm.clone(), mm.clone(), mm.clone()],
|
||||
ty: RuntimeType::any(),
|
||||
};
|
||||
assert_eq!(
|
||||
array3_mm.human_friendly_type(),
|
||||
"array of number(mm), number(mm), number(mm) with 3 values".to_string()
|
||||
);
|
||||
|
||||
let inches = KclValue::Number {
|
||||
value: 1.0,
|
||||
ty: NumericType::Known(UnitType::Length(UnitLen::Inches)),
|
||||
meta: vec![],
|
||||
};
|
||||
let array4 = KclValue::HomArray {
|
||||
value: vec![mm.clone(), mm.clone(), inches.clone(), mm.clone()],
|
||||
ty: RuntimeType::any(),
|
||||
};
|
||||
assert_eq!(
|
||||
array4.human_friendly_type(),
|
||||
"array of number(mm), number(mm), number(in), ... with 4 values".to_string()
|
||||
);
|
||||
|
||||
let empty_array = KclValue::HomArray {
|
||||
value: vec![],
|
||||
ty: RuntimeType::any(),
|
||||
};
|
||||
assert_eq!(empty_array.human_friendly_type(), "[any; 0]".to_string());
|
||||
|
||||
let array_nested = KclValue::HomArray {
|
||||
value: vec![array2_mm.clone()],
|
||||
ty: RuntimeType::any(),
|
||||
};
|
||||
assert_eq!(
|
||||
array_nested.human_friendly_type(),
|
||||
"array of [any; 2] with 1 value".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1044,7 +1044,6 @@ impl ExecutorContext {
|
||||
|
||||
let root_imports = crate::walk::import_universe(
|
||||
self,
|
||||
&ModulePath::Main,
|
||||
&ModuleRepr::Kcl(program.ast.clone(), None),
|
||||
&mut universe,
|
||||
exec_state,
|
||||
@ -1212,10 +1211,15 @@ impl ExecutorContext {
|
||||
/// 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> {
|
||||
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
|
||||
.open_module(&ImportPath::Std { path }, &[], &resolved_path, exec_state, source_range)
|
||||
.open_module(
|
||||
&ImportPath::Std {
|
||||
path: vec!["std".to_owned(), "prelude".to_owned()],
|
||||
},
|
||||
&[],
|
||||
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.
|
||||
pub settings: MetaSettings,
|
||||
pub(super) explicit_length_units: bool,
|
||||
pub(super) path: ModulePath,
|
||||
pub(super) std_path: Option<String>,
|
||||
}
|
||||
|
||||
impl ExecState {
|
||||
pub fn new(exec_context: &super::ExecutorContext) -> Self {
|
||||
ExecState {
|
||||
global: GlobalState::new(&exec_context.settings),
|
||||
mod_local: ModuleState::new(ModulePath::Main, ProgramMemory::new(), Default::default()),
|
||||
mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
|
||||
exec_context: Some(exec_context.clone()),
|
||||
}
|
||||
}
|
||||
@ -102,7 +102,7 @@ impl ExecState {
|
||||
|
||||
*self = ExecState {
|
||||
global,
|
||||
mod_local: ModuleState::new(self.mod_local.path.clone(), ProgramMemory::new(), Default::default()),
|
||||
mod_local: ModuleState::new(None, ProgramMemory::new(), Default::default()),
|
||||
exec_context: Some(exec_context.clone()),
|
||||
};
|
||||
}
|
||||
@ -337,14 +337,14 @@ impl GlobalState {
|
||||
}
|
||||
|
||||
impl ModuleState {
|
||||
pub(super) fn new(path: ModulePath, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
|
||||
pub(super) fn new(std_path: Option<String>, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
|
||||
ModuleState {
|
||||
id_generator: IdGenerator::new(module_id),
|
||||
stack: memory.new_stack(),
|
||||
pipe_value: Default::default(),
|
||||
module_exports: Default::default(),
|
||||
explicit_length_units: false,
|
||||
path,
|
||||
std_path,
|
||||
settings: MetaSettings {
|
||||
default_length_units: Default::default(),
|
||||
default_angle_units: Default::default(),
|
||||
|
@ -153,6 +153,13 @@ 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> {
|
||||
match self {
|
||||
ModulePath::Local { value: p } => Ok(ModuleSource {
|
||||
@ -174,52 +181,24 @@ impl ModulePath {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_import_path(
|
||||
path: &ImportPath,
|
||||
project_directory: &Option<TypedPath>,
|
||||
import_from: &ModulePath,
|
||||
) -> Result<Self, KclError> {
|
||||
pub(crate) fn from_import_path(path: &ImportPath, project_directory: &Option<TypedPath>) -> Self {
|
||||
match path {
|
||||
ImportPath::Kcl { filename: path } | ImportPath::Foreign { path } => {
|
||||
let resolved_path = match import_from {
|
||||
ModulePath::Main => {
|
||||
if let Some(project_dir) = project_directory {
|
||||
project_dir.join_typed(path)
|
||||
} else {
|
||||
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![])));
|
||||
}
|
||||
let resolved_path = if let Some(project_dir) = project_directory {
|
||||
project_dir.join_typed(path)
|
||||
} else {
|
||||
path.clone()
|
||||
};
|
||||
|
||||
Ok(ModulePath::Local { value: resolved_path })
|
||||
ModulePath::Local { value: resolved_path }
|
||||
}
|
||||
ImportPath::Std { path } => Self::from_std_import_path(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");
|
||||
|
||||
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![])));
|
||||
ModulePath::Std { value: path[1].clone() }
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ModulePath::Std { value: path[1].clone() })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,27 +384,6 @@ mod any_type {
|
||||
super::execute(TEST_NAME, false).await
|
||||
}
|
||||
}
|
||||
mod error_with_point_shows_numeric_units {
|
||||
const TEST_NAME: &str = "error_with_point_shows_numeric_units";
|
||||
|
||||
/// 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 artifact_graph_example_code1 {
|
||||
const TEST_NAME: &str = "artifact_graph_example_code1";
|
||||
|
||||
@ -3381,27 +3360,6 @@ mod nested_windows_main_kcl {
|
||||
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 {
|
||||
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> {
|
||||
let mut graph = Graph::new();
|
||||
|
||||
for (name, (_, _, path, repr)) in progs.iter() {
|
||||
for (name, (_, _, _, repr)) in progs.iter() {
|
||||
graph.extend(
|
||||
import_dependencies(path, repr, ctx)?
|
||||
import_dependencies(repr, ctx)?
|
||||
.into_iter()
|
||||
.map(|(dependency, _, _)| (name.clone(), dependency))
|
||||
.collect::<Vec<_>>(),
|
||||
@ -120,26 +120,17 @@ fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>, KclEr
|
||||
|
||||
type ImportDependencies = Vec<(String, AstNode<ImportStatement>, ModulePath)>;
|
||||
|
||||
pub(crate) fn import_dependencies(
|
||||
path: &ModulePath,
|
||||
repr: &ModuleRepr,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<ImportDependencies, KclError> {
|
||||
pub(crate) fn import_dependencies(repr: &ModuleRepr, ctx: &ExecutorContext) -> Result<ImportDependencies, KclError> {
|
||||
let ModuleRepr::Kcl(prog, _) = repr else {
|
||||
// It has no dependencies, so return an empty list.
|
||||
return Ok(vec![]);
|
||||
};
|
||||
|
||||
let ret = Arc::new(Mutex::new(vec![]));
|
||||
fn walk(
|
||||
ret: Arc<Mutex<ImportDependencies>>,
|
||||
node: Node<'_>,
|
||||
import_from: &ModulePath,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<(), KclError> {
|
||||
fn walk(ret: Arc<Mutex<ImportDependencies>>, node: Node<'_>, ctx: &ExecutorContext) -> Result<(), KclError> {
|
||||
if let Node::ImportStatement(is) = node {
|
||||
// We only care about Kcl and Foreign imports for now.
|
||||
let resolved_path = ModulePath::from_import_path(&is.path, &ctx.settings.project_directory, import_from)?;
|
||||
let resolved_path = ModulePath::from_import_path(&is.path, &ctx.settings.project_directory);
|
||||
match &is.path {
|
||||
ImportPath::Kcl { filename } => {
|
||||
// We need to lock the mutex to push the dependency.
|
||||
@ -169,13 +160,13 @@ pub(crate) fn import_dependencies(
|
||||
}
|
||||
|
||||
for child in node.children().iter() {
|
||||
walk(ret.clone(), *child, import_from, ctx)?;
|
||||
walk(ret.clone(), *child, ctx)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
walk(ret.clone(), prog.into(), path, ctx)?;
|
||||
walk(ret.clone(), prog.into(), ctx)?;
|
||||
|
||||
let ret = ret.lock().map_err(|err| {
|
||||
KclError::Internal(KclErrorDetails::new(
|
||||
@ -191,12 +182,11 @@ pub(crate) fn import_dependencies(
|
||||
/// only `repr`'s non-transitive imports.
|
||||
pub(crate) async fn import_universe(
|
||||
ctx: &ExecutorContext,
|
||||
path: &ModulePath,
|
||||
repr: &ModuleRepr,
|
||||
out: &mut Universe,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<UniverseMap, KclError> {
|
||||
let modules = import_dependencies(path, repr, ctx)?;
|
||||
let modules = import_dependencies(repr, ctx)?;
|
||||
let mut module_imports = HashMap::new();
|
||||
for (filename, import_stmt, module_path) in modules {
|
||||
match &module_path {
|
||||
@ -218,7 +208,7 @@ pub(crate) async fn import_universe(
|
||||
let source_range = SourceRange::from(&import_stmt);
|
||||
let attrs = &import_stmt.outer_attrs;
|
||||
let module_id = ctx
|
||||
.open_module(&import_stmt.path, attrs, &module_path, exec_state, source_range)
|
||||
.open_module(&import_stmt.path, attrs, exec_state, source_range)
|
||||
.await?;
|
||||
|
||||
let repr = {
|
||||
@ -231,8 +221,8 @@ pub(crate) async fn import_universe(
|
||||
module_info.repr.clone()
|
||||
};
|
||||
|
||||
out.insert(filename, (import_stmt, module_id, module_path.clone(), repr.clone()));
|
||||
Box::pin(import_universe(ctx, &module_path, &repr, out, exec_state)).await?;
|
||||
out.insert(filename, (import_stmt, module_id, module_path, repr.clone()));
|
||||
Box::pin(import_universe(ctx, &repr, out, exec_state)).await?;
|
||||
}
|
||||
|
||||
Ok(module_imports)
|
||||
|
@ -4,8 +4,7 @@ description: Error from executing argument_error.kcl
|
||||
---
|
||||
KCL Semantic error
|
||||
|
||||
× semantic: f requires a value with type `fn(any): any`, but found array of
|
||||
│ number(default units), number(default units) with 2 values
|
||||
× semantic: f requires a value with type `fn(any): any`, but found [any; 2]
|
||||
╭─[5:1]
|
||||
4 │
|
||||
5 │ map(f, f = [0, 1])
|
||||
@ -16,7 +15,7 @@ KCL Semantic error
|
||||
╰─▶ KCL Semantic error
|
||||
|
||||
× semantic: f requires a value with type `fn(any): any`, but found
|
||||
│ array of number(default units), number(default units) with 2 values
|
||||
│ [any; 2]
|
||||
╭─[5:12]
|
||||
4 │
|
||||
5 │ map(f, f = [0, 1])
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
source: kcl/src/simulation_tests.rs
|
||||
description: Error from executing array_elem_pop_fail.kcl
|
||||
---
|
||||
KCL UndefinedValue error
|
||||
|
@ -1,57 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Artifact commands error_with_point_shows_numeric_units.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": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"size": 60.0,
|
||||
"clobber": false,
|
||||
"hide": true
|
||||
}
|
||||
}
|
||||
]
|
@ -1,6 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart error_with_point_shows_numeric_units.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -1,5 +0,0 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
1["Plane<br>[0, 17, 0]"]
|
||||
%% [ProgramBodyItem { index: 0 }, ExpressionStatementExpr, PipeBodyItem { index: 0 }]
|
||||
```
|
@ -1,201 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Result of parsing error_with_point_shows_numeric_units.kcl
|
||||
---
|
||||
{
|
||||
"Ok": {
|
||||
"body": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"expression": {
|
||||
"body": [
|
||||
{
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "startSketchOn",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "CallExpressionKw",
|
||||
"type": "CallExpressionKw",
|
||||
"unlabeled": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "XZ",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "LabeledArg",
|
||||
"label": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "center",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"commentStart": 0,
|
||||
"elements": [
|
||||
{
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "sin",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "CallExpressionKw",
|
||||
"type": "CallExpressionKw",
|
||||
"unlabeled": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "66.6deg",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 66.6,
|
||||
"suffix": "Deg"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "cos",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "CallExpressionKw",
|
||||
"type": "CallExpressionKw",
|
||||
"unlabeled": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "66.6deg",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 66.6,
|
||||
"suffix": "Deg"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "ArrayExpression",
|
||||
"type": "ArrayExpression"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "LabeledArg",
|
||||
"label": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "radius",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "circle",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "CallExpressionKw",
|
||||
"type": "CallExpressionKw",
|
||||
"unlabeled": null
|
||||
}
|
||||
],
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "PipeExpression",
|
||||
"type": "PipeExpression"
|
||||
},
|
||||
"start": 0,
|
||||
"type": "ExpressionStatement",
|
||||
"type": "ExpressionStatement"
|
||||
}
|
||||
],
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Error from executing error_with_point_shows_numeric_units.kcl
|
||||
---
|
||||
KCL Semantic error
|
||||
|
||||
× semantic: center requires a value with type `Point2d`, but found array of
|
||||
│ number(Count), number(Count) with 2 values
|
||||
╭─[2:6]
|
||||
1 │ startSketchOn(XZ)
|
||||
2 │ ╭──▶ |> circle(center = [
|
||||
3 │ ││ sin(66.6deg),
|
||||
4 │ ││ cos(66.6deg)
|
||||
5 │ ├──▶ ], radius = 1)
|
||||
· ╰───── tests/error_with_point_shows_numeric_units/input.kcl
|
||||
· ╰───── tests/error_with_point_shows_numeric_units/input.kcl
|
||||
╰────
|
||||
╰─▶ KCL Semantic error
|
||||
|
||||
× semantic: center requires a value with type `Point2d`, but found
|
||||
│ array of number(Count), number(Count) with 2 values
|
||||
╭─[2:22]
|
||||
1 │ startSketchOn(XZ)
|
||||
2 │ ╭─▶ |> circle(center = [
|
||||
3 │ │ sin(66.6deg),
|
||||
4 │ │ cos(66.6deg)
|
||||
5 │ ├─▶ ], radius = 1)
|
||||
· ╰──── tests/error_with_point_shows_numeric_units/input.kcl
|
||||
╰────
|
@ -1,5 +0,0 @@
|
||||
startSketchOn(XZ)
|
||||
|> circle(center = [
|
||||
sin(66.6deg),
|
||||
cos(66.6deg)
|
||||
], radius = 1)
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Operations executed error_with_point_shows_numeric_units.kcl
|
||||
---
|
||||
[
|
||||
{
|
||||
"type": "StdLibCall",
|
||||
"name": "startSketchOn",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Plane",
|
||||
"artifact_id": "[uuid]"
|
||||
},
|
||||
"sourceRange": []
|
||||
},
|
||||
"labeledArgs": {},
|
||||
"sourceRange": []
|
||||
}
|
||||
]
|
@ -1,6 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Result of unparsing error_with_point_shows_numeric_units.kcl
|
||||
---
|
||||
startSketchOn(XZ)
|
||||
|> circle(center = [sin(66.6deg), cos(66.6deg)], radius = 1)
|
@ -1,184 +0,0 @@
|
||||
---
|
||||
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]"
|
||||
}
|
||||
}
|
||||
]
|
@ -1,6 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart nested_assembly.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
@ -1,23 +0,0 @@
|
||||
```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
|
||||
```
|
@ -1,73 +0,0 @@
|
||||
---
|
||||
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
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
import "nested/foo/bar/main.kcl" as bar
|
||||
|
||||
bar
|
@ -1,7 +0,0 @@
|
||||
// A donut shape.
|
||||
startSketchOn(XY)
|
||||
|> circle( center = [15, 0], radius = 5 )
|
||||
|> revolve(
|
||||
angle = 360,
|
||||
axis = Y,
|
||||
)
|
@ -1,3 +0,0 @@
|
||||
import "imported.kcl" as imported
|
||||
|
||||
imported
|
@ -1,18 +0,0 @@
|
||||
---
|
||||
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"
|
||||
}
|
||||
]
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Variables in memory after executing nested_main_kcl.kcl
|
||||
---
|
||||
{
|
||||
"bar": {
|
||||
"type": "Module",
|
||||
"value": 1
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 150 KiB |
@ -1,7 +0,0 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Result of unparsing nested_main_kcl.kcl
|
||||
---
|
||||
import "nested/foo/bar/main.kcl" as bar
|
||||
|
||||
bar
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
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)
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
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
|
@ -441,46 +441,39 @@ export const FileMachineProvider = ({
|
||||
)
|
||||
useMenuListener(cb)
|
||||
|
||||
const kclCommandMemo = useMemo(() => {
|
||||
const providedOptions = []
|
||||
if (isDesktop() && project?.children && file?.path) {
|
||||
const projectPath = project.path
|
||||
const filePath = file.path
|
||||
let children = project.children
|
||||
while (children.length > 0) {
|
||||
const v = children.pop()
|
||||
if (!v) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (v.children) {
|
||||
children.push(...v.children)
|
||||
continue
|
||||
}
|
||||
|
||||
const relativeFilePath = v.path.replace(
|
||||
projectPath + window.electron.sep,
|
||||
''
|
||||
)
|
||||
const isCurrentFile = v.path === filePath
|
||||
if (!isCurrentFile) {
|
||||
providedOptions.push({
|
||||
name: relativeFilePath.replaceAll(window.electron.sep, '/'),
|
||||
value: relativeFilePath.replaceAll(window.electron.sep, '/'),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return kclCommands({
|
||||
authToken: token ?? '',
|
||||
projectData,
|
||||
settings: {
|
||||
defaultUnit:
|
||||
settings.modeling.defaultUnit.current ?? DEFAULT_DEFAULT_LENGTH_UNIT,
|
||||
},
|
||||
specialPropsForInsertCommand: { providedOptions },
|
||||
})
|
||||
}, [codeManager, kclManager, send, project, file])
|
||||
const kclCommandMemo = useMemo(
|
||||
() =>
|
||||
kclCommands({
|
||||
authToken: token ?? '',
|
||||
projectData,
|
||||
settings: {
|
||||
defaultUnit:
|
||||
settings.modeling.defaultUnit.current ??
|
||||
DEFAULT_DEFAULT_LENGTH_UNIT,
|
||||
},
|
||||
specialPropsForInsertCommand: {
|
||||
providedOptions: (isDesktop() && project?.children
|
||||
? project.children
|
||||
: []
|
||||
).flatMap((v) => {
|
||||
// TODO: add support for full tree traversal when KCL support subdir imports
|
||||
const relativeFilePath = v.path.replace(
|
||||
project?.path + window.electron.sep,
|
||||
''
|
||||
)
|
||||
const isDirectory = v.children
|
||||
const isCurrentFile = v.path === file?.path
|
||||
return isDirectory || isCurrentFile
|
||||
? []
|
||||
: {
|
||||
name: relativeFilePath,
|
||||
value: relativeFilePath,
|
||||
}
|
||||
}),
|
||||
},
|
||||
}),
|
||||
[codeManager, kclManager, send, project, file]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
commandBarActor.send({
|
||||
|
@ -161,6 +161,40 @@ export const ModelingMachineProvider = ({
|
||||
'enable copilot': () => {
|
||||
editorManager.setCopilotEnabled(true)
|
||||
},
|
||||
'sketch exit execute': ({ context: { store } }) => {
|
||||
// TODO: Remove this async callback. For some reason eslint wouldn't
|
||||
// let me disable @typescript-eslint/no-misused-promises for the line.
|
||||
;(async () => {
|
||||
// When cancelling the sketch mode we should disable sketch mode within the engine.
|
||||
await engineCommandManager.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: { type: 'sketch_mode_disable' },
|
||||
})
|
||||
|
||||
sceneInfra.camControls.syncDirection = 'clientToEngine'
|
||||
|
||||
if (cameraProjection.current === 'perspective') {
|
||||
await sceneInfra.camControls.snapToPerspectiveBeforeHandingBackControlToEngine()
|
||||
}
|
||||
|
||||
sceneInfra.camControls.syncDirection = 'engineToClient'
|
||||
|
||||
// TODO: Re-evaluate if this pause/play logic is needed.
|
||||
store.videoElement?.pause()
|
||||
|
||||
return kclManager
|
||||
.executeCode()
|
||||
.then(() => {
|
||||
if (engineCommandManager.idleMode) return
|
||||
|
||||
store.videoElement?.play().catch((e) => {
|
||||
console.warn('Video playing was prevented', e)
|
||||
})
|
||||
})
|
||||
.catch(reportRejection)
|
||||
})().catch(reportRejection)
|
||||
},
|
||||
'Set mouse state': assign(({ context, event }) => {
|
||||
if (event.type !== 'Set mouse state') return {}
|
||||
const nextSegmentHoverMap = () => {
|
||||
@ -1269,7 +1303,6 @@ export const ModelingMachineProvider = ({
|
||||
store: {
|
||||
...modelingMachineDefaultContext.store,
|
||||
...persistedContext,
|
||||
cameraProjection,
|
||||
},
|
||||
machineManager,
|
||||
},
|
||||
|
@ -998,7 +998,7 @@ class EngineConnection extends EventTarget {
|
||||
if (!message.success) {
|
||||
const errorsString = message?.errors
|
||||
?.map((error) => {
|
||||
return ` - ${error.error_code}: ${error.message}`
|
||||
return ` - ${error?.error_code || 'Unknown error'}: ${error?.message || 'Unknown message'}`
|
||||
})
|
||||
.join('\n')
|
||||
if (message.request_id) {
|
||||
@ -1016,7 +1016,7 @@ class EngineConnection extends EventTarget {
|
||||
}
|
||||
|
||||
const firstError = message?.errors[0]
|
||||
if (firstError.error_code === 'auth_token_invalid') {
|
||||
if (firstError?.error_code === 'auth_token_invalid') {
|
||||
this.state = {
|
||||
type: EngineConnectionStateType.Disconnecting,
|
||||
value: {
|
||||
@ -1030,7 +1030,7 @@ class EngineConnection extends EventTarget {
|
||||
this.disconnectAll()
|
||||
}
|
||||
|
||||
if (firstError.error_code === 'internal_api') {
|
||||
if (firstError?.error_code === 'internal_api') {
|
||||
this.state = {
|
||||
type: EngineConnectionStateType.Disconnecting,
|
||||
value: {
|
||||
|
@ -333,7 +333,6 @@ export function createApplicationCommands({
|
||||
isDesktop() &&
|
||||
commandsContext.argumentsToSubmit.method === 'existingProject',
|
||||
skip: true,
|
||||
defaultValue: isDesktop() ? undefined : 'browser',
|
||||
options: (_, _context) => {
|
||||
const { folders } = systemIOActor.getSnapshot().context
|
||||
const options: CommandArgumentOption<string>[] = []
|
||||
|
@ -9,8 +9,6 @@ import {
|
||||
orthoScale,
|
||||
quaternionFromUpNForward,
|
||||
} from '@src/clientSideScene/helpers'
|
||||
import type { Setting } from '@src/lib/settings/initialSettings'
|
||||
import type { CameraProjectionType } from '@rust/kcl-lib/bindings/CameraProjectionType'
|
||||
import { DRAFT_DASHED_LINE } from '@src/clientSideScene/sceneConstants'
|
||||
import { DRAFT_POINT } from '@src/clientSideScene/sceneUtils'
|
||||
import { createProfileStartHandle } from '@src/clientSideScene/segments'
|
||||
@ -301,7 +299,6 @@ export type SegmentOverlayPayload =
|
||||
export interface Store {
|
||||
videoElement?: HTMLVideoElement
|
||||
openPanes: SidebarType[]
|
||||
cameraProjection?: Setting<CameraProjectionType>
|
||||
}
|
||||
|
||||
export type SketchTool =
|
||||
@ -336,6 +333,7 @@ export type ModelingMachineEvent =
|
||||
}
|
||||
| { type: 'Sketch no face' }
|
||||
| { type: 'Cancel'; cleanup?: () => void }
|
||||
| { type: 'CancelSketch' }
|
||||
| {
|
||||
type: 'Add start point' | 'Continue existing profile'
|
||||
data: {
|
||||
@ -858,6 +856,10 @@ export const modelingMachine = setup({
|
||||
sketchDetails: event.output,
|
||||
}
|
||||
}),
|
||||
'tear down client sketch': () => {
|
||||
sceneEntitiesManager.tearDownSketch({ removeAxis: false })
|
||||
},
|
||||
'remove sketch grid': () => sceneEntitiesManager.removeSketchGrid(),
|
||||
'set up draft line': assign(({ context: { sketchDetails }, event }) => {
|
||||
if (!sketchDetails) return {}
|
||||
if (event.type !== 'Add start point') return {}
|
||||
@ -1198,6 +1200,9 @@ export const modelingMachine = setup({
|
||||
'clientToEngine cam sync direction': () => {
|
||||
sceneInfra.camControls.syncDirection = 'clientToEngine'
|
||||
},
|
||||
'engineToClient cam sync direction': () => {
|
||||
sceneInfra.camControls.syncDirection = 'engineToClient'
|
||||
},
|
||||
/** TODO: this action is hiding unawaited asynchronous code */
|
||||
'set selection filter to faces only': () => {
|
||||
kclManager.setSelectionFilter(['face', 'object'])
|
||||
@ -1218,6 +1223,7 @@ export const modelingMachine = setup({
|
||||
return codeManager.updateEditorWithAstAndWriteToFile(kclManager.ast)
|
||||
})
|
||||
},
|
||||
'Reset Segment Overlays': () => sceneEntitiesManager.resetOverlays(),
|
||||
'Set context': assign({
|
||||
store: ({ context: { store }, event }) => {
|
||||
if (event.type !== 'Set context') return store
|
||||
@ -1536,6 +1542,7 @@ export const modelingMachine = setup({
|
||||
'Center camera on selection': () => {},
|
||||
'Submit to Text-to-CAD API': () => {},
|
||||
'Set sketchDetails': () => {},
|
||||
'sketch exit execute': () => {},
|
||||
'debug-action': (data) => {
|
||||
console.log('re-eval debug-action', data)
|
||||
},
|
||||
@ -1603,45 +1610,6 @@ export const modelingMachine = setup({
|
||||
},
|
||||
// end actions
|
||||
actors: {
|
||||
sketchExit: fromPromise(
|
||||
async (args: { input: { context: { store: Store } } }) => {
|
||||
const store = args.input.context.store
|
||||
|
||||
// When cancelling the sketch mode we should disable sketch mode within the engine.
|
||||
await engineCommandManager.sendSceneCommand({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: { type: 'sketch_mode_disable' },
|
||||
})
|
||||
|
||||
sceneInfra.camControls.syncDirection = 'clientToEngine'
|
||||
|
||||
if (store.cameraProjection?.current === 'perspective') {
|
||||
await sceneInfra.camControls.snapToPerspectiveBeforeHandingBackControlToEngine()
|
||||
}
|
||||
|
||||
sceneInfra.camControls.syncDirection = 'engineToClient'
|
||||
|
||||
// TODO: Re-evaluate if this pause/play logic is needed.
|
||||
store.videoElement?.pause()
|
||||
|
||||
await kclManager
|
||||
.executeCode()
|
||||
.then(() => {
|
||||
if (engineCommandManager.idleMode) return
|
||||
|
||||
store.videoElement?.play().catch((e: Error) => {
|
||||
console.warn('Video playing was prevented', e)
|
||||
})
|
||||
})
|
||||
.catch(reportRejection)
|
||||
|
||||
sceneEntitiesManager.tearDownSketch({ removeAxis: false })
|
||||
sceneEntitiesManager.removeSketchGrid()
|
||||
sceneInfra.camControls.syncDirection = 'engineToClient'
|
||||
sceneEntitiesManager.resetOverlays()
|
||||
}
|
||||
),
|
||||
/* Below are all the do-constrain sketch actors,
|
||||
* which aren't using updateModelingState and don't have the 'no kcl errors' guard yet */
|
||||
'do-constrain-remove-constraint': fromPromise(
|
||||
@ -4226,29 +4194,22 @@ export const modelingMachine = setup({
|
||||
},
|
||||
|
||||
'undo startSketchOn': {
|
||||
invoke: [
|
||||
{
|
||||
id: 'sketchExit',
|
||||
src: 'sketchExit',
|
||||
input: ({ context }) => ({ context }),
|
||||
},
|
||||
{
|
||||
src: 'AST-undo-startSketchOn',
|
||||
id: 'AST-undo-startSketchOn',
|
||||
input: ({ context: { sketchDetails } }) => ({ sketchDetails }),
|
||||
invoke: {
|
||||
src: 'AST-undo-startSketchOn',
|
||||
id: 'AST-undo-startSketchOn',
|
||||
input: ({ context: { sketchDetails } }) => ({ sketchDetails }),
|
||||
|
||||
onDone: {
|
||||
target: '#Modeling.idle',
|
||||
actions: 'enter modeling mode',
|
||||
reenter: true,
|
||||
},
|
||||
|
||||
onError: {
|
||||
target: '#Modeling.idle',
|
||||
reenter: true,
|
||||
},
|
||||
onDone: {
|
||||
target: '#Modeling.idle',
|
||||
actions: 'enter modeling mode',
|
||||
reenter: true,
|
||||
},
|
||||
],
|
||||
|
||||
onError: {
|
||||
target: '#Modeling.idle',
|
||||
reenter: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
'Rectangle tool': {
|
||||
@ -4966,6 +4927,7 @@ export const modelingMachine = setup({
|
||||
|
||||
on: {
|
||||
Cancel: '.undo startSketchOn',
|
||||
CancelSketch: '.SketchIdle',
|
||||
|
||||
'Delete segment': {
|
||||
reenter: false,
|
||||
@ -4978,7 +4940,14 @@ export const modelingMachine = setup({
|
||||
},
|
||||
},
|
||||
|
||||
exit: ['enable copilot'],
|
||||
exit: [
|
||||
'sketch exit execute',
|
||||
'tear down client sketch',
|
||||
'remove sketch grid',
|
||||
'engineToClient cam sync direction',
|
||||
'Reset Segment Overlays',
|
||||
'enable copilot',
|
||||
],
|
||||
|
||||
entry: ['add axis n grid', 'clientToEngine cam sync direction'],
|
||||
},
|
||||
|
Reference in New Issue
Block a user