KCL stdlib and circle function (#1029)

Allows stdlib functions to be written as KCL, not as Rust. 

Rust stdlib functions will hereafter be referred to as "core" not "std".

Right now the only stdlib function I implemented is a circle function (it's a wrapper around the core arc function which sets the arc's start/end to 0 and 360 respectively). I know I want to change this function as soon as KCL has enums, which is my next task. So, I don't want users to start using this right away. To that end, I've named this function "unstable_stdlib_circle" not "circle". Once the function is ready to be stabilized, I can rename it to just "circle".

Note that this PR modifies the existing "sketch and extrude a cylinder" KCL test so that instead of using a user-defined circle function, it uses the unstable_stdlib_circle function now. And the twenty-twenty tests pass, so we know my stdlib is working.

https://github.com/KittyCAD/modeling-app/issues/922
This commit is contained in:
Adam Chalmers
2023-11-09 09:58:20 -06:00
committed by GitHub
parent 0db5db2181
commit b925ed9b65
9 changed files with 356 additions and 413 deletions

View File

@ -0,0 +1,102 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use super::kcl_stdlib::KclStdLibFn;
use crate::{
ast::types::{FunctionExpression, Program},
docs::StdLibFn,
};
pub const CIRCLE_FN: &str = r#"
(plane, center, radius) => {
const sg = startSketchOn(plane)
|> startProfileAt([center[0] + radius, center[1]], %)
|> arc({
angle_end: 360,
angle_start: 0,
radius: radius
}, %)
|> close(%)
return sg
}
"#;
#[derive(Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
pub struct Circle {
function: FunctionExpression,
program: Program,
}
impl Default for Circle {
fn default() -> Self {
// TODO in https://github.com/KittyCAD/modeling-app/issues/1018
// Don't unwrap here, parse it at compile-time.
let (src, function) = super::kcl_stdlib::extract_function(CIRCLE_FN).unwrap();
Self {
function: *function,
program: src,
}
}
}
impl std::fmt::Debug for Circle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
"circle".fmt(f)
}
}
/// TODO: Parse the KCL in a macro and generate these
impl StdLibFn for Circle {
fn name(&self) -> String {
"unstable_stdlib_circle".to_owned()
}
fn summary(&self) -> String {
"Sketch a circle on the given plane".to_owned()
}
fn description(&self) -> String {
String::new()
}
fn tags(&self) -> Vec<String> {
Vec::new()
}
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
Vec::new() // TODO
}
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
None
}
fn unpublished(&self) -> bool {
true
}
fn deprecated(&self) -> bool {
false
}
fn std_lib_fn(&self) -> crate::std::StdFn {
todo!()
}
fn clone_box(&self) -> Box<dyn StdLibFn> {
Box::new(self.to_owned())
}
}
impl KclStdLibFn for Circle {
fn function(&self) -> &FunctionExpression {
&self.function
}
fn program(&self) -> &Program {
&self.program
}
fn kcl_clone_box(&self) -> Box<dyn KclStdLibFn> {
Box::new(self.clone())
}
}