1pub mod appearance;
4pub mod args;
5pub mod array;
6pub mod assert;
7pub mod axis_or_reference;
8pub mod chamfer;
9pub mod clone;
10pub mod csg;
11pub mod edge;
12pub mod extrude;
13pub mod fillet;
14pub mod helix;
15pub mod loft;
16pub mod math;
17pub mod mirror;
18pub mod patterns;
19pub mod planes;
20pub mod revolve;
21pub mod segment;
22pub mod shapes;
23pub mod shell;
24pub mod sketch;
25pub mod sweep;
26pub mod transform;
27pub mod utils;
28
29use anyhow::Result;
30pub use args::Args;
31use indexmap::IndexMap;
32use lazy_static::lazy_static;
33
34use crate::{
35 docs::StdLibFn,
36 errors::KclError,
37 execution::{types::PrimitiveType, ExecState, KclValue},
38 parsing::ast::types::Name,
39};
40
41pub type StdFn = fn(
42 &mut ExecState,
43 Args,
44) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<KclValue, KclError>> + Send + '_>>;
45
46lazy_static! {
47 static ref CORE_FNS: Vec<Box<dyn StdLibFn>> = vec![
48 Box::new(crate::std::appearance::Appearance),
49 Box::new(crate::std::extrude::Extrude),
50 Box::new(crate::std::segment::SegEnd),
51 Box::new(crate::std::segment::SegEndX),
52 Box::new(crate::std::segment::SegEndY),
53 Box::new(crate::std::segment::SegStart),
54 Box::new(crate::std::segment::SegStartX),
55 Box::new(crate::std::segment::SegStartY),
56 Box::new(crate::std::segment::LastSegX),
57 Box::new(crate::std::segment::LastSegY),
58 Box::new(crate::std::segment::SegLen),
59 Box::new(crate::std::segment::SegAng),
60 Box::new(crate::std::segment::TangentToEnd),
61 Box::new(crate::std::shapes::CircleThreePoint),
62 Box::new(crate::std::shapes::Polygon),
63 Box::new(crate::std::sketch::InvoluteCircular),
64 Box::new(crate::std::sketch::Line),
65 Box::new(crate::std::sketch::XLine),
66 Box::new(crate::std::sketch::YLine),
67 Box::new(crate::std::sketch::AngledLine),
68 Box::new(crate::std::sketch::AngledLineThatIntersects),
69 Box::new(crate::std::sketch::StartSketchOn),
70 Box::new(crate::std::sketch::StartProfile),
71 Box::new(crate::std::sketch::ProfileStartX),
72 Box::new(crate::std::sketch::ProfileStartY),
73 Box::new(crate::std::sketch::ProfileStart),
74 Box::new(crate::std::sketch::Close),
75 Box::new(crate::std::sketch::Arc),
76 Box::new(crate::std::sketch::TangentialArc),
77 Box::new(crate::std::sketch::BezierCurve),
78 Box::new(crate::std::sketch::Subtract2D),
79 Box::new(crate::std::patterns::PatternLinear2D),
80 Box::new(crate::std::patterns::PatternLinear3D),
81 Box::new(crate::std::patterns::PatternCircular2D),
82 Box::new(crate::std::patterns::PatternCircular3D),
83 Box::new(crate::std::edge::GetOppositeEdge),
84 Box::new(crate::std::edge::GetNextAdjacentEdge),
85 Box::new(crate::std::edge::GetPreviousAdjacentEdge),
86 Box::new(crate::std::edge::GetCommonEdge),
87 Box::new(crate::std::sweep::Sweep),
88 Box::new(crate::std::loft::Loft),
89 Box::new(crate::std::assert::Assert),
90 Box::new(crate::std::assert::AssertIs),
91 Box::new(crate::std::transform::Scale),
92 Box::new(crate::std::transform::Translate),
93 Box::new(crate::std::transform::Rotate),
94 Box::new(crate::std::csg::Intersect),
95 Box::new(crate::std::csg::Union),
96 Box::new(crate::std::csg::Subtract),
97 ];
98}
99
100pub fn name_in_stdlib(name: &str) -> bool {
101 CORE_FNS.iter().any(|f| f.name() == name)
102}
103
104pub fn get_stdlib_fn(name: &str) -> Option<Box<dyn StdLibFn>> {
105 CORE_FNS.iter().find(|f| f.name() == name).cloned()
106}
107
108#[derive(Clone, Debug, PartialEq, Eq)]
109pub struct StdFnProps {
110 pub name: String,
111 pub deprecated: bool,
112 pub include_in_feature_tree: bool,
113}
114
115impl StdFnProps {
116 fn default(name: &str) -> Self {
117 Self {
118 name: name.to_owned(),
119 deprecated: false,
120 include_in_feature_tree: false,
121 }
122 }
123
124 fn include_in_feature_tree(mut self) -> Self {
125 self.include_in_feature_tree = true;
126 self
127 }
128}
129
130pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProps) {
131 match (path, fn_name) {
132 ("math", "cos") => (
133 |e, a| Box::pin(crate::std::math::cos(e, a)),
134 StdFnProps::default("std::math::cos"),
135 ),
136 ("math", "sin") => (
137 |e, a| Box::pin(crate::std::math::sin(e, a)),
138 StdFnProps::default("std::math::sin"),
139 ),
140 ("math", "tan") => (
141 |e, a| Box::pin(crate::std::math::tan(e, a)),
142 StdFnProps::default("std::math::tan"),
143 ),
144 ("math", "acos") => (
145 |e, a| Box::pin(crate::std::math::acos(e, a)),
146 StdFnProps::default("std::math::acos"),
147 ),
148 ("math", "asin") => (
149 |e, a| Box::pin(crate::std::math::asin(e, a)),
150 StdFnProps::default("std::math::asin"),
151 ),
152 ("math", "atan") => (
153 |e, a| Box::pin(crate::std::math::atan(e, a)),
154 StdFnProps::default("std::math::atan"),
155 ),
156 ("math", "atan2") => (
157 |e, a| Box::pin(crate::std::math::atan2(e, a)),
158 StdFnProps::default("std::math::atan2"),
159 ),
160 ("math", "sqrt") => (
161 |e, a| Box::pin(crate::std::math::sqrt(e, a)),
162 StdFnProps::default("std::math::sqrt"),
163 ),
164
165 ("math", "abs") => (
166 |e, a| Box::pin(crate::std::math::abs(e, a)),
167 StdFnProps::default("std::math::abs"),
168 ),
169 ("math", "rem") => (
170 |e, a| Box::pin(crate::std::math::rem(e, a)),
171 StdFnProps::default("std::math::rem"),
172 ),
173 ("math", "round") => (
174 |e, a| Box::pin(crate::std::math::round(e, a)),
175 StdFnProps::default("std::math::round"),
176 ),
177 ("math", "floor") => (
178 |e, a| Box::pin(crate::std::math::floor(e, a)),
179 StdFnProps::default("std::math::floor"),
180 ),
181 ("math", "ceil") => (
182 |e, a| Box::pin(crate::std::math::ceil(e, a)),
183 StdFnProps::default("std::math::ceil"),
184 ),
185 ("math", "min") => (
186 |e, a| Box::pin(crate::std::math::min(e, a)),
187 StdFnProps::default("std::math::min"),
188 ),
189 ("math", "max") => (
190 |e, a| Box::pin(crate::std::math::max(e, a)),
191 StdFnProps::default("std::math::max"),
192 ),
193 ("math", "pow") => (
194 |e, a| Box::pin(crate::std::math::pow(e, a)),
195 StdFnProps::default("std::math::pow"),
196 ),
197 ("math", "log") => (
198 |e, a| Box::pin(crate::std::math::log(e, a)),
199 StdFnProps::default("std::math::log"),
200 ),
201 ("math", "log2") => (
202 |e, a| Box::pin(crate::std::math::log2(e, a)),
203 StdFnProps::default("std::math::log2"),
204 ),
205 ("math", "log10") => (
206 |e, a| Box::pin(crate::std::math::log10(e, a)),
207 StdFnProps::default("std::math::log10"),
208 ),
209 ("math", "ln") => (
210 |e, a| Box::pin(crate::std::math::ln(e, a)),
211 StdFnProps::default("std::math::ln"),
212 ),
213 ("math", "legLen") => (
214 |e, a| Box::pin(crate::std::math::leg_length(e, a)),
215 StdFnProps::default("std::math::legLen"),
216 ),
217 ("math", "legAngX") => (
218 |e, a| Box::pin(crate::std::math::leg_angle_x(e, a)),
219 StdFnProps::default("std::math::legAngX"),
220 ),
221 ("math", "legAngY") => (
222 |e, a| Box::pin(crate::std::math::leg_angle_y(e, a)),
223 StdFnProps::default("std::math::legAngY"),
224 ),
225 ("sketch", "circle") => (
226 |e, a| Box::pin(crate::std::shapes::circle(e, a)),
227 StdFnProps::default("std::sketch::circle"),
228 ),
229 ("prelude", "helix") => (
230 |e, a| Box::pin(crate::std::helix::helix(e, a)),
231 StdFnProps::default("std::helix").include_in_feature_tree(),
232 ),
233 ("transform", "mirror2d") => (
234 |e, a| Box::pin(crate::std::mirror::mirror_2d(e, a)),
235 StdFnProps::default("std::transform::mirror2d"),
236 ),
237 ("sketch", "revolve") => (
238 |e, a| Box::pin(crate::std::revolve::revolve(e, a)),
239 StdFnProps::default("std::sketch::revolve").include_in_feature_tree(),
240 ),
241 ("prelude", "offsetPlane") => (
242 |e, a| Box::pin(crate::std::planes::offset_plane(e, a)),
243 StdFnProps::default("std::offsetPlane").include_in_feature_tree(),
244 ),
245 ("solid", "fillet") => (
246 |e, a| Box::pin(crate::std::fillet::fillet(e, a)),
247 StdFnProps::default("std::solid::fillet").include_in_feature_tree(),
248 ),
249 ("solid", "chamfer") => (
250 |e, a| Box::pin(crate::std::chamfer::chamfer(e, a)),
251 StdFnProps::default("std::solid::chamfer").include_in_feature_tree(),
252 ),
253 ("solid", "shell") => (
254 |e, a| Box::pin(crate::std::shell::shell(e, a)),
255 StdFnProps::default("std::solid::shell").include_in_feature_tree(),
256 ),
257 ("solid", "hollow") => (
258 |e, a| Box::pin(crate::std::shell::hollow(e, a)),
259 StdFnProps::default("std::solid::hollow").include_in_feature_tree(),
260 ),
261 ("array", "map") => (
262 |e, a| Box::pin(crate::std::array::map(e, a)),
263 StdFnProps::default("std::array::map"),
264 ),
265 ("array", "reduce") => (
266 |e, a| Box::pin(crate::std::array::reduce(e, a)),
267 StdFnProps::default("std::array::reduce"),
268 ),
269 ("array", "push") => (
270 |e, a| Box::pin(crate::std::array::push(e, a)),
271 StdFnProps::default("std::array::push"),
272 ),
273 ("array", "pop") => (
274 |e, a| Box::pin(crate::std::array::pop(e, a)),
275 StdFnProps::default("std::array::pop"),
276 ),
277 ("prelude", "clone") => (
278 |e, a| Box::pin(crate::std::clone::clone(e, a)),
279 StdFnProps::default("std::clone").include_in_feature_tree(),
280 ),
281 ("solid", "patternTransform") => (
282 |e, a| Box::pin(crate::std::patterns::pattern_transform(e, a)),
283 StdFnProps::default("std::solid::patternTransform").include_in_feature_tree(),
284 ),
285 ("sketch", "patternTransform2d") => (
286 |e, a| Box::pin(crate::std::patterns::pattern_transform_2d(e, a)),
287 StdFnProps::default("std::sketch::patternTransform2d"),
288 ),
289 ("appearance", "hexString") => (
290 |e, a| Box::pin(crate::std::appearance::hex_string(e, a)),
291 StdFnProps::default("std::appearance::hexString"),
292 ),
293 (module, fn_name) => {
294 panic!("No implementation found for {module}::{fn_name}, please add it to this big match statement")
295 }
296 }
297}
298
299pub(crate) fn std_ty(path: &str, fn_name: &str) -> (PrimitiveType, StdFnProps) {
300 match (path, fn_name) {
301 ("types", "Sketch") => (PrimitiveType::Sketch, StdFnProps::default("std::types::Sketch")),
302 ("types", "Solid") => (PrimitiveType::Solid, StdFnProps::default("std::types::Solid")),
303 ("types", "Plane") => (PrimitiveType::Plane, StdFnProps::default("std::types::Plane")),
304 ("types", "Face") => (PrimitiveType::Face, StdFnProps::default("std::types::Face")),
305 ("types", "Helix") => (PrimitiveType::Helix, StdFnProps::default("std::types::Helix")),
306 ("types", "Edge") => (PrimitiveType::Edge, StdFnProps::default("std::types::Edge")),
307 ("types", "Axis2d") => (PrimitiveType::Axis2d, StdFnProps::default("std::types::Axis2d")),
308 ("types", "Axis3d") => (PrimitiveType::Axis3d, StdFnProps::default("std::types::Axis3d")),
309 _ => unreachable!(),
310 }
311}
312
313pub struct StdLib {
314 pub fns: IndexMap<String, Box<dyn StdLibFn>>,
315}
316
317impl std::fmt::Debug for StdLib {
318 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
319 f.debug_struct("StdLib").field("fns.len()", &self.fns.len()).finish()
320 }
321}
322
323impl StdLib {
324 pub fn new() -> Self {
325 let fns = CORE_FNS
326 .clone()
327 .into_iter()
328 .map(|internal_fn| (internal_fn.name(), internal_fn))
329 .collect();
330
331 Self { fns }
332 }
333
334 pub fn combined(&self) -> IndexMap<String, Box<dyn StdLibFn>> {
336 self.fns.clone()
337 }
338
339 pub fn get(&self, name: &str) -> Option<Box<dyn StdLibFn>> {
340 self.fns.get(name).cloned()
341 }
342
343 pub fn get_rust_function(&self, name: &Name) -> Option<Box<dyn StdLibFn>> {
344 if let Some(name) = name.local_ident() {
345 if let Some(f) = self.get(name.inner) {
346 return Some(f);
347 }
348 }
349
350 None
351 }
352
353 pub fn contains_key(&self, key: &str) -> bool {
354 self.fns.contains_key(key)
355 }
356}
357
358impl Default for StdLib {
359 fn default() -> Self {
360 Self::new()
361 }
362}
363
364const DEFAULT_TOLERANCE: f64 = 0.0000001;