Compare commits
	
		
			3 Commits
		
	
	
		
			jtran/test
			...
			angled-lin
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 58b9382990 | |||
| 0947d970a6 | |||
| e8769eb543 | 
| @ -8,6 +8,7 @@ description = "A new executor for KCL which compiles to Execution Plans" | |||||||
| [dependencies] | [dependencies] | ||||||
| image = { version = "0.24.7", default-features = false, features = ["png"] } | image = { version = "0.24.7", default-features = false, features = ["png"] } | ||||||
| kcl-lib = { path = "../kcl" } | kcl-lib = { path = "../kcl" } | ||||||
|  | kcl-macros = { path = "../kcl-macros/" } | ||||||
| kittycad = { workspace = true } | kittycad = { workspace = true } | ||||||
| kittycad-execution-plan = { workspace = true } | kittycad-execution-plan = { workspace = true } | ||||||
| kittycad-execution-plan-traits = { workspace = true } | kittycad-execution-plan-traits = { workspace = true } | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								src/wasm-lib/grackle/fixtures/tri_angledLineToX.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/wasm-lib/grackle/fixtures/tri_angledLineToX.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 91 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/wasm-lib/grackle/fixtures/tri_angledLineX.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/wasm-lib/grackle/fixtures/tri_angledLineX.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 77 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/wasm-lib/grackle/fixtures/zigzag_angledLine.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/wasm-lib/grackle/fixtures/zigzag_angledLine.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 76 KiB | 
| @ -43,7 +43,12 @@ impl EpBinding { | |||||||
|     /// Look up the given property of this binding. |     /// Look up the given property of this binding. | ||||||
|     pub fn property_of(&self, property: LiteralIdentifier) -> Result<&Self, CompileError> { |     pub fn property_of(&self, property: LiteralIdentifier) -> Result<&Self, CompileError> { | ||||||
|         match property { |         match property { | ||||||
|             LiteralIdentifier::Identifier(_) => todo!("Support identifier properties"), |             LiteralIdentifier::Identifier(ident) => { | ||||||
|  |               let EpBinding::Map { length_at: _, properties } = self else { | ||||||
|  |                 return Err(CompileError::CannotIndex) | ||||||
|  |               }; | ||||||
|  |               properties.get(&ident.name).ok_or(CompileError::CannotIndex) | ||||||
|  |             } | ||||||
|             LiteralIdentifier::Literal(litval) => match litval.value { |             LiteralIdentifier::Literal(litval) => match litval.value { | ||||||
|                 // Arrays can be indexed by integers. |                 // Arrays can be indexed by integers. | ||||||
|                 LiteralValue::IInteger(i) => match self { |                 LiteralValue::IInteger(i) => match self { | ||||||
|  | |||||||
| @ -11,6 +11,8 @@ use kcl_lib::{ | |||||||
|     ast, |     ast, | ||||||
|     ast::types::{BodyItem, FunctionExpressionParts, KclNone, LiteralValue, Program}, |     ast::types::{BodyItem, FunctionExpressionParts, KclNone, LiteralValue, Program}, | ||||||
| }; | }; | ||||||
|  | extern crate alloc; | ||||||
|  | use kcl_macros::parse_file; | ||||||
| use kcl_value_group::into_single_value; | use kcl_value_group::into_single_value; | ||||||
| use kittycad_execution_plan::{self as ep, Destination, Instruction}; | use kittycad_execution_plan::{self as ep, Destination, Instruction}; | ||||||
| use kittycad_execution_plan_traits as ept; | use kittycad_execution_plan_traits as ept; | ||||||
| @ -24,9 +26,11 @@ use self::{ | |||||||
| }; | }; | ||||||
|  |  | ||||||
| /// Execute a KCL program by compiling into an execution plan, then running that. | /// Execute a KCL program by compiling into an execution plan, then running that. | ||||||
| pub async fn execute(ast: Program, session: &mut Option<Session>) -> Result<ep::Memory, Error> { | /// Include a `prelude.kcl` inlined as a `Program` struct thanks to a proc_macro `parse!`. | ||||||
|  | /// This makes additional functions available to the user. | ||||||
|  | pub async fn execute(ast_user: Program, session: &mut Option<Session>) -> Result<ep::Memory, Error> { | ||||||
|     let mut planner = Planner::new(); |     let mut planner = Planner::new(); | ||||||
|     let (plan, _retval) = planner.build_plan(ast)?; |     let (plan, _retval) = planner.build_plan(ast_user)?; | ||||||
|     let mut mem = ep::Memory::default(); |     let mut mem = ep::Memory::default(); | ||||||
|     ep::execute(&mut mem, plan, session).await?; |     ep::execute(&mut mem, plan, session).await?; | ||||||
|     Ok(mem) |     Ok(mem) | ||||||
| @ -54,7 +58,9 @@ impl Planner { | |||||||
|  |  | ||||||
|     /// If successful, return the KCEP instructions for executing the given program. |     /// If successful, return the KCEP instructions for executing the given program. | ||||||
|     /// If the program is a function with a return, then it also returns the KCL function's return value. |     /// If the program is a function with a return, then it also returns the KCL function's return value. | ||||||
|     fn build_plan(&mut self, program: Program) -> Result<(Vec<Instruction>, Option<EpBinding>), CompileError> { |     fn build_plan(&mut self, ast_user: Program) -> Result<(Vec<Instruction>, Option<EpBinding>), CompileError> { | ||||||
|  |         let ast_prelude = parse_file!("./prelude.kcl"); | ||||||
|  |         let program = ast_prelude.merge(ast_user); | ||||||
|         program |         program | ||||||
|             .body |             .body | ||||||
|             .into_iter() |             .into_iter() | ||||||
|  | |||||||
| @ -32,23 +32,23 @@ impl<'a> Context<'a> { | |||||||
| /// Unary operator macro to quickly create new bindings. | /// Unary operator macro to quickly create new bindings. | ||||||
| macro_rules! define_unary { | macro_rules! define_unary { | ||||||
|   () => {}; |   () => {}; | ||||||
|   ($h:ident$( $r:ident)*) => { |   ($fn_name:ident$( $rest:ident)*) => { | ||||||
|     #[derive(Debug, Clone)] |     #[derive(Debug, Clone)] | ||||||
|     #[cfg_attr(test, derive(Eq, PartialEq))] |     #[cfg_attr(test, derive(Eq, PartialEq))] | ||||||
|     pub struct $h; |     pub struct $fn_name; | ||||||
|  |  | ||||||
|     impl Callable for $h { |     impl Callable for $fn_name { | ||||||
|         fn call(&self, ctx: &mut Context<'_>, mut args: Vec<EpBinding>) -> Result<EvalPlan, CompileError> { |         fn call(&self, ctx: &mut Context<'_>, mut args: Vec<EpBinding>) -> Result<EvalPlan, CompileError> { | ||||||
|             if args.len() > 1 { |             if args.len() > 1 { | ||||||
|                 return Err(CompileError::TooManyArgs { |                 return Err(CompileError::TooManyArgs { | ||||||
|                     fn_name: "$h".into(), |                     fn_name: "$fn_name".into(), | ||||||
|                     maximum: 1, |                     maximum: 1, | ||||||
|                     actual: args.len(), |                     actual: args.len(), | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             let not_enough_args = CompileError::NotEnoughArgs { |             let not_enough_args = CompileError::NotEnoughArgs { | ||||||
|                 fn_name: "$h".into(), |                 fn_name: "$fn_name".into(), | ||||||
|                 required: 1, |                 required: 1, | ||||||
|                 actual: args.len(), |                 actual: args.len(), | ||||||
|             }; |             }; | ||||||
| @ -61,7 +61,7 @@ macro_rules! define_unary { | |||||||
|             let instructions = vec![ |             let instructions = vec![ | ||||||
|               Instruction::UnaryArithmetic { |               Instruction::UnaryArithmetic { | ||||||
|                 arithmetic: UnaryArithmetic { |                 arithmetic: UnaryArithmetic { | ||||||
|                   operation: UnaryOperation::$h, |                   operation: UnaryOperation::$fn_name, | ||||||
|                   operand: Operand::Reference(arg0) |                   operand: Operand::Reference(arg0) | ||||||
|                 }, |                 }, | ||||||
|                 destination: Destination::Address(destination) |                 destination: Destination::Address(destination) | ||||||
| @ -75,7 +75,7 @@ macro_rules! define_unary { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     define_unary!($($r)*); |     define_unary!($($rest)*); | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -115,27 +115,27 @@ impl Callable for Id { | |||||||
| /// Binary operator macro to quickly create new bindings. | /// Binary operator macro to quickly create new bindings. | ||||||
| macro_rules! define_binary { | macro_rules! define_binary { | ||||||
|   () => {}; |   () => {}; | ||||||
|   ($h:ident$( $r:ident)*) => { |   ($fn_name:ident$( $rest:ident)*) => { | ||||||
|     #[derive(Debug, Clone)] |     #[derive(Debug, Clone)] | ||||||
|     #[cfg_attr(test, derive(Eq, PartialEq))] |     #[cfg_attr(test, derive(Eq, PartialEq))] | ||||||
|     pub struct $h; |     pub struct $fn_name; | ||||||
|  |  | ||||||
|     impl Callable for $h { |     impl Callable for $fn_name { | ||||||
|         fn call(&self, ctx: &mut Context<'_>, mut args: Vec<EpBinding>) -> Result<EvalPlan, CompileError> { |         fn call(&self, ctx: &mut Context<'_>, mut args: Vec<EpBinding>) -> Result<EvalPlan, CompileError> { | ||||||
|           let len = args.len(); |           let len = args.len(); | ||||||
|           if len > 2 { |           if len > 2 { | ||||||
|               return Err(CompileError::TooManyArgs { |               return Err(CompileError::TooManyArgs { | ||||||
|                   fn_name: "$h".into(), |                   fn_name: "$fn_name".into(), | ||||||
|                   maximum: 2, |                   maximum: 2, | ||||||
|                   actual: len, |                   actual: len, | ||||||
|               }); |               }); | ||||||
|           } |           } | ||||||
|           let not_enough_args = CompileError::NotEnoughArgs { |           let not_enough_args = CompileError::NotEnoughArgs { | ||||||
|               fn_name: "$h".into(), |               fn_name: "$fn_name".into(), | ||||||
|               required: 2, |               required: 2, | ||||||
|               actual: len, |               actual: len, | ||||||
|           }; |           }; | ||||||
|           const ERR: &str = "cannot use composite values (e.g. array) as arguments to $h"; |           const ERR: &str = "cannot use composite values (e.g. array) as arguments to $fn_name"; | ||||||
|           let EpBinding::Single(arg1) = args.pop().ok_or(not_enough_args.clone())? else { |           let EpBinding::Single(arg1) = args.pop().ok_or(not_enough_args.clone())? else { | ||||||
|               return Err(CompileError::InvalidOperand(ERR)); |               return Err(CompileError::InvalidOperand(ERR)); | ||||||
|           }; |           }; | ||||||
| @ -146,7 +146,7 @@ macro_rules! define_binary { | |||||||
|           Ok(EvalPlan { |           Ok(EvalPlan { | ||||||
|               instructions: vec![Instruction::BinaryArithmetic { |               instructions: vec![Instruction::BinaryArithmetic { | ||||||
|                   arithmetic: BinaryArithmetic { |                   arithmetic: BinaryArithmetic { | ||||||
|                       operation: BinaryOperation::$h, |                       operation: BinaryOperation::$fn_name, | ||||||
|                       operand0: Operand::Reference(arg0), |                       operand0: Operand::Reference(arg0), | ||||||
|                       operand1: Operand::Reference(arg1), |                       operand1: Operand::Reference(arg1), | ||||||
|                   }, |                   }, | ||||||
| @ -157,7 +157,7 @@ macro_rules! define_binary { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     define_binary!($($r)*); |     define_binary!($($rest)*); | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -1144,10 +1144,6 @@ async fn stdlib_cube_xline_yline() { | |||||||
|         |> close(%) |         |> close(%) | ||||||
|         |> extrude(100.0, %) |         |> extrude(100.0, %) | ||||||
|     "#; |     "#; | ||||||
|     kcvm_dbg( |  | ||||||
|         program, |  | ||||||
|         "/home/lee/Code/Zoo/modeling-api/execution-plan-debugger/cube_xyline.json", |  | ||||||
|     ); |  | ||||||
|     let (_plan, _scope, _last_address) = must_plan(program); |     let (_plan, _scope, _last_address) = must_plan(program); | ||||||
|  |  | ||||||
|     let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program)) |     let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program)) | ||||||
| @ -1442,3 +1438,154 @@ async fn cos_sin_pi() { | |||||||
|     // Constants don't live in memory. |     // Constants don't live in memory. | ||||||
|     assert_eq!(*z, constants::PI); |     assert_eq!(*z, constants::PI); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[tokio::test] | ||||||
|  | async fn kcl_prelude() { | ||||||
|  |     let program = " | ||||||
|  |         let the_answer_to_the_universe_is = hey_from_one_of_the_devs_of_the_past_i_wish_you_a_great_day_and_maybe_gave_you_a_little_smile_as_youve_found_this() | ||||||
|  |     "; | ||||||
|  |     let (_plan, scope, _) = must_plan(program); | ||||||
|  |     let Some(EpBinding::Single(the_answer_to_the_universe_is)) = scope.get("the_answer_to_the_universe_is") else { | ||||||
|  |         panic!( | ||||||
|  |             "Unexpected binding for variable 'the_answer_to_the_universe_is': {:?}", | ||||||
|  |             scope.get("the_answer_to_the_universe_is") | ||||||
|  |         ); | ||||||
|  |     }; | ||||||
|  |     let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program)) | ||||||
|  |         .ast() | ||||||
|  |         .unwrap(); | ||||||
|  |     let mem = crate::execute(ast, &mut None).await.unwrap(); | ||||||
|  |     use ept::ReadMemory; | ||||||
|  |     assert_eq!(*mem.get(the_answer_to_the_universe_is).unwrap(), Primitive::from(42i64)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[tokio::test] | ||||||
|  | async fn angled_line() { | ||||||
|  |     let program = r#" | ||||||
|  |     let zigzag = startSketchAt([0.0, 0.0], "test") | ||||||
|  |         |> angledLine({ angle: 45.0, length: 100 }, %, "") | ||||||
|  |         |> angledLine({ angle: 45.0 + 90.0, length: 100 }, %, "") | ||||||
|  |         |> angledLine({ angle: 45.0, length: 100 }, %, "") | ||||||
|  |         |> angledLine({ angle: 45.0 + 90.0, length: 100 }, %, "") | ||||||
|  |         |> close(%) | ||||||
|  |         |> extrude(100.0, %) | ||||||
|  |     "#; | ||||||
|  |     let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program)) | ||||||
|  |         .ast() | ||||||
|  |         .unwrap(); | ||||||
|  |     let mut client = Some(test_client().await); | ||||||
|  |     let mem = match crate::execute(ast, &mut client).await { | ||||||
|  |         Ok(mem) => mem, | ||||||
|  |         Err(e) => panic!("{e}"), | ||||||
|  |     }; | ||||||
|  |     use kittycad_modeling_cmds::{each_cmd, ok_response::OkModelingCmdResponse, ImageFormat}; | ||||||
|  |     let out = client | ||||||
|  |         .unwrap() | ||||||
|  |         .run_command( | ||||||
|  |             uuid::Uuid::new_v4().into(), | ||||||
|  |             kittycad_modeling_cmds::ModelingCmd::from(each_cmd::TakeSnapshot { | ||||||
|  |                 format: ImageFormat::Png, | ||||||
|  |             }), | ||||||
|  |         ) | ||||||
|  |         .await | ||||||
|  |         .unwrap(); | ||||||
|  |  | ||||||
|  |     let out = match out { | ||||||
|  |         OkModelingCmdResponse::TakeSnapshot(kittycad_modeling_cmds::output::TakeSnapshot { contents: b }) => b, | ||||||
|  |         other => panic!("wrong output: {other:?}"), | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     use image::io::Reader as ImageReader; | ||||||
|  |     let img = ImageReader::new(std::io::Cursor::new(out)) | ||||||
|  |         .with_guessed_format() | ||||||
|  |         .unwrap() | ||||||
|  |         .decode() | ||||||
|  |         .unwrap(); | ||||||
|  |     twenty_twenty::assert_image("fixtures/zigzag_angledLine.png", &img, 0.9999); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[tokio::test] | ||||||
|  | async fn angled_line_to_x() { | ||||||
|  |     let program = r#" | ||||||
|  |     let zigzag = startSketchAt([0.0, 0.0], "test") | ||||||
|  |         |> angledLineToX({ angle: toRadians(85.0), to: 300.0 }, %, "") | ||||||
|  |         |> angledLineToX({ angle: toRadians(35.0), to: 550.0 }, %, "") | ||||||
|  |         |> close(%) | ||||||
|  |         |> extrude(100.0, %) | ||||||
|  |     "#; | ||||||
|  |     let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program)) | ||||||
|  |         .ast() | ||||||
|  |         .unwrap(); | ||||||
|  |     let mut client = Some(test_client().await); | ||||||
|  |     let mem = match crate::execute(ast, &mut client).await { | ||||||
|  |         Ok(mem) => mem, | ||||||
|  |         Err(e) => panic!("{e}"), | ||||||
|  |     }; | ||||||
|  |     use kittycad_modeling_cmds::{each_cmd, ok_response::OkModelingCmdResponse, ImageFormat}; | ||||||
|  |     let out = client | ||||||
|  |         .unwrap() | ||||||
|  |         .run_command( | ||||||
|  |             uuid::Uuid::new_v4().into(), | ||||||
|  |             kittycad_modeling_cmds::ModelingCmd::from(each_cmd::TakeSnapshot { | ||||||
|  |                 format: ImageFormat::Png, | ||||||
|  |             }), | ||||||
|  |         ) | ||||||
|  |         .await | ||||||
|  |         .unwrap(); | ||||||
|  |  | ||||||
|  |     let out = match out { | ||||||
|  |         OkModelingCmdResponse::TakeSnapshot(kittycad_modeling_cmds::output::TakeSnapshot { contents: b }) => b, | ||||||
|  |         other => panic!("wrong output: {other:?}"), | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     use image::io::Reader as ImageReader; | ||||||
|  |     let img = ImageReader::new(std::io::Cursor::new(out)) | ||||||
|  |         .with_guessed_format() | ||||||
|  |         .unwrap() | ||||||
|  |         .decode() | ||||||
|  |         .unwrap(); | ||||||
|  |     twenty_twenty::assert_image("fixtures/tri_angledLineToX.png", &img, 0.9999); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[tokio::test] | ||||||
|  | async fn angled_line_x() { | ||||||
|  |     let program = r#" | ||||||
|  |     let zigzag = startSketchAt([0.0, 0.0], "test") | ||||||
|  |         |> angledLineX({ angle: toRadians(85.0), to: 300.0 }, %, "") | ||||||
|  |         |> angledLineX({ angle: toRadians(35.0), to: 550.0 }, %, "") | ||||||
|  |         |> close(%) | ||||||
|  |         |> extrude(100.0, %) | ||||||
|  |     "#; | ||||||
|  |     let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program)) | ||||||
|  |         .ast() | ||||||
|  |         .unwrap(); | ||||||
|  |     let mut client = Some(test_client().await); | ||||||
|  |     let mem = match crate::execute(ast, &mut client).await { | ||||||
|  |         Ok(mem) => mem, | ||||||
|  |         Err(e) => panic!("{e}"), | ||||||
|  |     }; | ||||||
|  |     use kittycad_modeling_cmds::{each_cmd, ok_response::OkModelingCmdResponse, ImageFormat}; | ||||||
|  |     let out = client | ||||||
|  |         .unwrap() | ||||||
|  |         .run_command( | ||||||
|  |             uuid::Uuid::new_v4().into(), | ||||||
|  |             kittycad_modeling_cmds::ModelingCmd::from(each_cmd::TakeSnapshot { | ||||||
|  |                 format: ImageFormat::Png, | ||||||
|  |             }), | ||||||
|  |         ) | ||||||
|  |         .await | ||||||
|  |         .unwrap(); | ||||||
|  |  | ||||||
|  |     let out = match out { | ||||||
|  |         OkModelingCmdResponse::TakeSnapshot(kittycad_modeling_cmds::output::TakeSnapshot { contents: b }) => b, | ||||||
|  |         other => panic!("wrong output: {other:?}"), | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     use image::io::Reader as ImageReader; | ||||||
|  |     let img = ImageReader::new(std::io::Cursor::new(out)) | ||||||
|  |         .with_guessed_format() | ||||||
|  |         .unwrap() | ||||||
|  |         .decode() | ||||||
|  |         .unwrap(); | ||||||
|  |     twenty_twenty::assert_image("fixtures/tri_angledLineX.png", &img, 0.9999); | ||||||
|  | } | ||||||
|  | |||||||
| @ -8,7 +8,6 @@ use syn::{parse_macro_input, LitStr}; | |||||||
| /// This macro takes exactly one argument: A string literal containing KCL. | /// This macro takes exactly one argument: A string literal containing KCL. | ||||||
| /// # Examples | /// # Examples | ||||||
| /// ``` | /// ``` | ||||||
| /// extern crate alloc; |  | ||||||
| /// use kcl_compile_macro::parse_kcl; | /// use kcl_compile_macro::parse_kcl; | ||||||
| /// let ast: kcl_lib::ast::types::Program = parse_kcl!("const y = 4"); | /// let ast: kcl_lib::ast::types::Program = parse_kcl!("const y = 4"); | ||||||
| /// ``` | /// ``` | ||||||
| @ -21,3 +20,14 @@ pub fn parse(input: TokenStream) -> TokenStream { | |||||||
|     let ast_struct = ast.bake(&Default::default()); |     let ast_struct = ast.bake(&Default::default()); | ||||||
|     quote!(#ast_struct).into() |     quote!(#ast_struct).into() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// Same as `parse!` but read in a file. | ||||||
|  | #[proc_macro] | ||||||
|  | pub fn parse_file(input: TokenStream) -> TokenStream { | ||||||
|  |     let file_name = parse_macro_input!(input as LitStr); | ||||||
|  |     let kcl_src = std::fs::read_to_string(file_name.value()).unwrap(); | ||||||
|  |     let tokens = kcl_lib::token::lexer(&kcl_src); | ||||||
|  |     let ast = kcl_lib::parser::Parser::new(tokens).ast().unwrap(); | ||||||
|  |     let ast_struct = ast.bake(&Default::default()); | ||||||
|  |     quote!(#ast_struct).into() | ||||||
|  | } | ||||||
|  | |||||||
| @ -351,6 +351,31 @@ impl Program { | |||||||
|  |  | ||||||
|         None |         None | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Merge two `Program`s together. | ||||||
|  |     pub fn merge(self, ast_other: Program) -> Program { | ||||||
|  |       let mut body_new: Vec<BodyItem> = vec![]; | ||||||
|  |       body_new.extend(self.body); | ||||||
|  |       body_new.extend(ast_other.body); | ||||||
|  |  | ||||||
|  |       let mut non_code_nodes_new: HashMap<usize, Vec<NonCodeNode>> = HashMap::new(); | ||||||
|  |       non_code_nodes_new.extend(self.non_code_meta.non_code_nodes); | ||||||
|  |       non_code_nodes_new.extend(ast_other.non_code_meta.non_code_nodes); | ||||||
|  |  | ||||||
|  |       let mut start_new: Vec<NonCodeNode> = vec![]; | ||||||
|  |       start_new.extend(self.non_code_meta.start); | ||||||
|  |       start_new.extend(ast_other.non_code_meta.start); | ||||||
|  |  | ||||||
|  |       Program { | ||||||
|  |         start: self.start, | ||||||
|  |         end: self.end + (ast_other.end - ast_other.start), | ||||||
|  |         body: body_new, | ||||||
|  |         non_code_meta: NonCodeMeta { | ||||||
|  |           non_code_nodes: non_code_nodes_new, | ||||||
|  |           start: start_new, | ||||||
|  |         }, | ||||||
|  |       } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| pub trait ValueMeta { | pub trait ValueMeta { | ||||||
|  | |||||||
| @ -958,7 +958,7 @@ impl TryFrom<Token> for Identifier { | |||||||
|             Err(KclError::Syntax(KclErrorDetails { |             Err(KclError::Syntax(KclErrorDetails { | ||||||
|                 source_ranges: token.as_source_ranges(), |                 source_ranges: token.as_source_ranges(), | ||||||
|                 message: format!( |                 message: format!( | ||||||
|                     "Cannot assign a variable to a reserved keyword: {}", |                     "Word Cannot assign a variable to a reserved keyword: {}", | ||||||
|                     token.value.as_str() |                     token.value.as_str() | ||||||
|                 ), |                 ), | ||||||
|             })) |             })) | ||||||
| @ -1283,13 +1283,6 @@ fn optional_after_required(params: &[Parameter]) -> Result<(), KclError> { | |||||||
|  |  | ||||||
| impl Identifier { | impl Identifier { | ||||||
|     fn into_valid_binding_name(self) -> Result<Identifier, KclError> { |     fn into_valid_binding_name(self) -> Result<Identifier, KclError> { | ||||||
|         // Make sure they are not assigning a variable to a stdlib function. |  | ||||||
|         if crate::std::name_in_stdlib(&self.name) { |  | ||||||
|             return Err(KclError::Syntax(KclErrorDetails { |  | ||||||
|                 source_ranges: vec![SourceRange([self.start, self.end])], |  | ||||||
|                 message: format!("Cannot assign a variable to a reserved keyword: {}", self.name), |  | ||||||
|             })); |  | ||||||
|         } |  | ||||||
|         Ok(self) |         Ok(self) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								src/wasm-lib/prelude.kcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/wasm-lib/prelude.kcl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | fn hey_from_one_of_the_devs_of_the_past_i_wish_you_a_great_day_and_maybe_gave_you_a_little_smile_as_youve_found_this = () => { | ||||||
|  |   return 42 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | let TAU = PI * 2.0 | ||||||
|  |  | ||||||
|  | fn angledLine = (args, segment_group, tag?) => { | ||||||
|  |   let x = cos(args.angle) * args.length | ||||||
|  |   let y = sin(args.angle) * args.length | ||||||
|  |   return line([x, y], segment_group, tag) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn angledLineTo_ = (args, axis) => { | ||||||
|  |   let fn = { X: [cos, sin], Y: [sin, cos] } | ||||||
|  |   let a = args.to | ||||||
|  |   let length = args.to / fn[axis][0](args.angle) | ||||||
|  |   let b = fn[axis][1](args.angle) * length | ||||||
|  |   return [x, y] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn angledLineToX = (args, segment_group, tag?) => { | ||||||
|  |   return lineTo(angledLineTo_(args, "X"), segment_group, tag) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn angledLineX = (args, segment_group, tag?) => { | ||||||
|  |   return line(angledLineTo_(args, "X"), segment_group, tag) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn angledLineToY = (args, segment_group, tag?) => { | ||||||
|  |   return lineTo(angledLineTo_(args, "Y"), segment_group, tag) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn angledLineY = (args, segment_group, tag?) => { | ||||||
|  |   return line(angledLineTo_(args, "Y"), segment_group, tag) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	