Make most top-level modules in KCL private (#4478)
* Make ast module private Signed-off-by: Nick Cameron <nrc@ncameron.org> * Make most other modules private Signed-off-by: Nick Cameron <nrc@ncameron.org> * Expand API to support CLI, Python bindings, and LSP crate Signed-off-by: Nick Cameron <nrc@ncameron.org> --------- Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
12
src/wasm-lib/Cargo.lock
generated
12
src/wasm-lib/Cargo.lock
generated
@ -1737,18 +1737,6 @@ dependencies = [
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kcl-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"databake",
|
||||
"kcl-lib",
|
||||
"pretty_assertions",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.16"
|
||||
|
@ -68,7 +68,6 @@ debug = "line-tables-only"
|
||||
members = [
|
||||
"derive-docs",
|
||||
"kcl",
|
||||
"kcl-macros",
|
||||
"kcl-test-server",
|
||||
"kcl-to-core",
|
||||
]
|
||||
|
@ -173,11 +173,11 @@ fn do_stdlib_inner(
|
||||
quote! {
|
||||
let code_blocks = vec![#(#cb),*];
|
||||
code_blocks.iter().map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
}).collect::<Vec<String>>()
|
||||
}
|
||||
} else {
|
||||
@ -748,8 +748,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
|
||||
quote! {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn #test_name_mock() {
|
||||
let program = crate::parser::top_level_parse(#code_block).unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse(#code_block).unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(crate::engine::conn_mock::EngineConnection::new().await.unwrap())),
|
||||
fs: std::sync::Arc::new(crate::fs::FileManager::new()),
|
||||
@ -758,7 +757,7 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default()).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
|
@ -2,8 +2,7 @@
|
||||
mod test_examples_someFn {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_someFn0() {
|
||||
let program = crate::parser::top_level_parse("someFn()").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("someFn()").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -15,7 +14,9 @@ mod test_examples_someFn {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -111,10 +112,10 @@ impl crate::docs::StdLibFn for SomeFn {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -2,8 +2,7 @@
|
||||
mod test_examples_someFn {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_someFn0() {
|
||||
let program = crate::parser::top_level_parse("someFn()").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("someFn()").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -15,7 +14,9 @@ mod test_examples_someFn {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -111,10 +112,10 @@ impl crate::docs::StdLibFn for SomeFn {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -3,9 +3,7 @@ mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_show0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is another code block.\nyes sirrr.\nshow")
|
||||
.unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
crate::Program::parse("This is another code block.\nyes sirrr.\nshow").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +15,9 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -36,9 +36,7 @@ mod test_examples_show {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_show1() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -50,7 +48,9 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -149,10 +149,10 @@ impl crate::docs::StdLibFn for Show {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_show0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -16,7 +14,9 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -112,10 +112,10 @@ impl crate::docs::StdLibFn for Show {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -3,9 +3,7 @@ mod test_examples_my_func {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_my_func0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is another code block.\nyes sirrr.\nmyFunc")
|
||||
.unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
crate::Program::parse("This is another code block.\nyes sirrr.\nmyFunc").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +15,9 @@ mod test_examples_my_func {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -36,9 +36,7 @@ mod test_examples_my_func {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_my_func1() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nmyFunc").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nmyFunc").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -50,7 +48,9 @@ mod test_examples_my_func {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -149,10 +149,10 @@ impl crate::docs::StdLibFn for MyFunc {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -3,9 +3,7 @@ mod test_examples_line_to {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_line_to0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is another code block.\nyes sirrr.\nlineTo")
|
||||
.unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
crate::Program::parse("This is another code block.\nyes sirrr.\nlineTo").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -17,7 +15,9 @@ mod test_examples_line_to {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -36,9 +36,7 @@ mod test_examples_line_to {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_line_to1() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nlineTo").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nlineTo").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -50,7 +48,9 @@ mod test_examples_line_to {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -157,10 +157,10 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -3,8 +3,7 @@ mod test_examples_min {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_min0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is another code block.\nyes sirrr.\nmin").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
crate::Program::parse("This is another code block.\nyes sirrr.\nmin").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -16,7 +15,9 @@ mod test_examples_min {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -35,9 +36,7 @@ mod test_examples_min {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_min1() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nmin").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nmin").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -49,7 +48,9 @@ mod test_examples_min {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -148,10 +149,10 @@ impl crate::docs::StdLibFn for Min {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_show0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -16,7 +14,9 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -112,10 +112,10 @@ impl crate::docs::StdLibFn for Show {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_import0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -16,7 +14,9 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -112,10 +112,10 @@ impl crate::docs::StdLibFn for Import {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_import0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -16,7 +14,9 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -112,10 +112,10 @@ impl crate::docs::StdLibFn for Import {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_import0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nimport").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -16,7 +14,9 @@ mod test_examples_import {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -112,10 +112,10 @@ impl crate::docs::StdLibFn for Import {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_show0() {
|
||||
let program =
|
||||
crate::parser::top_level_parse("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("This is code.\nIt does other shit.\nshow").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -16,7 +14,9 @@ mod test_examples_show {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -112,10 +112,10 @@ impl crate::docs::StdLibFn for Show {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -2,8 +2,7 @@
|
||||
mod test_examples_some_function {
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_mock_example_some_function0() {
|
||||
let program = crate::parser::top_level_parse("someFunction()").unwrap();
|
||||
let id_generator = crate::executor::IdGenerator::default();
|
||||
let program = crate::Program::parse("someFunction()").unwrap();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
@ -15,7 +14,9 @@ mod test_examples_some_function {
|
||||
settings: Default::default(),
|
||||
context_type: crate::executor::ContextType::Mock,
|
||||
};
|
||||
ctx.run(&program, None, id_generator, None).await.unwrap();
|
||||
ctx.run(&program, &mut crate::ExecState::default())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
@ -106,10 +107,10 @@ impl crate::docs::StdLibFn for SomeFunction {
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let program = crate::parser::top_level_parse(cb).unwrap();
|
||||
let program = crate::Program::parse(cb).unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
program.ast.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
[package]
|
||||
name = "kcl-macros"
|
||||
description = "Macro for compiling KCL to its AST during Rust compile-time"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
databake = "0.1.8"
|
||||
kcl-lib = { path = "../kcl" }
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2.0.87", features = ["full"] }
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "1.4.1"
|
@ -1,22 +0,0 @@
|
||||
//! This crate contains macros for parsing KCL at Rust compile-time.
|
||||
use databake::*;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, LitStr};
|
||||
|
||||
/// Parses KCL into its AST at compile-time.
|
||||
/// This macro takes exactly one argument: A string literal containing KCL.
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// extern crate alloc;
|
||||
/// use kcl_compile_macro::parse_kcl;
|
||||
/// let ast: kcl_lib::ast::types::Program = parse_kcl!("const y = 4");
|
||||
/// ```
|
||||
#[proc_macro]
|
||||
pub fn parse(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as LitStr);
|
||||
let kcl_src = input.value();
|
||||
let ast = kcl_lib::parser::top_level_parse(&kcl_src).unwrap();
|
||||
let ast_struct = ast.bake(&Default::default());
|
||||
quote!(#ast_struct).into()
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
extern crate alloc;
|
||||
use kcl_lib::ast::types::{
|
||||
BodyItem, Expr, Identifier, ItemVisibility, Literal, LiteralValue, ModuleId, Node, Program, VariableDeclaration,
|
||||
VariableDeclarator, VariableKind,
|
||||
};
|
||||
use kcl_macros::parse;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
let actual = parse!("const y = 4");
|
||||
let module_id = ModuleId::default();
|
||||
let expected = Node {
|
||||
inner: Program {
|
||||
body: vec![BodyItem::VariableDeclaration(Box::new(Node::new(
|
||||
VariableDeclaration {
|
||||
declarations: vec![Node::new(
|
||||
VariableDeclarator {
|
||||
id: Node::new(
|
||||
Identifier {
|
||||
name: "y".to_owned(),
|
||||
digest: None,
|
||||
},
|
||||
6,
|
||||
7,
|
||||
module_id,
|
||||
),
|
||||
init: Expr::Literal(Box::new(Node::new(
|
||||
Literal {
|
||||
value: LiteralValue::IInteger(4),
|
||||
raw: "4".to_owned(),
|
||||
digest: None,
|
||||
},
|
||||
10,
|
||||
11,
|
||||
module_id,
|
||||
))),
|
||||
digest: None,
|
||||
},
|
||||
6,
|
||||
11,
|
||||
module_id,
|
||||
)],
|
||||
visibility: ItemVisibility::Default,
|
||||
kind: VariableKind::Const,
|
||||
digest: None,
|
||||
},
|
||||
0,
|
||||
11,
|
||||
module_id,
|
||||
)))],
|
||||
non_code_meta: Default::default(),
|
||||
digest: None,
|
||||
},
|
||||
start: 0,
|
||||
end: 11,
|
||||
module_id,
|
||||
};
|
||||
assert_eq!(expected, actual);
|
||||
}
|
@ -15,7 +15,7 @@ use hyper::{
|
||||
service::{make_service_fn, service_fn},
|
||||
Body, Error, Response, Server,
|
||||
};
|
||||
use kcl_lib::{ast::types::ModuleId, executor::ExecutorContext, settings::types::UnitLength, test_server::RequestBody};
|
||||
use kcl_lib::{test_server::RequestBody, ExecState, ExecutorContext, Program, UnitLength};
|
||||
use tokio::{
|
||||
sync::{mpsc, oneshot},
|
||||
task::JoinHandle,
|
||||
@ -157,21 +157,18 @@ async fn snapshot_endpoint(body: Bytes, state: ExecutorContext) -> Response<Body
|
||||
Err(e) => return bad_request(format!("Invalid request JSON: {e}")),
|
||||
};
|
||||
let RequestBody { kcl_program, test_name } = body;
|
||||
let module_id = ModuleId::default();
|
||||
let parser = match kcl_lib::token::lexer(&kcl_program, module_id) {
|
||||
Ok(ts) => kcl_lib::parser::Parser::new(ts),
|
||||
Err(e) => return bad_request(format!("tokenization error: {e}")),
|
||||
};
|
||||
let program = match parser.ast() {
|
||||
|
||||
let program = match Program::parse(&kcl_program) {
|
||||
Ok(pr) => pr,
|
||||
Err(e) => return bad_request(format!("Parse error: {e}")),
|
||||
};
|
||||
|
||||
eprintln!("Executing {test_name}");
|
||||
let mut id_generator = kcl_lib::executor::IdGenerator::default();
|
||||
let mut exec_state = ExecState::default();
|
||||
// This is a shitty source range, I don't know what else to use for it though.
|
||||
// There's no actual KCL associated with this reset_scene call.
|
||||
if let Err(e) = state
|
||||
.reset_scene(&mut id_generator, kcl_lib::executor::SourceRange::default())
|
||||
.reset_scene(&mut exec_state, kcl_lib::SourceRange::default())
|
||||
.await
|
||||
{
|
||||
return kcl_err(e);
|
||||
@ -179,7 +176,7 @@ async fn snapshot_endpoint(body: Bytes, state: ExecutorContext) -> Response<Body
|
||||
// Let users know if the test is taking a long time.
|
||||
let (done_tx, done_rx) = oneshot::channel::<()>();
|
||||
let timer = time_until(done_rx);
|
||||
let snapshot = match state.execute_and_prepare_snapshot(&program, id_generator, None).await {
|
||||
let snapshot = match state.execute_and_prepare_snapshot(&program, &mut exec_state).await {
|
||||
Ok(sn) => sn,
|
||||
Err(e) => return kcl_err(e),
|
||||
};
|
||||
|
@ -1,9 +1,8 @@
|
||||
use anyhow::Result;
|
||||
use indexmap::IndexMap;
|
||||
use kcl_lib::{
|
||||
engine::ExecutionKind,
|
||||
errors::KclError,
|
||||
executor::{DefaultPlanes, IdGenerator},
|
||||
exec::{DefaultPlanes, IdGenerator},
|
||||
ExecutionKind, KclError,
|
||||
};
|
||||
use kittycad_modeling_cmds::{
|
||||
self as kcmc,
|
||||
@ -23,8 +22,8 @@ const NEED_PLANES: bool = true;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EngineConnection {
|
||||
batch: Arc<Mutex<Vec<(WebSocketRequest, kcl_lib::executor::SourceRange)>>>,
|
||||
batch_end: Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::executor::SourceRange)>>>,
|
||||
batch: Arc<Mutex<Vec<(WebSocketRequest, kcl_lib::SourceRange)>>>,
|
||||
batch_end: Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::SourceRange)>>>,
|
||||
core_test: Arc<Mutex<String>>,
|
||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||
execution_kind: Arc<Mutex<ExecutionKind>>,
|
||||
@ -354,12 +353,12 @@ fn codegen_cpp_repl_uuid_setters(reps_id: &str, entity_ids: &[uuid::Uuid]) -> St
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl kcl_lib::engine::EngineManager for EngineConnection {
|
||||
fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, kcl_lib::executor::SourceRange)>>> {
|
||||
impl kcl_lib::EngineManager for EngineConnection {
|
||||
fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, kcl_lib::SourceRange)>>> {
|
||||
self.batch.clone()
|
||||
}
|
||||
|
||||
fn batch_end(&self) -> Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::executor::SourceRange)>>> {
|
||||
fn batch_end(&self) -> Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::SourceRange)>>> {
|
||||
self.batch_end.clone()
|
||||
}
|
||||
|
||||
@ -378,7 +377,7 @@ impl kcl_lib::engine::EngineManager for EngineConnection {
|
||||
async fn default_planes(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
source_range: kcl_lib::executor::SourceRange,
|
||||
source_range: kcl_lib::SourceRange,
|
||||
) -> Result<DefaultPlanes, KclError> {
|
||||
if NEED_PLANES {
|
||||
{
|
||||
@ -400,7 +399,7 @@ impl kcl_lib::engine::EngineManager for EngineConnection {
|
||||
async fn clear_scene_post_hook(
|
||||
&self,
|
||||
_id_generator: &mut IdGenerator,
|
||||
_source_range: kcl_lib::executor::SourceRange,
|
||||
_source_range: kcl_lib::SourceRange,
|
||||
) -> Result<(), KclError> {
|
||||
Ok(())
|
||||
}
|
||||
@ -408,9 +407,9 @@ impl kcl_lib::engine::EngineManager for EngineConnection {
|
||||
async fn inner_send_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
_source_range: kcl_lib::executor::SourceRange,
|
||||
_source_range: kcl_lib::SourceRange,
|
||||
cmd: WebSocketRequest,
|
||||
_id_to_source_range: std::collections::HashMap<uuid::Uuid, kcl_lib::executor::SourceRange>,
|
||||
_id_to_source_range: std::collections::HashMap<uuid::Uuid, kcl_lib::SourceRange>,
|
||||
) -> Result<WebSocketResponse, KclError> {
|
||||
match cmd {
|
||||
WebSocketRequest::ModelingCmdBatchReq(ModelingBatch {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use kcl_lib::executor::{ExecutorContext, IdGenerator};
|
||||
use kcl_lib::{ExecState, ExecutorContext};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@ -7,21 +7,15 @@ mod conn_mock_core;
|
||||
|
||||
///Converts the given kcl code to an engine test
|
||||
pub async fn kcl_to_engine_core(code: &str) -> Result<String> {
|
||||
let program = kcl_lib::parser::top_level_parse(code)?;
|
||||
let program = kcl_lib::Program::parse(code)?;
|
||||
|
||||
let result = Arc::new(Mutex::new("".into()));
|
||||
let ref_result = Arc::clone(&result);
|
||||
|
||||
let ctx = ExecutorContext {
|
||||
engine: Arc::new(Box::new(
|
||||
let ctx = ExecutorContext::new_forwarded_mock(Arc::new(Box::new(
|
||||
crate::conn_mock_core::EngineConnection::new(ref_result).await?,
|
||||
)),
|
||||
fs: Arc::new(kcl_lib::fs::FileManager::new()),
|
||||
stdlib: Arc::new(kcl_lib::std::StdLib::new()),
|
||||
settings: Default::default(),
|
||||
context_type: kcl_lib::executor::ContextType::MockCustomForwarded,
|
||||
};
|
||||
let _memory = ctx.run(&program, None, IdGenerator::default(), None).await?;
|
||||
)));
|
||||
ctx.run(&program, &mut ExecState::default()).await?;
|
||||
|
||||
let result = result.lock().expect("mutex lock").clone();
|
||||
Ok(result)
|
||||
|
@ -1,12 +1,5 @@
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
pub fn bench_lex(c: &mut Criterion) {
|
||||
let module_id = kcl_lib::ast::types::ModuleId::default();
|
||||
c.bench_function("lex_cube", |b| b.iter(|| lex(CUBE_PROGRAM, module_id)));
|
||||
c.bench_function("lex_big_kitt", |b| b.iter(|| lex(KITT_PROGRAM, module_id)));
|
||||
c.bench_function("lex_pipes_on_pipes", |b| b.iter(|| lex(PIPES_PROGRAM, module_id)));
|
||||
}
|
||||
|
||||
pub fn bench_parse(c: &mut Criterion) {
|
||||
for (name, file) in [
|
||||
("pipes_on_pipes", PIPES_PROGRAM),
|
||||
@ -16,23 +9,15 @@ pub fn bench_parse(c: &mut Criterion) {
|
||||
("mike_stress_test", MIKE_STRESS_TEST_PROGRAM),
|
||||
("koch snowflake", LSYSTEM_KOCH_SNOWFLAKE_PROGRAM),
|
||||
] {
|
||||
let module_id = kcl_lib::ast::types::ModuleId::default();
|
||||
let tokens = kcl_lib::token::lexer(file, module_id).unwrap();
|
||||
c.bench_function(&format!("parse_{name}"), move |b| {
|
||||
let tok = tokens.clone();
|
||||
b.iter(move || {
|
||||
let parser = kcl_lib::parser::Parser::new(tok.clone());
|
||||
black_box(parser.ast().unwrap());
|
||||
black_box(kcl_lib::Program::parse(file).unwrap());
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn lex(program: &str, module_id: kcl_lib::ast::types::ModuleId) {
|
||||
black_box(kcl_lib::token::lexer(program, module_id).unwrap());
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_lex, bench_parse);
|
||||
criterion_group!(benches, bench_parse);
|
||||
criterion_main!(benches);
|
||||
|
||||
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
|
||||
|
@ -1,32 +1,7 @@
|
||||
use iai::black_box;
|
||||
|
||||
pub fn parse(program: &str) {
|
||||
let module_id = kcl_lib::ast::types::ModuleId::default();
|
||||
let tokens = kcl_lib::token::lexer(program, module_id).unwrap();
|
||||
let tok = tokens.clone();
|
||||
let parser = kcl_lib::parser::Parser::new(tok.clone());
|
||||
black_box(parser.ast().unwrap());
|
||||
}
|
||||
|
||||
fn lex_kitt() {
|
||||
let module_id = kcl_lib::ast::types::ModuleId::default();
|
||||
black_box(kcl_lib::token::lexer(KITT_PROGRAM, module_id).unwrap());
|
||||
}
|
||||
fn lex_pipes() {
|
||||
let module_id = kcl_lib::ast::types::ModuleId::default();
|
||||
black_box(kcl_lib::token::lexer(PIPES_PROGRAM, module_id).unwrap());
|
||||
}
|
||||
fn lex_cube() {
|
||||
let module_id = kcl_lib::ast::types::ModuleId::default();
|
||||
black_box(kcl_lib::token::lexer(CUBE_PROGRAM, module_id).unwrap());
|
||||
}
|
||||
fn lex_math() {
|
||||
let module_id = kcl_lib::ast::types::ModuleId::default();
|
||||
black_box(kcl_lib::token::lexer(MATH_PROGRAM, module_id).unwrap());
|
||||
}
|
||||
fn lex_lsystem() {
|
||||
let module_id = kcl_lib::ast::types::ModuleId::default();
|
||||
black_box(kcl_lib::token::lexer(LSYSTEM_PROGRAM, module_id).unwrap());
|
||||
black_box(kcl_lib::Program::parse(program).unwrap());
|
||||
}
|
||||
|
||||
fn parse_kitt() {
|
||||
@ -46,11 +21,6 @@ fn parse_lsystem() {
|
||||
}
|
||||
|
||||
iai::main! {
|
||||
lex_kitt,
|
||||
lex_pipes,
|
||||
lex_cube,
|
||||
lex_math,
|
||||
lex_lsystem,
|
||||
parse_kitt,
|
||||
parse_pipes,
|
||||
parse_cube,
|
||||
|
@ -9,7 +9,7 @@ pub fn bench_digest(c: &mut Criterion) {
|
||||
("mike_stress_test", MIKE_STRESS_TEST_PROGRAM),
|
||||
("lsystem", LSYSTEM_PROGRAM),
|
||||
] {
|
||||
let prog = kcl_lib::parser::top_level_parse(file).unwrap();
|
||||
let prog = kcl_lib::Program::parse(file).unwrap();
|
||||
c.bench_function(&format!("digest_{name}"), move |b| {
|
||||
let prog = prog.clone();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use kcl_lib::{settings::types::UnitLength::Mm, test_server};
|
||||
use kcl_lib::{test_server, UnitLength::Mm};
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
pub fn bench_execute(c: &mut Criterion) {
|
||||
|
@ -3,7 +3,7 @@ use iai::black_box;
|
||||
async fn execute_server_rack_heavy() {
|
||||
let code = SERVER_RACK_HEAVY_PROGRAM;
|
||||
black_box(
|
||||
kcl_lib::test_server::execute_and_snapshot(code, kcl_lib::settings::types::UnitLength::Mm)
|
||||
kcl_lib::test_server::execute_and_snapshot(code, kcl_lib::UnitLength::Mm)
|
||||
.await
|
||||
.unwrap(),
|
||||
);
|
||||
@ -12,7 +12,7 @@ async fn execute_server_rack_heavy() {
|
||||
async fn execute_server_rack_lite() {
|
||||
let code = SERVER_RACK_LITE_PROGRAM;
|
||||
black_box(
|
||||
kcl_lib::test_server::execute_and_snapshot(code, kcl_lib::settings::types::UnitLength::Mm)
|
||||
kcl_lib::test_server::execute_and_snapshot(code, kcl_lib::UnitLength::Mm)
|
||||
.await
|
||||
.unwrap(),
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use kcl_lib::lsp::test_util::kcl_lsp_server;
|
||||
use kcl_lib::kcl_lsp_server;
|
||||
use tokio::runtime::Runtime;
|
||||
use tower_lsp::LanguageServer;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use iai::black_box;
|
||||
use kcl_lib::lsp::test_util::kcl_lsp_server;
|
||||
use kcl_lib::kcl_lsp_server;
|
||||
use tower_lsp::LanguageServer;
|
||||
|
||||
async fn kcl_lsp_semantic_tokens(code: &str) {
|
||||
|
@ -9,11 +9,12 @@ use kittycad_modeling_cmds as kcmc;
|
||||
use crate::{
|
||||
ast::types::{
|
||||
ArrayExpression, CallExpression, ConstraintLevel, FormatOptions, Literal, PipeExpression, PipeSubstitution,
|
||||
Program, VariableDeclarator,
|
||||
VariableDeclarator,
|
||||
},
|
||||
engine::EngineManager,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{Point2d, SourceRange},
|
||||
Program,
|
||||
};
|
||||
|
||||
use super::types::{ModuleId, Node};
|
||||
@ -22,13 +23,13 @@ type Point3d = kcmc::shared::Point3d<f64>;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// The control point data for a curve or line.
|
||||
pub struct ControlPointData {
|
||||
struct ControlPointData {
|
||||
/// The control points for the curve or line.
|
||||
pub points: Vec<Point3d>,
|
||||
points: Vec<Point3d>,
|
||||
/// The command that created this curve or line.
|
||||
pub command: PathCommand,
|
||||
_command: PathCommand,
|
||||
/// The id of the curve or line.
|
||||
pub id: uuid::Uuid,
|
||||
_id: uuid::Uuid,
|
||||
}
|
||||
|
||||
const EPSILON: f64 = 0.015625; // or 2^-6
|
||||
@ -37,7 +38,7 @@ const EPSILON: f64 = 0.015625; // or 2^-6
|
||||
/// a move or a new line.
|
||||
pub async fn modify_ast_for_sketch(
|
||||
engine: &Arc<Box<dyn EngineManager>>,
|
||||
program: &mut Node<Program>,
|
||||
program: &mut Program,
|
||||
module_id: ModuleId,
|
||||
// The name of the sketch.
|
||||
sketch_name: &str,
|
||||
@ -50,7 +51,7 @@ pub async fn modify_ast_for_sketch(
|
||||
// If it is, we cannot modify it.
|
||||
|
||||
// Get the information about the sketch.
|
||||
if let Some(ast_sketch) = program.get_variable(sketch_name) {
|
||||
if let Some(ast_sketch) = program.ast.get_variable(sketch_name) {
|
||||
let constraint_level = match ast_sketch {
|
||||
super::types::Definition::Variable(var) => var.get_constraint_level(),
|
||||
super::types::Definition::Import(import) => import.get_constraint_level(),
|
||||
@ -130,8 +131,8 @@ pub async fn modify_ast_for_sketch(
|
||||
|
||||
control_points.push(ControlPointData {
|
||||
points: data.control_points.clone(),
|
||||
command: segment.command,
|
||||
id: (*command_id).into(),
|
||||
_command: segment.command,
|
||||
_id: (*command_id).into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -179,12 +180,12 @@ pub async fn modify_ast_for_sketch(
|
||||
)?;
|
||||
|
||||
// Add the sketch back to the program.
|
||||
program.replace_variable(sketch_name, sketch);
|
||||
program.ast.replace_variable(sketch_name, sketch);
|
||||
|
||||
let recasted = program.recast(&FormatOptions::default(), 0);
|
||||
let recasted = program.ast.recast(&FormatOptions::default(), 0);
|
||||
|
||||
// Re-parse the ast so we get the correct source ranges.
|
||||
*program = crate::parser::parse(&recasted, module_id)?;
|
||||
*program = crate::parser::parse(&recasted, module_id)?.into();
|
||||
|
||||
Ok(recasted)
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ impl Node<Program> {
|
||||
/// Check the provided Program for any lint findings.
|
||||
pub fn lint<'a, RuleT>(&'a self, rule: RuleT) -> Result<Vec<crate::lint::Discovered>>
|
||||
where
|
||||
RuleT: crate::lint::rule::Rule<'a>,
|
||||
RuleT: crate::lint::Rule<'a>,
|
||||
{
|
||||
let v = Arc::new(Mutex::new(vec![]));
|
||||
crate::walk::walk(self, &|node: crate::walk::Node<'a>| {
|
||||
|
@ -1,4 +1,5 @@
|
||||
//! Core dump related structures and functions.
|
||||
#![allow(dead_code)]
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod local;
|
||||
|
@ -26,14 +26,14 @@ type Point3D = kcmc::shared::Point3d<f64>;
|
||||
|
||||
use crate::{
|
||||
ast::types::{
|
||||
BodyItem, Expr, FunctionExpression, ItemVisibility, KclNone, ModuleId, Node, NodeRef, Program, TagDeclarator,
|
||||
TagNode,
|
||||
BodyItem, Expr, FunctionExpression, ItemVisibility, KclNone, ModuleId, Node, NodeRef, TagDeclarator, TagNode,
|
||||
},
|
||||
engine::{EngineManager, ExecutionKind},
|
||||
errors::{KclError, KclErrorDetails},
|
||||
fs::{FileManager, FileSystem},
|
||||
settings::types::UnitLength,
|
||||
std::{FnAsArg, StdLib},
|
||||
Program,
|
||||
};
|
||||
|
||||
/// State for executing a program.
|
||||
@ -152,6 +152,7 @@ impl ProgramMemory {
|
||||
/// Find all solids in the memory that are on a specific sketch id.
|
||||
/// This does not look inside closures. But as long as we do not allow
|
||||
/// mutation of variables in KCL, closure memory should be a subset of this.
|
||||
#[allow(clippy::vec_box)]
|
||||
pub fn find_solids_on_sketch(&self, sketch_id: uuid::Uuid) -> Vec<Box<Solid>> {
|
||||
self.environments
|
||||
.iter()
|
||||
@ -537,6 +538,7 @@ impl Geometry {
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
#[allow(clippy::vec_box)]
|
||||
pub enum Geometries {
|
||||
Sketches(Vec<Box<Sketch>>),
|
||||
Solids(Vec<Box<Solid>>),
|
||||
@ -555,6 +557,7 @@ impl From<Geometry> for Geometries {
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[allow(clippy::vec_box)]
|
||||
pub enum SketchSet {
|
||||
Sketch(Box<Sketch>),
|
||||
Sketches(Vec<Box<Sketch>>),
|
||||
@ -635,6 +638,7 @@ impl From<Box<Sketch>> for Vec<Box<Sketch>> {
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[allow(clippy::vec_box)]
|
||||
pub enum SolidSet {
|
||||
Solid(Box<Solid>),
|
||||
Solids(Vec<Box<Solid>>),
|
||||
@ -2189,6 +2193,70 @@ impl ExecutorContext {
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub async fn new_mock() -> Self {
|
||||
ExecutorContext {
|
||||
engine: Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new().await.unwrap(),
|
||||
)),
|
||||
fs: Arc::new(FileManager::new()),
|
||||
stdlib: Arc::new(StdLib::new()),
|
||||
settings: Default::default(),
|
||||
context_type: ContextType::Mock,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub async fn new(
|
||||
engine_manager: crate::engine::conn_wasm::EngineCommandManager,
|
||||
fs_manager: crate::fs::wasm::FileSystemManager,
|
||||
units: UnitLength,
|
||||
) -> Result<Self, String> {
|
||||
Ok(ExecutorContext {
|
||||
engine: Arc::new(Box::new(
|
||||
crate::engine::conn_wasm::EngineConnection::new(engine_manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
)),
|
||||
fs: Arc::new(FileManager::new(fs_manager)),
|
||||
stdlib: Arc::new(StdLib::new()),
|
||||
settings: ExecutorSettings {
|
||||
units,
|
||||
..Default::default()
|
||||
},
|
||||
context_type: ContextType::Live,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub async fn new_mock(fs_manager: crate::fs::wasm::FileSystemManager, units: UnitLength) -> Result<Self, String> {
|
||||
Ok(ExecutorContext {
|
||||
engine: Arc::new(Box::new(
|
||||
crate::engine::conn_mock::EngineConnection::new()
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
)),
|
||||
fs: Arc::new(FileManager::new(fs_manager)),
|
||||
stdlib: Arc::new(StdLib::new()),
|
||||
settings: ExecutorSettings {
|
||||
units,
|
||||
..Default::default()
|
||||
},
|
||||
context_type: ContextType::Mock,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn new_forwarded_mock(engine: Arc<Box<dyn EngineManager>>) -> Self {
|
||||
ExecutorContext {
|
||||
engine,
|
||||
fs: Arc::new(FileManager::new()),
|
||||
stdlib: Arc::new(StdLib::new()),
|
||||
settings: Default::default(),
|
||||
context_type: ContextType::MockCustomForwarded,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new default executor context.
|
||||
/// With a kittycad client.
|
||||
/// This allows for passing in `ZOO_API_TOKEN` and `ZOO_HOST` as environment
|
||||
@ -2212,9 +2280,17 @@ impl ExecutorContext {
|
||||
/// This allows for passing in `ZOO_API_TOKEN` and `ZOO_HOST` as environment
|
||||
/// variables.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub async fn new_with_default_client(settings: ExecutorSettings) -> Result<Self> {
|
||||
pub async fn new_with_default_client(units: UnitLength) -> Result<Self> {
|
||||
// Create the client.
|
||||
let ctx = Self::new_with_client(settings, None, None).await?;
|
||||
let ctx = Self::new_with_client(
|
||||
ExecutorSettings {
|
||||
units,
|
||||
..Default::default()
|
||||
},
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
Ok(ctx)
|
||||
}
|
||||
|
||||
@ -2242,48 +2318,31 @@ impl ExecutorContext {
|
||||
|
||||
pub async fn reset_scene(
|
||||
&self,
|
||||
id_generator: &mut IdGenerator,
|
||||
exec_state: &mut ExecState,
|
||||
source_range: crate::executor::SourceRange,
|
||||
) -> Result<()> {
|
||||
self.engine.clear_scene(id_generator, source_range).await?;
|
||||
self.engine
|
||||
.clear_scene(&mut exec_state.id_generator, source_range)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Perform the execution of a program.
|
||||
/// You can optionally pass in some initialization memory.
|
||||
/// Kurt uses this for partial execution.
|
||||
pub async fn run(
|
||||
&self,
|
||||
program: NodeRef<'_, crate::ast::types::Program>,
|
||||
memory: Option<ProgramMemory>,
|
||||
id_generator: IdGenerator,
|
||||
project_directory: Option<String>,
|
||||
) -> Result<ExecState, KclError> {
|
||||
self.run_with_session_data(program, memory, id_generator, project_directory)
|
||||
.await
|
||||
.map(|x| x.0)
|
||||
pub async fn run(&self, program: &Program, exec_state: &mut ExecState) -> Result<(), KclError> {
|
||||
self.run_with_session_data(program, exec_state).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Perform the execution of a program.
|
||||
/// You can optionally pass in some initialization memory.
|
||||
/// Kurt uses this for partial execution.
|
||||
pub async fn run_with_session_data(
|
||||
&self,
|
||||
program: NodeRef<'_, crate::ast::types::Program>,
|
||||
memory: Option<ProgramMemory>,
|
||||
id_generator: IdGenerator,
|
||||
project_directory: Option<String>,
|
||||
) -> Result<(ExecState, Option<ModelingSessionData>), KclError> {
|
||||
let memory = if let Some(memory) = memory {
|
||||
memory.clone()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let mut exec_state = ExecState {
|
||||
memory,
|
||||
id_generator,
|
||||
project_directory,
|
||||
..Default::default()
|
||||
};
|
||||
program: &Program,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<Option<ModelingSessionData>, KclError> {
|
||||
// TODO: Use the top-level file's path.
|
||||
exec_state.add_module(std::path::PathBuf::from(""));
|
||||
// Before we even start executing the program, set the units.
|
||||
@ -2304,10 +2363,10 @@ impl ExecutorContext {
|
||||
)
|
||||
.await?;
|
||||
|
||||
self.inner_execute(program, &mut exec_state, crate::executor::BodyType::Root)
|
||||
self.inner_execute(&program.ast, exec_state, crate::executor::BodyType::Root)
|
||||
.await?;
|
||||
let session_data = self.engine.get_session_data();
|
||||
Ok((exec_state, session_data))
|
||||
Ok(session_data)
|
||||
}
|
||||
|
||||
/// Execute an AST's program.
|
||||
@ -2558,23 +2617,15 @@ impl ExecutorContext {
|
||||
/// Execute the program, then get a PNG screenshot.
|
||||
pub async fn execute_and_prepare_snapshot(
|
||||
&self,
|
||||
program: NodeRef<'_, Program>,
|
||||
id_generator: IdGenerator,
|
||||
project_directory: Option<String>,
|
||||
program: &Program,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<TakeSnapshot> {
|
||||
self.execute_and_prepare(program, id_generator, project_directory)
|
||||
.await
|
||||
.map(|(_state, snap)| snap)
|
||||
self.execute_and_prepare(program, exec_state).await
|
||||
}
|
||||
|
||||
/// Execute the program, return the interpreter and outputs.
|
||||
pub async fn execute_and_prepare(
|
||||
&self,
|
||||
program: NodeRef<'_, Program>,
|
||||
id_generator: IdGenerator,
|
||||
project_directory: Option<String>,
|
||||
) -> Result<(ExecState, TakeSnapshot)> {
|
||||
let state = self.run(program, None, id_generator, project_directory).await?;
|
||||
pub async fn execute_and_prepare(&self, program: &Program, exec_state: &mut ExecState) -> Result<TakeSnapshot> {
|
||||
self.run(program, exec_state).await?;
|
||||
|
||||
// Zoom to fit.
|
||||
self.engine
|
||||
@ -2607,7 +2658,7 @@ impl ExecutorContext {
|
||||
else {
|
||||
anyhow::bail!("Unexpected response from engine: {:?}", resp);
|
||||
};
|
||||
Ok((state, contents))
|
||||
Ok(contents)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2714,7 +2765,7 @@ mod tests {
|
||||
use crate::ast::types::{Identifier, Node, Parameter};
|
||||
|
||||
pub async fn parse_execute(code: &str) -> Result<ProgramMemory> {
|
||||
let program = crate::parser::top_level_parse(code)?;
|
||||
let program = Program::parse(code)?;
|
||||
|
||||
let ctx = ExecutorContext {
|
||||
engine: Arc::new(Box::new(crate::engine::conn_mock::EngineConnection::new().await?)),
|
||||
@ -2723,7 +2774,8 @@ mod tests {
|
||||
settings: Default::default(),
|
||||
context_type: ContextType::Mock,
|
||||
};
|
||||
let exec_state = ctx.run(&program, None, IdGenerator::default(), None).await?;
|
||||
let mut exec_state = ExecState::default();
|
||||
ctx.run(&program, &mut exec_state).await?;
|
||||
|
||||
Ok(exec_state.memory)
|
||||
}
|
||||
|
@ -13,26 +13,112 @@ macro_rules! println {
|
||||
}
|
||||
}
|
||||
|
||||
pub mod ast;
|
||||
pub mod coredump;
|
||||
pub mod docs;
|
||||
pub mod engine;
|
||||
pub mod errors;
|
||||
pub mod executor;
|
||||
pub mod fs;
|
||||
mod ast;
|
||||
mod coredump;
|
||||
mod docs;
|
||||
mod engine;
|
||||
mod errors;
|
||||
mod executor;
|
||||
mod fs;
|
||||
mod function_param;
|
||||
pub mod lint;
|
||||
pub mod lsp;
|
||||
pub mod parser;
|
||||
pub mod settings;
|
||||
mod lsp;
|
||||
mod parser;
|
||||
mod settings;
|
||||
#[cfg(test)]
|
||||
mod simulation_tests;
|
||||
pub mod std;
|
||||
mod std;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod test_server;
|
||||
pub mod thread;
|
||||
pub mod token;
|
||||
mod thread;
|
||||
mod token;
|
||||
mod unparser;
|
||||
pub mod walk;
|
||||
mod walk;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub mod wasm;
|
||||
mod wasm;
|
||||
|
||||
pub use ast::modify::modify_ast_for_sketch;
|
||||
pub use ast::types::{FormatOptions, ModuleId};
|
||||
pub use coredump::CoreDump;
|
||||
pub use engine::{EngineManager, ExecutionKind};
|
||||
pub use errors::KclError;
|
||||
pub use executor::{ExecState, ExecutorContext, ExecutorSettings, SourceRange};
|
||||
pub use lsp::copilot::Backend as CopilotLspBackend;
|
||||
pub use lsp::kcl::Backend as KclLspBackend;
|
||||
pub use lsp::kcl::Server as KclLspServerSubCommand;
|
||||
pub use settings::types::{project::ProjectConfiguration, Configuration, UnitLength};
|
||||
pub use token::lexer;
|
||||
|
||||
// Rather than make executor public and make lots of it pub(crate), just re-export into a new module.
|
||||
// Ideally we wouldn't export these things at all, they should only be used for testing.
|
||||
pub mod exec {
|
||||
pub use crate::executor::{DefaultPlanes, IdGenerator, KclValue, PlaneType, ProgramMemory, Sketch};
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub mod wasm_engine {
|
||||
pub use crate::coredump::wasm::{CoreDumpManager, CoreDumper};
|
||||
pub use crate::engine::conn_wasm::{EngineCommandManager, EngineConnection};
|
||||
pub use crate::fs::wasm::FileSystemManager;
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod native_engine {
|
||||
pub use crate::engine::conn::EngineConnection;
|
||||
}
|
||||
|
||||
pub mod std_utils {
|
||||
pub use crate::std::utils::{get_tangential_arc_to_info, is_points_ccw_wasm, TangentialArcInfoInput};
|
||||
}
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Program {
|
||||
#[serde(flatten)]
|
||||
ast: ast::types::Node<ast::types::Program>,
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "lsp-test-util"))]
|
||||
pub use lsp::test_util::copilot_lsp_server;
|
||||
#[cfg(any(test, feature = "lsp-test-util"))]
|
||||
pub use lsp::test_util::kcl_lsp_server;
|
||||
|
||||
impl Program {
|
||||
pub fn parse(input: &str) -> Result<Program, KclError> {
|
||||
let module_id = ModuleId::default();
|
||||
let tokens = token::lexer(input, module_id)?;
|
||||
let parser = parser::Parser::new(tokens);
|
||||
let ast = parser.ast()?;
|
||||
|
||||
Ok(Program { ast })
|
||||
}
|
||||
|
||||
/// Deserialize the ast from a stringified json
|
||||
pub fn compute_digest(&mut self) -> ast::types::digest::Digest {
|
||||
self.ast.compute_digest()
|
||||
}
|
||||
|
||||
pub fn lint_all(&self) -> Result<Vec<lint::Discovered>, anyhow::Error> {
|
||||
self.ast.lint_all()
|
||||
}
|
||||
|
||||
pub fn lint<'a>(&'a self, rule: impl lint::Rule<'a>) -> Result<Vec<lint::Discovered>, anyhow::Error> {
|
||||
self.ast.lint(rule)
|
||||
}
|
||||
|
||||
pub fn recast(&self) -> String {
|
||||
// Use the default options until we integrate into the UI the ability to change them.
|
||||
self.ast.recast(&Default::default(), 0)
|
||||
}
|
||||
|
||||
pub fn recast_with_options(&self, options: &FormatOptions) -> String {
|
||||
self.ast.recast(options, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ast::types::Node<ast::types::Program>> for Program {
|
||||
fn from(ast: ast::types::Node<ast::types::Program>) -> Program {
|
||||
Self { ast }
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ mod camel_case;
|
||||
mod offset_plane;
|
||||
mod std_lib_args;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub use camel_case::{lint_object_properties, lint_variables, Z0001};
|
||||
pub use offset_plane::{lint_should_be_offset_plane, Z0003};
|
||||
pub use std_lib_args::{lint_call_expressions, Z0002};
|
||||
|
@ -1,4 +1,4 @@
|
||||
pub mod checks;
|
||||
pub mod rule;
|
||||
mod rule;
|
||||
|
||||
pub use rule::{Discovered, Finding};
|
||||
pub use rule::{Discovered, Finding, Rule};
|
||||
|
@ -1,4 +1,5 @@
|
||||
//! The copilot lsp server for ghost text.
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub mod cache;
|
||||
pub mod types;
|
||||
@ -26,6 +27,7 @@ use tower_lsp::{
|
||||
|
||||
use crate::lsp::{
|
||||
backend::Backend as _,
|
||||
copilot::cache::CopilotCache,
|
||||
copilot::types::{
|
||||
CopilotAcceptCompletionParams, CopilotCompletionResponse, CopilotCompletionTelemetry, CopilotEditorInfo,
|
||||
CopilotLspCompletionParams, CopilotRejectCompletionParams, DocParams,
|
||||
@ -131,6 +133,38 @@ impl crate::lsp::backend::Backend for Backend {
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn new_wasm(
|
||||
client: tower_lsp::Client,
|
||||
fs: crate::fs::wasm::FileSystemManager,
|
||||
zoo_client: kittycad::Client,
|
||||
dev_mode: bool,
|
||||
) -> Self {
|
||||
Self::new(client, crate::fs::FileManager::new(fs), zoo_client, dev_mode)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
client: tower_lsp::Client,
|
||||
fs: crate::fs::FileManager,
|
||||
zoo_client: kittycad::Client,
|
||||
dev_mode: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
client,
|
||||
fs: Arc::new(fs),
|
||||
workspace_folders: Default::default(),
|
||||
code_map: Default::default(),
|
||||
editor_info: Arc::new(RwLock::new(CopilotEditorInfo::default())),
|
||||
cache: Arc::new(CopilotCache::new()),
|
||||
telemetry: Default::default(),
|
||||
zoo_client,
|
||||
|
||||
is_initialized: Default::default(),
|
||||
diagnostics_map: Default::default(),
|
||||
dev_mode,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get completions from the kittycad api.
|
||||
pub async fn get_completions(&self, language: String, prompt: String, suffix: String) -> Result<Vec<String>> {
|
||||
let body = kittycad::types::KclCodeCompletionRequest {
|
||||
|
@ -1,4 +1,5 @@
|
||||
//! Functions for the `kcl` lsp server.
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@ -40,11 +41,11 @@ use tower_lsp::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ast::types::{Expr, ModuleId, Node, NodeRef, VariableKind},
|
||||
executor::{IdGenerator, SourceRange},
|
||||
ast::types::{Expr, ModuleId, Node, VariableKind},
|
||||
lsp::{backend::Backend as _, util::IntoDiagnostic},
|
||||
parser::PIPE_OPERATOR,
|
||||
token::TokenType,
|
||||
ExecState, Program, SourceRange,
|
||||
};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@ -122,6 +123,73 @@ pub struct Backend {
|
||||
pub is_initialized: Arc<RwLock<bool>>,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn new_wasm(
|
||||
client: Client,
|
||||
executor_ctx: Option<crate::executor::ExecutorContext>,
|
||||
fs: crate::fs::wasm::FileSystemManager,
|
||||
zoo_client: kittycad::Client,
|
||||
can_send_telemetry: bool,
|
||||
) -> Result<Self, String> {
|
||||
Self::with_file_manager(
|
||||
client,
|
||||
executor_ctx,
|
||||
crate::fs::FileManager::new(fs),
|
||||
zoo_client,
|
||||
can_send_telemetry,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn new(
|
||||
client: Client,
|
||||
executor_ctx: Option<crate::executor::ExecutorContext>,
|
||||
zoo_client: kittycad::Client,
|
||||
can_send_telemetry: bool,
|
||||
) -> Result<Self, String> {
|
||||
Self::with_file_manager(
|
||||
client,
|
||||
executor_ctx,
|
||||
crate::fs::FileManager::new(),
|
||||
zoo_client,
|
||||
can_send_telemetry,
|
||||
)
|
||||
}
|
||||
|
||||
fn with_file_manager(
|
||||
client: Client,
|
||||
executor_ctx: Option<crate::executor::ExecutorContext>,
|
||||
fs: crate::fs::FileManager,
|
||||
zoo_client: kittycad::Client,
|
||||
can_send_telemetry: bool,
|
||||
) -> Result<Self, String> {
|
||||
let stdlib = crate::std::StdLib::new();
|
||||
let stdlib_completions = get_completions_from_stdlib(&stdlib).map_err(|e| e.to_string())?;
|
||||
let stdlib_signatures = get_signatures_from_stdlib(&stdlib).map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(Self {
|
||||
client,
|
||||
fs: Arc::new(fs),
|
||||
stdlib_completions,
|
||||
stdlib_signatures,
|
||||
zoo_client,
|
||||
can_send_telemetry,
|
||||
can_execute: Arc::new(RwLock::new(executor_ctx.is_some())),
|
||||
executor_ctx: Arc::new(RwLock::new(executor_ctx)),
|
||||
workspace_folders: Default::default(),
|
||||
token_map: Default::default(),
|
||||
ast_map: Default::default(),
|
||||
memory_map: Default::default(),
|
||||
code_map: Default::default(),
|
||||
diagnostics_map: Default::default(),
|
||||
symbols_map: Default::default(),
|
||||
semantic_tokens_map: Default::default(),
|
||||
is_initialized: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the shared backend trait for the language server.
|
||||
#[async_trait::async_trait]
|
||||
impl crate::lsp::backend::Backend for Backend {
|
||||
@ -289,7 +357,7 @@ impl crate::lsp::backend::Backend for Backend {
|
||||
// Execute the code if we have an executor context.
|
||||
// This function automatically executes if we should & updates the diagnostics if we got
|
||||
// errors.
|
||||
if self.execute(¶ms, &ast).await.is_err() {
|
||||
if self.execute(¶ms, &ast.into()).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -572,7 +640,7 @@ impl Backend {
|
||||
self.client.publish_diagnostics(params.uri.clone(), items, None).await;
|
||||
}
|
||||
|
||||
async fn execute(&self, params: &TextDocumentItem, ast: NodeRef<'_, crate::ast::types::Program>) -> Result<()> {
|
||||
async fn execute(&self, params: &TextDocumentItem, ast: &Program) -> Result<()> {
|
||||
// Check if we can execute.
|
||||
if !self.can_execute().await {
|
||||
return Ok(());
|
||||
@ -589,17 +657,15 @@ impl Backend {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut id_generator = IdGenerator::default();
|
||||
let mut exec_state = ExecState::default();
|
||||
|
||||
// Clear the scene, before we execute so it's not fugly as shit.
|
||||
executor_ctx
|
||||
.engine
|
||||
.clear_scene(&mut id_generator, SourceRange::default())
|
||||
.clear_scene(&mut exec_state.id_generator, SourceRange::default())
|
||||
.await?;
|
||||
|
||||
let exec_state = match executor_ctx.run(ast, None, id_generator, None).await {
|
||||
Ok(exec_state) => exec_state,
|
||||
Err(err) => {
|
||||
if let Err(err) = executor_ctx.run(ast, &mut exec_state).await {
|
||||
self.memory_map.remove(params.uri.as_str());
|
||||
self.add_to_diagnostics(params, &[err], false).await;
|
||||
|
||||
@ -607,7 +673,6 @@ impl Backend {
|
||||
// string.
|
||||
return Err(anyhow::anyhow!("failed to execute code"));
|
||||
}
|
||||
};
|
||||
|
||||
self.memory_map
|
||||
.insert(params.uri.to_string(), exec_state.memory.clone());
|
||||
|
@ -12,6 +12,7 @@ pub(crate) mod parser_impl;
|
||||
pub const PIPE_SUBSTITUTION_OPERATOR: &str = "%";
|
||||
pub const PIPE_OPERATOR: &str = "|>";
|
||||
|
||||
#[cfg(test)]
|
||||
/// Parse the given KCL code into an AST. This is the top-level.
|
||||
pub fn top_level_parse(code: &str) -> Result<Node<Program>, KclError> {
|
||||
let module_id = ModuleId::default();
|
||||
|
@ -9,7 +9,6 @@ use serde::{Deserialize, Serialize};
|
||||
use validator::{Validate, ValidateRange};
|
||||
|
||||
const DEFAULT_THEME_COLOR: f64 = 264.5;
|
||||
pub const DEFAULT_PROJECT_KCL_FILE: &str = "main.kcl";
|
||||
const DEFAULT_PROJECT_NAME_TEMPLATE: &str = "project-$nnn";
|
||||
|
||||
/// High level configuration.
|
||||
|
@ -92,7 +92,8 @@ async fn execute(test_name: &str, render_to_png: bool) {
|
||||
};
|
||||
|
||||
// Run the program.
|
||||
let exec_res = crate::test_server::execute_and_snapshot_ast(ast, crate::settings::types::UnitLength::Mm).await;
|
||||
let exec_res =
|
||||
crate::test_server::execute_and_snapshot_ast(ast.into(), crate::settings::types::UnitLength::Mm).await;
|
||||
match exec_res {
|
||||
Ok((program_memory, png)) => {
|
||||
if render_to_png {
|
||||
|
@ -4,7 +4,7 @@ use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
ast::types::{BodyItem, Expr, FunctionExpression, Node, Program},
|
||||
ast::types::{FunctionExpression, Program},
|
||||
docs::{StdLibFn, StdLibFnData},
|
||||
};
|
||||
|
||||
@ -77,18 +77,3 @@ impl Serialize for Box<dyn KclStdLibFn> {
|
||||
self.to_json().unwrap().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a KCL program. Expect it to have a single body item, which is a function.
|
||||
/// Return the program and its single function.
|
||||
/// Return None if those expectations aren't met.
|
||||
pub fn extract_function(source: &str) -> Option<(Node<Program>, crate::ast::types::BoxNode<FunctionExpression>)> {
|
||||
let src = crate::parser::top_level_parse(source).ok()?;
|
||||
assert_eq!(src.body.len(), 1);
|
||||
let BodyItem::ExpressionStatement(expr) = src.body.last()? else {
|
||||
panic!("expected expression statement");
|
||||
};
|
||||
let Expr::FunctionExpression(function) = expr.expression.clone() else {
|
||||
panic!("expected function expr");
|
||||
};
|
||||
Some((src, function))
|
||||
}
|
||||
|
@ -48,8 +48,6 @@ pub type StdFn = fn(
|
||||
Args,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<KclValue, KclError>> + Send + '_>>;
|
||||
|
||||
pub type FnMap = HashMap<String, StdFn>;
|
||||
|
||||
lazy_static! {
|
||||
static ref CORE_FNS: Vec<Box<dyn StdLibFn>> = vec![
|
||||
Box::new(LegLen),
|
||||
|
@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize};
|
||||
#[ts(export)]
|
||||
pub struct Uint(f64);
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Uint {
|
||||
pub fn new(value: f64) -> Self {
|
||||
if value < 0.0 {
|
||||
|
@ -53,20 +53,6 @@ pub fn delta(from_angle: Angle, to_angle: Angle) -> Angle {
|
||||
Angle::default()
|
||||
}
|
||||
|
||||
pub fn clockwise_sign(points: &[Point2d]) -> i32 {
|
||||
let mut sum = 0.0;
|
||||
for i in 0..points.len() {
|
||||
let current_point = points[i];
|
||||
let next_point = points[(i + 1) % points.len()];
|
||||
sum += (next_point.x - current_point.x) * (next_point.y + current_point.y);
|
||||
}
|
||||
if sum >= 0.0 {
|
||||
1
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn normalize_rad(angle: f64) -> f64 {
|
||||
let draft = angle % (2.0 * PI);
|
||||
if draft < 0.0 {
|
||||
@ -76,32 +62,6 @@ pub fn normalize_rad(angle: f64) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the distance between two points.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use kcl_lib::executor::Point2d;
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// kcl_lib::std::utils::distance_between_points(Point2d::ZERO, Point2d { x: 0.0, y: 5.0 }),
|
||||
/// 5.0
|
||||
/// );
|
||||
/// assert_eq!(
|
||||
/// kcl_lib::std::utils::distance_between_points(Point2d::ZERO, Point2d { x: 3.0, y: 4.0 }),
|
||||
/// 5.0
|
||||
/// );
|
||||
/// ```
|
||||
#[allow(dead_code)]
|
||||
pub fn distance_between_points(point_a: Point2d, point_b: Point2d) -> f64 {
|
||||
let x1 = point_a.x;
|
||||
let y1 = point_a.y;
|
||||
let x2 = point_b.x;
|
||||
let y2 = point_b.y;
|
||||
|
||||
((y2 - y1).powi(2) + (x2 - x1).powi(2)).sqrt()
|
||||
}
|
||||
|
||||
pub fn calculate_intersection_of_two_lines(line1: &[Point2d; 2], line2_angle: f64, line2_point: Point2d) -> Point2d {
|
||||
let line2_point_b = Point2d {
|
||||
x: line2_point.x + f64::cos(line2_angle.to_radians()) * 10.0,
|
||||
@ -563,6 +523,7 @@ pub struct TangentialArcInfoInput {
|
||||
}
|
||||
|
||||
/// Structure to hold the output data from calculating tangential arc information.
|
||||
#[allow(dead_code)]
|
||||
pub struct TangentialArcInfoOutput {
|
||||
/// The center point of the arc.
|
||||
pub center: Coords2d,
|
||||
|
@ -1,9 +1,9 @@
|
||||
//! Types used to send data to the test server.
|
||||
|
||||
use crate::{
|
||||
ast::types::{Node, Program},
|
||||
executor::{new_zoo_client, ExecutorContext, ExecutorSettings, IdGenerator, ProgramMemory},
|
||||
executor::{new_zoo_client, ExecutorContext, ExecutorSettings, ProgramMemory},
|
||||
settings::types::UnitLength,
|
||||
ExecState, Program,
|
||||
};
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
@ -17,14 +17,14 @@ pub struct RequestBody {
|
||||
/// This returns the bytes of the snapshot.
|
||||
pub async fn execute_and_snapshot(code: &str, units: UnitLength) -> anyhow::Result<image::DynamicImage> {
|
||||
let ctx = new_context(units, true).await?;
|
||||
let program = crate::parser::top_level_parse(code)?;
|
||||
let program = Program::parse(code)?;
|
||||
do_execute_and_snapshot(&ctx, program).await.map(|(_state, snap)| snap)
|
||||
}
|
||||
|
||||
/// Executes a kcl program and takes a snapshot of the result.
|
||||
/// This returns the bytes of the snapshot.
|
||||
pub async fn execute_and_snapshot_ast(
|
||||
ast: Node<Program>,
|
||||
ast: Program,
|
||||
units: UnitLength,
|
||||
) -> anyhow::Result<(ProgramMemory, image::DynamicImage)> {
|
||||
let ctx = new_context(units, true).await?;
|
||||
@ -35,15 +35,16 @@ pub async fn execute_and_snapshot_ast(
|
||||
|
||||
pub async fn execute_and_snapshot_no_auth(code: &str, units: UnitLength) -> anyhow::Result<image::DynamicImage> {
|
||||
let ctx = new_context(units, false).await?;
|
||||
let program = crate::parser::top_level_parse(code)?;
|
||||
let program = Program::parse(code)?;
|
||||
do_execute_and_snapshot(&ctx, program).await.map(|(_state, snap)| snap)
|
||||
}
|
||||
|
||||
async fn do_execute_and_snapshot(
|
||||
ctx: &ExecutorContext,
|
||||
program: Node<Program>,
|
||||
program: Program,
|
||||
) -> anyhow::Result<(crate::executor::ExecState, image::DynamicImage)> {
|
||||
let (exec_state, snapshot) = ctx.execute_and_prepare(&program, IdGenerator::default(), None).await?;
|
||||
let mut exec_state = ExecState::default();
|
||||
let snapshot = ctx.execute_and_prepare(&program, &mut exec_state).await?;
|
||||
|
||||
// Create a temporary file to write the output to.
|
||||
let output_file = std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
|
||||
|
@ -1,13 +1,15 @@
|
||||
//! An implementation of threads that works in wasm with promises and other platforms with tokio.
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod local;
|
||||
mod local;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub use local::JoinHandle;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(not(test))]
|
||||
pub mod wasm;
|
||||
mod wasm;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(not(test))]
|
||||
|
@ -1,18 +1,10 @@
|
||||
//! Wasm bindings for `kcl`.
|
||||
|
||||
use std::{
|
||||
str::FromStr,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use std::{str::FromStr, sync::Arc};
|
||||
|
||||
use futures::stream::TryStreamExt;
|
||||
use gloo_utils::format::JsValueSerdeExt;
|
||||
use kcl_lib::{
|
||||
ast::types::{ModuleId, Node, Program},
|
||||
coredump::CoreDump,
|
||||
engine::EngineManager,
|
||||
executor::ExecutorSettings,
|
||||
};
|
||||
use kcl_lib::{CoreDump, EngineManager, ExecState, ModuleId, Program};
|
||||
use tower_lsp::{LspService, Server};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
@ -23,54 +15,32 @@ pub async fn execute_wasm(
|
||||
memory_str: &str,
|
||||
id_generator_str: &str,
|
||||
units: &str,
|
||||
engine_manager: kcl_lib::engine::conn_wasm::EngineCommandManager,
|
||||
fs_manager: kcl_lib::fs::wasm::FileSystemManager,
|
||||
engine_manager: kcl_lib::wasm_engine::EngineCommandManager,
|
||||
fs_manager: kcl_lib::wasm_engine::FileSystemManager,
|
||||
project_directory: Option<String>,
|
||||
is_mock: bool,
|
||||
) -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
// deserialize the ast from a stringified json
|
||||
|
||||
let program: Node<Program> = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||
let memory: kcl_lib::executor::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
|
||||
let id_generator: kcl_lib::executor::IdGenerator =
|
||||
serde_json::from_str(id_generator_str).map_err(|e| e.to_string())?;
|
||||
let units = kcl_lib::settings::types::UnitLength::from_str(units).map_err(|e| e.to_string())?;
|
||||
let program: Program = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||
let memory: kcl_lib::exec::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
|
||||
let id_generator: kcl_lib::exec::IdGenerator = serde_json::from_str(id_generator_str).map_err(|e| e.to_string())?;
|
||||
|
||||
let engine: std::sync::Arc<Box<dyn kcl_lib::engine::EngineManager>> = if is_mock {
|
||||
Arc::new(Box::new(
|
||||
kcl_lib::engine::conn_mock::EngineConnection::new()
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
))
|
||||
let units = kcl_lib::UnitLength::from_str(units).map_err(|e| e.to_string())?;
|
||||
let ctx = if is_mock {
|
||||
kcl_lib::ExecutorContext::new_mock(fs_manager, units).await?
|
||||
} else {
|
||||
Arc::new(Box::new(
|
||||
kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
))
|
||||
};
|
||||
let fs = Arc::new(kcl_lib::fs::FileManager::new(fs_manager));
|
||||
let context_type = if is_mock {
|
||||
kcl_lib::executor::ContextType::Mock
|
||||
} else {
|
||||
kcl_lib::executor::ContextType::Live
|
||||
};
|
||||
let ctx = kcl_lib::executor::ExecutorContext {
|
||||
engine,
|
||||
fs,
|
||||
stdlib: std::sync::Arc::new(kcl_lib::std::StdLib::new()),
|
||||
settings: ExecutorSettings {
|
||||
units,
|
||||
..Default::default()
|
||||
},
|
||||
context_type,
|
||||
kcl_lib::ExecutorContext::new(engine_manager, fs_manager, units).await?
|
||||
};
|
||||
|
||||
let exec_state = ctx
|
||||
.run(&program, Some(memory), id_generator, project_directory)
|
||||
.await
|
||||
.map_err(String::from)?;
|
||||
let mut exec_state = ExecState {
|
||||
memory,
|
||||
id_generator,
|
||||
project_directory,
|
||||
..ExecState::default()
|
||||
};
|
||||
|
||||
ctx.run(&program, &mut exec_state).await.map_err(String::from)?;
|
||||
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
// gloo-serialize crate instead.
|
||||
@ -84,7 +54,7 @@ pub async fn execute_wasm(
|
||||
pub async fn kcl_lint(program_str: &str) -> Result<JsValue, JsValue> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let program: Node<Program> = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||
let program: Program = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||
let mut findings = vec![];
|
||||
for discovered_finding in program.lint_all().into_iter().flatten() {
|
||||
findings.push(discovered_finding);
|
||||
@ -96,16 +66,16 @@ pub async fn kcl_lint(program_str: &str) -> Result<JsValue, JsValue> {
|
||||
// wasm_bindgen wrapper for creating default planes
|
||||
#[wasm_bindgen]
|
||||
pub async fn make_default_planes(
|
||||
engine_manager: kcl_lib::engine::conn_wasm::EngineCommandManager,
|
||||
engine_manager: kcl_lib::wasm_engine::EngineCommandManager,
|
||||
) -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
// deserialize the ast from a stringified json
|
||||
|
||||
let engine = kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
||||
let engine = kcl_lib::wasm_engine::EngineConnection::new(engine_manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
let default_planes = engine
|
||||
.new_default_planes(&mut kcl_lib::executor::IdGenerator::default(), Default::default())
|
||||
.new_default_planes(&mut kcl_lib::exec::IdGenerator::default(), Default::default())
|
||||
.await
|
||||
.map_err(String::from)?;
|
||||
|
||||
@ -117,13 +87,13 @@ pub async fn make_default_planes(
|
||||
// wasm_bindgen wrapper for modifying the grid
|
||||
#[wasm_bindgen]
|
||||
pub async fn modify_grid(
|
||||
engine_manager: kcl_lib::engine::conn_wasm::EngineCommandManager,
|
||||
engine_manager: kcl_lib::wasm_engine::EngineCommandManager,
|
||||
hidden: bool,
|
||||
) -> Result<(), String> {
|
||||
console_error_panic_hook::set_once();
|
||||
// deserialize the ast from a stringified json
|
||||
|
||||
let engine = kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
||||
let engine = kcl_lib::wasm_engine::EngineConnection::new(engine_manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
engine.modify_grid(hidden).await.map_err(String::from)?;
|
||||
@ -134,7 +104,7 @@ pub async fn modify_grid(
|
||||
// wasm_bindgen wrapper for execute
|
||||
#[wasm_bindgen]
|
||||
pub async fn modify_ast_for_sketch_wasm(
|
||||
manager: kcl_lib::engine::conn_wasm::EngineCommandManager,
|
||||
manager: kcl_lib::wasm_engine::EngineCommandManager,
|
||||
program_str: &str,
|
||||
sketch_name: &str,
|
||||
plane_type: &str,
|
||||
@ -142,19 +112,18 @@ pub async fn modify_ast_for_sketch_wasm(
|
||||
) -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
// deserialize the ast from a stringified json
|
||||
let mut program: Node<Program> = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||
let mut program: Program = serde_json::from_str(program_str).map_err(|e| e.to_string())?;
|
||||
|
||||
let plane: kcl_lib::executor::PlaneType = serde_json::from_str(plane_type).map_err(|e| e.to_string())?;
|
||||
let plane: kcl_lib::exec::PlaneType = serde_json::from_str(plane_type).map_err(|e| e.to_string())?;
|
||||
|
||||
let engine: Arc<Box<dyn EngineManager>> = Arc::new(Box::new(
|
||||
kcl_lib::engine::conn_wasm::EngineConnection::new(manager)
|
||||
kcl_lib::wasm_engine::EngineConnection::new(manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
));
|
||||
|
||||
let module_id = ModuleId::default();
|
||||
let _ = kcl_lib::ast::modify::modify_ast_for_sketch(
|
||||
let _ = kcl_lib::modify_ast_for_sketch(
|
||||
&engine,
|
||||
&mut program,
|
||||
module_id,
|
||||
@ -196,7 +165,7 @@ pub fn lexer_wasm(js: &str) -> Result<JsValue, JsError> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let module_id = ModuleId::default();
|
||||
let tokens = kcl_lib::token::lexer(js, module_id).map_err(JsError::from)?;
|
||||
let tokens = kcl_lib::lexer(js, module_id).map_err(JsError::from)?;
|
||||
Ok(JsValue::from_serde(&tokens)?)
|
||||
}
|
||||
|
||||
@ -204,10 +173,7 @@ pub fn lexer_wasm(js: &str) -> Result<JsValue, JsError> {
|
||||
pub fn parse_wasm(js: &str) -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let module_id = ModuleId::default();
|
||||
let tokens = kcl_lib::token::lexer(js, module_id).map_err(String::from)?;
|
||||
let parser = kcl_lib::parser::Parser::new(tokens);
|
||||
let program = parser.ast().map_err(String::from)?;
|
||||
let program = Program::parse(js).map_err(String::from)?;
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
// gloo-serialize crate instead.
|
||||
JsValue::from_serde(&program).map_err(|e| e.to_string())
|
||||
@ -219,19 +185,15 @@ pub fn parse_wasm(js: &str) -> Result<JsValue, String> {
|
||||
pub fn recast_wasm(json_str: &str) -> Result<JsValue, JsError> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
// deserialize the ast from a stringified json
|
||||
let program: kcl_lib::ast::types::Program = serde_json::from_str(json_str).map_err(JsError::from)?;
|
||||
|
||||
// Use the default options until we integrate into the UI the ability to change them.
|
||||
let result = program.recast(&Default::default(), 0);
|
||||
Ok(JsValue::from_serde(&result)?)
|
||||
let program: Program = serde_json::from_str(json_str).map_err(JsError::from)?;
|
||||
Ok(JsValue::from_serde(&program.recast())?)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct ServerConfig {
|
||||
into_server: js_sys::AsyncIterator,
|
||||
from_server: web_sys::WritableStream,
|
||||
fs: kcl_lib::fs::wasm::FileSystemManager,
|
||||
fs: kcl_lib::wasm_engine::FileSystemManager,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
@ -240,7 +202,7 @@ impl ServerConfig {
|
||||
pub fn new(
|
||||
into_server: js_sys::AsyncIterator,
|
||||
from_server: web_sys::WritableStream,
|
||||
fs: kcl_lib::fs::wasm::FileSystemManager,
|
||||
fs: kcl_lib::wasm_engine::FileSystemManager,
|
||||
) -> Self {
|
||||
Self {
|
||||
into_server,
|
||||
@ -260,7 +222,7 @@ impl ServerConfig {
|
||||
#[wasm_bindgen]
|
||||
pub async fn kcl_lsp_run(
|
||||
config: ServerConfig,
|
||||
engine_manager: Option<kcl_lib::engine::conn_wasm::EngineCommandManager>,
|
||||
engine_manager: Option<kcl_lib::wasm_engine::EngineCommandManager>,
|
||||
units: &str,
|
||||
token: String,
|
||||
baseurl: String,
|
||||
@ -273,74 +235,37 @@ pub async fn kcl_lsp_run(
|
||||
fs,
|
||||
} = config;
|
||||
|
||||
let stdlib = kcl_lib::std::StdLib::new();
|
||||
let stdlib_completions = kcl_lib::lsp::kcl::get_completions_from_stdlib(&stdlib).map_err(|e| e.to_string())?;
|
||||
let stdlib_signatures = kcl_lib::lsp::kcl::get_signatures_from_stdlib(&stdlib).map_err(|e| e.to_string())?;
|
||||
|
||||
let mut zoo_client = kittycad::Client::new(token);
|
||||
zoo_client.set_base_url(baseurl.as_str());
|
||||
|
||||
let file_manager = Arc::new(kcl_lib::fs::FileManager::new(fs));
|
||||
|
||||
let executor_ctx = if let Some(engine_manager) = engine_manager {
|
||||
let units = kcl_lib::settings::types::UnitLength::from_str(units).map_err(|e| e.to_string())?;
|
||||
let engine = kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
Some(kcl_lib::executor::ExecutorContext {
|
||||
engine: Arc::new(Box::new(engine)),
|
||||
fs: file_manager.clone(),
|
||||
stdlib: std::sync::Arc::new(stdlib),
|
||||
settings: ExecutorSettings {
|
||||
units,
|
||||
..Default::default()
|
||||
},
|
||||
context_type: kcl_lib::executor::ContextType::Live,
|
||||
})
|
||||
let units = kcl_lib::UnitLength::from_str(units).map_err(|e| e.to_string())?;
|
||||
Some(kcl_lib::ExecutorContext::new(engine_manager, fs.clone(), units).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut zoo_client = kittycad::Client::new(token);
|
||||
zoo_client.set_base_url(baseurl.as_str());
|
||||
|
||||
// Check if we can send telememtry for this user.
|
||||
let privacy_settings = match zoo_client.users().get_privacy_settings().await {
|
||||
Ok(privacy_settings) => privacy_settings,
|
||||
let can_send_telemetry = match zoo_client.users().get_privacy_settings().await {
|
||||
Ok(privacy_settings) => privacy_settings.can_train_on_data,
|
||||
Err(err) => {
|
||||
// In the case of dev we don't always have a sub set, but prod we should.
|
||||
if err
|
||||
.to_string()
|
||||
.contains("The modeling app subscription type is missing.")
|
||||
{
|
||||
kittycad::types::PrivacySettings {
|
||||
can_train_on_data: true,
|
||||
}
|
||||
true
|
||||
} else {
|
||||
return Err(err.to_string().into());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let (service, socket) = LspService::build(|client| kcl_lib::lsp::kcl::Backend {
|
||||
client,
|
||||
fs: file_manager,
|
||||
workspace_folders: Default::default(),
|
||||
stdlib_completions,
|
||||
stdlib_signatures,
|
||||
token_map: Default::default(),
|
||||
ast_map: Default::default(),
|
||||
memory_map: Default::default(),
|
||||
code_map: Default::default(),
|
||||
diagnostics_map: Default::default(),
|
||||
symbols_map: Default::default(),
|
||||
semantic_tokens_map: Default::default(),
|
||||
zoo_client,
|
||||
can_send_telemetry: privacy_settings.can_train_on_data,
|
||||
can_execute: Arc::new(tokio::sync::RwLock::new(executor_ctx.is_some())),
|
||||
executor_ctx: Arc::new(tokio::sync::RwLock::new(executor_ctx)),
|
||||
|
||||
is_initialized: Default::default(),
|
||||
let (service, socket) = LspService::build(|client| {
|
||||
kcl_lib::KclLspBackend::new_wasm(client, executor_ctx, fs, zoo_client, can_send_telemetry).unwrap()
|
||||
})
|
||||
.custom_method("kcl/updateUnits", kcl_lib::lsp::kcl::Backend::update_units)
|
||||
.custom_method("kcl/updateCanExecute", kcl_lib::lsp::kcl::Backend::update_can_execute)
|
||||
.custom_method("kcl/updateUnits", kcl_lib::KclLspBackend::update_units)
|
||||
.custom_method("kcl/updateCanExecute", kcl_lib::KclLspBackend::update_can_execute)
|
||||
.finish();
|
||||
|
||||
let input = wasm_bindgen_futures::stream::JsStream::from(into_server);
|
||||
@ -383,39 +308,21 @@ pub async fn copilot_lsp_run(config: ServerConfig, token: String, baseurl: Strin
|
||||
let mut zoo_client = kittycad::Client::new(token);
|
||||
zoo_client.set_base_url(baseurl.as_str());
|
||||
|
||||
let file_manager = Arc::new(kcl_lib::fs::FileManager::new(fs));
|
||||
|
||||
let (service, socket) = LspService::build(|client| kcl_lib::lsp::copilot::Backend {
|
||||
client,
|
||||
fs: file_manager,
|
||||
workspace_folders: Default::default(),
|
||||
code_map: Default::default(),
|
||||
editor_info: Arc::new(RwLock::new(kcl_lib::lsp::copilot::types::CopilotEditorInfo::default())),
|
||||
cache: Arc::new(kcl_lib::lsp::copilot::cache::CopilotCache::new()),
|
||||
telemetry: Default::default(),
|
||||
zoo_client,
|
||||
|
||||
is_initialized: Default::default(),
|
||||
diagnostics_map: Default::default(),
|
||||
dev_mode: if baseurl == "https://api.dev.zoo.dev" {
|
||||
let dev_mode = if baseurl == "https://api.dev.zoo.dev" {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
},
|
||||
})
|
||||
.custom_method("copilot/setEditorInfo", kcl_lib::lsp::copilot::Backend::set_editor_info)
|
||||
};
|
||||
|
||||
let (service, socket) =
|
||||
LspService::build(|client| kcl_lib::CopilotLspBackend::new_wasm(client, fs, zoo_client, dev_mode))
|
||||
.custom_method("copilot/setEditorInfo", kcl_lib::CopilotLspBackend::set_editor_info)
|
||||
.custom_method(
|
||||
"copilot/getCompletions",
|
||||
kcl_lib::lsp::copilot::Backend::get_completions_cycling,
|
||||
)
|
||||
.custom_method(
|
||||
"copilot/notifyAccepted",
|
||||
kcl_lib::lsp::copilot::Backend::accept_completion,
|
||||
)
|
||||
.custom_method(
|
||||
"copilot/notifyRejected",
|
||||
kcl_lib::lsp::copilot::Backend::reject_completions,
|
||||
kcl_lib::CopilotLspBackend::get_completions_cycling,
|
||||
)
|
||||
.custom_method("copilot/notifyAccepted", kcl_lib::CopilotLspBackend::accept_completion)
|
||||
.custom_method("copilot/notifyRejected", kcl_lib::CopilotLspBackend::reject_completions)
|
||||
.finish();
|
||||
|
||||
let input = wasm_bindgen_futures::stream::JsStream::from(into_server);
|
||||
@ -442,7 +349,7 @@ pub async fn copilot_lsp_run(config: ServerConfig, token: String, baseurl: Strin
|
||||
pub fn is_points_ccw(points: &[f64]) -> i32 {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
kcl_lib::std::utils::is_points_ccw_wasm(points)
|
||||
kcl_lib::std_utils::is_points_ccw_wasm(points)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
@ -479,7 +386,7 @@ pub fn get_tangential_arc_to_info(
|
||||
) -> TangentialArcInfoOutputWasm {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let result = kcl_lib::std::utils::get_tangential_arc_to_info(kcl_lib::std::utils::TangentialArcInfoInput {
|
||||
let result = kcl_lib::std_utils::get_tangential_arc_to_info(kcl_lib::std_utils::TangentialArcInfoInput {
|
||||
arc_start_point: [arc_start_point_x, arc_start_point_y],
|
||||
arc_end_point: [arc_end_point_x, arc_end_point_y],
|
||||
tan_previous_point: [tan_previous_point_x, tan_previous_point_y],
|
||||
@ -503,7 +410,7 @@ pub fn get_tangential_arc_to_info(
|
||||
pub fn program_memory_init() -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let memory = kcl_lib::executor::ProgramMemory::default();
|
||||
let memory = kcl_lib::exec::ProgramMemory::default();
|
||||
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
// gloo-serialize crate instead.
|
||||
@ -512,10 +419,10 @@ pub fn program_memory_init() -> Result<JsValue, String> {
|
||||
|
||||
/// Get a coredump.
|
||||
#[wasm_bindgen]
|
||||
pub async fn coredump(core_dump_manager: kcl_lib::coredump::wasm::CoreDumpManager) -> Result<JsValue, String> {
|
||||
pub async fn coredump(core_dump_manager: kcl_lib::wasm_engine::CoreDumpManager) -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let core_dumper = kcl_lib::coredump::wasm::CoreDumper::new(core_dump_manager);
|
||||
let core_dumper = kcl_lib::wasm_engine::CoreDumper::new(core_dump_manager);
|
||||
let dump = core_dumper.dump().await.map_err(|e| e.to_string())?;
|
||||
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
@ -528,7 +435,7 @@ pub async fn coredump(core_dump_manager: kcl_lib::coredump::wasm::CoreDumpManage
|
||||
pub fn default_app_settings() -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let settings = kcl_lib::settings::types::Configuration::default();
|
||||
let settings = kcl_lib::Configuration::default();
|
||||
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
// gloo-serialize crate instead.
|
||||
@ -540,8 +447,7 @@ pub fn default_app_settings() -> Result<JsValue, String> {
|
||||
pub fn parse_app_settings(toml_str: &str) -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let settings = kcl_lib::settings::types::Configuration::backwards_compatible_toml_parse(&toml_str)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let settings = kcl_lib::Configuration::backwards_compatible_toml_parse(&toml_str).map_err(|e| e.to_string())?;
|
||||
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
// gloo-serialize crate instead.
|
||||
@ -553,7 +459,7 @@ pub fn parse_app_settings(toml_str: &str) -> Result<JsValue, String> {
|
||||
pub fn default_project_settings() -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let settings = kcl_lib::settings::types::project::ProjectConfiguration::default();
|
||||
let settings = kcl_lib::ProjectConfiguration::default();
|
||||
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
// gloo-serialize crate instead.
|
||||
@ -565,8 +471,8 @@ pub fn default_project_settings() -> Result<JsValue, String> {
|
||||
pub fn parse_project_settings(toml_str: &str) -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let settings = kcl_lib::settings::types::project::ProjectConfiguration::backwards_compatible_toml_parse(&toml_str)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let settings =
|
||||
kcl_lib::ProjectConfiguration::backwards_compatible_toml_parse(&toml_str).map_err(|e| e.to_string())?;
|
||||
|
||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
||||
// gloo-serialize crate instead.
|
||||
@ -578,7 +484,7 @@ pub fn parse_project_settings(toml_str: &str) -> Result<JsValue, String> {
|
||||
pub fn serialize_project_settings(val: JsValue) -> Result<JsValue, String> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let config: kcl_lib::settings::types::Configuration = val.into_serde().map_err(|e| e.to_string())?;
|
||||
let config: kcl_lib::Configuration = val.into_serde().map_err(|e| e.to_string())?;
|
||||
|
||||
let toml_str = toml::to_string_pretty(&config).map_err(|e| e.to_string())?;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use kcl_lib::{
|
||||
settings::types::UnitLength,
|
||||
test_server::{execute_and_snapshot, execute_and_snapshot_no_auth},
|
||||
UnitLength,
|
||||
};
|
||||
|
||||
/// The minimum permissible difference between asserted twenty-twenty images.
|
||||
|
@ -1,20 +1,17 @@
|
||||
use anyhow::Result;
|
||||
use kcl_lib::{
|
||||
ast::{
|
||||
modify::modify_ast_for_sketch,
|
||||
types::{ModuleId, Node, Program},
|
||||
},
|
||||
executor::{ExecutorContext, IdGenerator, KclValue, PlaneType, SourceRange},
|
||||
exec::{KclValue, PlaneType},
|
||||
modify_ast_for_sketch, ExecState, ExecutorContext, ModuleId, Program, SourceRange,
|
||||
};
|
||||
use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit, shared::Point3d, ModelingCmd};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
/// Setup the engine and parse code for an ast.
|
||||
async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Node<Program>, ModuleId, uuid::Uuid)> {
|
||||
let module_id = ModuleId::default();
|
||||
let program = kcl_lib::parser::parse(code, module_id)?;
|
||||
let ctx = kcl_lib::executor::ExecutorContext::new_with_default_client(Default::default()).await?;
|
||||
let exec_state = ctx.run(&program, None, IdGenerator::default(), None).await?;
|
||||
async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, ModuleId, uuid::Uuid)> {
|
||||
let program = Program::parse(code)?;
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()).await?;
|
||||
let mut exec_state = ExecState::default();
|
||||
ctx.run(&program, &mut exec_state).await?;
|
||||
|
||||
// We need to get the sketch ID.
|
||||
// Get the sketch ID from memory.
|
||||
@ -56,7 +53,7 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Node<Program>
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok((ctx, program, module_id, sketch_id))
|
||||
Ok((ctx, program, ModuleId::default(), sketch_id))
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
|
Reference in New Issue
Block a user