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:
@ -1,8 +1,10 @@
|
||||
//! Functions implemented for language execution.
|
||||
|
||||
pub mod extrude;
|
||||
pub mod kcl_stdlib;
|
||||
pub mod math;
|
||||
pub mod segment;
|
||||
pub mod shapes;
|
||||
pub mod sketch;
|
||||
pub mod utils;
|
||||
|
||||
@ -16,6 +18,7 @@ use parse_display::{Display, FromStr};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use self::kcl_stdlib::KclStdLibFn;
|
||||
use crate::{
|
||||
ast::types::parse_json_number_as_f64,
|
||||
docs::StdLibFn,
|
||||
@ -92,12 +95,16 @@ pub fn name_in_stdlib(name: &str) -> bool {
|
||||
}
|
||||
|
||||
pub struct StdLib {
|
||||
pub fns: HashMap<String, Box<(dyn StdLibFn)>>,
|
||||
pub fns: HashMap<String, Box<dyn StdLibFn>>,
|
||||
pub kcl_fns: HashMap<String, Box<dyn KclStdLibFn>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for StdLib {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("StdLib").field("fns.len()", &self.fns.len()).finish()
|
||||
f.debug_struct("StdLib")
|
||||
.field("fns.len()", &self.fns.len())
|
||||
.field("kcl_fns.len()", &self.kcl_fns.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,12 +116,36 @@ impl StdLib {
|
||||
.map(|internal_fn| (internal_fn.name(), internal_fn))
|
||||
.collect();
|
||||
|
||||
Self { fns }
|
||||
let kcl_internal_fns: [Box<dyn KclStdLibFn>; 1] = [Box::<shapes::Circle>::default()];
|
||||
let kcl_fns = kcl_internal_fns
|
||||
.into_iter()
|
||||
.map(|internal_fn| (internal_fn.name(), internal_fn))
|
||||
.collect();
|
||||
|
||||
Self { fns, kcl_fns }
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &str) -> Option<Box<dyn StdLibFn>> {
|
||||
self.fns.get(name).cloned()
|
||||
}
|
||||
|
||||
pub fn get_kcl(&self, name: &str) -> Option<Box<dyn KclStdLibFn>> {
|
||||
self.kcl_fns.get(name).cloned()
|
||||
}
|
||||
|
||||
pub fn get_either(&self, name: &str) -> FunctionKind {
|
||||
if let Some(f) = self.get(name) {
|
||||
FunctionKind::Core(f)
|
||||
} else if let Some(f) = self.get_kcl(name) {
|
||||
FunctionKind::Std(f)
|
||||
} else {
|
||||
FunctionKind::UserDefined
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_key(&self, key: &str) -> bool {
|
||||
self.fns.contains_key(key) || self.kcl_fns.contains_key(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for StdLib {
|
||||
@ -123,6 +154,12 @@ impl Default for StdLib {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum FunctionKind {
|
||||
Core(Box<dyn StdLibFn>),
|
||||
Std(Box<dyn KclStdLibFn>),
|
||||
UserDefined,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Args {
|
||||
pub args: Vec<MemoryItem>,
|
||||
|
Reference in New Issue
Block a user