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(
 | 
			
		||||
            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?;
 | 
			
		||||
    let ctx = ExecutorContext::new_forwarded_mock(Arc::new(Box::new(
 | 
			
		||||
        crate::conn_mock_core::EngineConnection::new(ref_result).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,25 +657,22 @@ 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) => {
 | 
			
		||||
                self.memory_map.remove(params.uri.as_str());
 | 
			
		||||
                self.add_to_diagnostics(params, &[err], false).await;
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
                // Since we already published the diagnostics we don't really care about the error
 | 
			
		||||
                // string.
 | 
			
		||||
                return Err(anyhow::anyhow!("failed to execute code"));
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
            // Since we already published the diagnostics we don't really care about the error
 | 
			
		||||
            // 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,40 +308,22 @@ 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 dev_mode = if baseurl == "https://api.dev.zoo.dev" {
 | 
			
		||||
        true
 | 
			
		||||
    } else {
 | 
			
		||||
        false
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    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" {
 | 
			
		||||
            true
 | 
			
		||||
        } else {
 | 
			
		||||
            false
 | 
			
		||||
        },
 | 
			
		||||
    })
 | 
			
		||||
    .custom_method("copilot/setEditorInfo", kcl_lib::lsp::copilot::Backend::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,
 | 
			
		||||
    )
 | 
			
		||||
    .finish();
 | 
			
		||||
    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::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);
 | 
			
		||||
    let input = input
 | 
			
		||||
@ -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