Skip to main content

kcl_lib/std/
mod.rs

1//! Functions implemented for language execution.
2
3pub mod appearance;
4pub mod args;
5pub mod array;
6pub mod assert;
7pub mod axis_or_reference;
8pub mod chamfer;
9pub mod clone;
10pub mod constraints;
11pub mod csg;
12pub mod edge;
13pub mod extrude;
14pub mod faces;
15pub mod fail;
16pub mod fillet;
17pub mod gdt;
18pub mod helix;
19pub mod ids;
20pub mod loft;
21pub mod math;
22pub mod mirror;
23pub mod operation;
24pub mod patterns;
25pub mod planes;
26pub(crate) mod region_consumption;
27pub mod revolve;
28pub mod runtime;
29pub mod segment;
30pub mod shapes;
31pub mod shell;
32pub mod sketch;
33pub(crate) mod solid_consumption;
34pub(crate) mod solver;
35pub mod string;
36pub mod surfaces;
37pub mod sweep;
38pub mod transform;
39pub mod utils;
40pub mod view;
41
42use anyhow::Result;
43pub use args::Args;
44use futures::future::FutureExt;
45
46use crate::errors::KclError;
47use crate::execution::ConsumedRegionOperation;
48use crate::execution::ExecState;
49use crate::execution::KclValue;
50use crate::execution::KclValueControlFlow;
51use crate::execution::types::PrimitiveType;
52
53pub type StdFn =
54    fn(
55        &mut ExecState,
56        Args,
57    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<KclValueControlFlow, KclError>> + Send + '_>>;
58
59#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
60pub(crate) enum ConsumedSolidArgCheck {
61    #[default]
62    Error,
63    WarnDeprecated,
64}
65
66#[derive(Clone, Copy, Debug, PartialEq, Eq)]
67pub(crate) enum ConsumedRegionDuplicatePolicy {
68    Reject,
69    Deduplicate,
70}
71
72#[derive(Clone, Copy, Debug, PartialEq, Eq)]
73pub(crate) enum ConsumedRegionAliasPolicy {
74    None,
75    Reject(&'static str),
76    Preserve(&'static str),
77}
78
79#[derive(Clone, Copy, Debug, PartialEq, Eq)]
80pub(crate) struct ConsumedRegionArg {
81    pub(crate) operation: ConsumedRegionOperation,
82    pub(crate) duplicate_policy: ConsumedRegionDuplicatePolicy,
83    pub(crate) alias_policy: ConsumedRegionAliasPolicy,
84    pub(crate) stale_region_policy: StaleRegionPolicy,
85}
86
87impl ConsumedRegionArg {
88    pub(crate) const fn new(operation: ConsumedRegionOperation) -> Self {
89        Self {
90            operation,
91            duplicate_policy: ConsumedRegionDuplicatePolicy::Reject,
92            alias_policy: ConsumedRegionAliasPolicy::None,
93            stale_region_policy: StaleRegionPolicy::Error,
94        }
95    }
96
97    pub(crate) const fn reject_alias_with(mut self, arg_name: &'static str) -> Self {
98        self.alias_policy = ConsumedRegionAliasPolicy::Reject(arg_name);
99        self
100    }
101
102    pub(crate) const fn preserve_alias_with(mut self, arg_name: &'static str) -> Self {
103        self.alias_policy = ConsumedRegionAliasPolicy::Preserve(arg_name);
104        self
105    }
106
107    pub(crate) const fn deduplicate(mut self) -> Self {
108        self.duplicate_policy = ConsumedRegionDuplicatePolicy::Deduplicate;
109        self
110    }
111
112    pub(crate) const fn warn_if_already_consumed(mut self) -> Self {
113        self.stale_region_policy = StaleRegionPolicy::Warning;
114        self
115    }
116}
117
118#[derive(Clone, Copy, Debug, PartialEq, Eq)]
119pub(crate) enum StaleRegionPolicy {
120    Error,
121    Warning,
122}
123
124#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
125pub(crate) enum RegionBehavior {
126    /// Warn when a consumed region reaches a Rust-backed stdlib function.
127    #[default]
128    WarnOnConsumed,
129    /// Apply the configured stale-region policy and record the specified inputs
130    /// as consumed after success.
131    Consume(ConsumedRegionArg),
132    /// The function reads stored region data without sending its object ID to the engine.
133    ReadLocal,
134}
135
136impl RegionBehavior {
137    pub(crate) const fn stale_region_policy(self) -> Option<StaleRegionPolicy> {
138        match self {
139            Self::WarnOnConsumed => Some(StaleRegionPolicy::Warning),
140            Self::Consume(policy) => Some(policy.stale_region_policy),
141            Self::ReadLocal => None,
142        }
143    }
144}
145
146#[derive(Clone, Debug, PartialEq, Eq)]
147pub struct StdFnProps {
148    pub name: String,
149    pub(crate) consumed_solid_arg_check: ConsumedSolidArgCheck,
150    pub(crate) region_behavior: RegionBehavior,
151    /// Set for the few builtins that call back into KCL (map, reduce,
152    /// patternTransform): the machine executor routes them to a resumable
153    /// entry so their callbacks run on the machine's continuation stack
154    /// instead of re-entering natively. The recursive executor ignores this.
155    pub(crate) resumable: Option<ResumableKind>,
156}
157
158/// Which resumable builtin this is. See
159/// `crate::execution::machine`'s resume continuations.
160#[derive(Clone, Copy, Debug, PartialEq, Eq)]
161pub(crate) enum ResumableKind {
162    Map,
163    Reduce,
164    PatternTransform,
165    PatternTransform2d,
166}
167
168impl StdFnProps {
169    pub(crate) fn default(name: &str) -> Self {
170        Self {
171            name: name.to_owned(),
172            consumed_solid_arg_check: Default::default(),
173            region_behavior: Default::default(),
174            resumable: None,
175        }
176    }
177
178    pub(crate) fn resumable(mut self, kind: ResumableKind) -> Self {
179        self.resumable = Some(kind);
180        self
181    }
182
183    pub(crate) fn warn_deprecated_on_consumed_solid_args(mut self) -> Self {
184        self.consumed_solid_arg_check = ConsumedSolidArgCheck::WarnDeprecated;
185        self
186    }
187
188    pub(crate) fn consumes_regions(mut self, consumed_region_arg: ConsumedRegionArg) -> Self {
189        self.region_behavior = RegionBehavior::Consume(consumed_region_arg);
190        self
191    }
192
193    pub(crate) fn reads_regions_locally(mut self) -> Self {
194        self.region_behavior = RegionBehavior::ReadLocal;
195        self
196    }
197}
198
199/// Resolves a Rust-backed standard-library function and its execution policies.
200///
201/// When registering a new function, start with `StdFnProps::default(...)`. Its
202/// fully qualified name is used in diagnostics. Then add modifiers according to
203/// how the function handles values consumed by earlier engine operations:
204///
205/// - Keep the default region behavior if the function does not accept Regions,
206///   or may use a Region's engine UUID without consuming it. A stale Region
207///   produces a warning and the call continues.
208/// - Use [`StdFnProps::reads_regions_locally`] only when the function itself
209///   uses stored KCL data and never sends an input Region's UUID to the engine.
210///   Calls made by callbacks or KCL wrappers apply their own policies.
211/// - Use [`StdFnProps::consumes_regions`] when a successful call consumes Regions
212///   in its unlabeled input. By default, the function rejects stale Regions,
213///   rejects duplicate Regions in that input, and records the Regions as consumed
214///   after success. The modifiers define engine-specific exceptions:
215///   - [`ConsumedRegionArg::warn_if_already_consumed`] warns instead of rejecting
216///     stale Regions.
217///   - [`ConsumedRegionArg::deduplicate`] allows duplicate Regions in the input.
218///   - [`ConsumedRegionArg::reject_alias_with`] rejects a Region that is also
219///     passed in the named argument.
220///   - [`ConsumedRegionArg::preserve_alias_with`] does not record a Region as
221///     consumed when it is also passed in the named argument.
222/// - Keep the default consumed-solid behavior for new functions. Use
223///   [`StdFnProps::warn_deprecated_on_consumed_solid_args`] only as a temporary
224///   compatibility exception that warns instead of rejecting the call.
225///
226/// Region and solid policies are independent, so their modifiers may be chained.
227pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProps) {
228    match (path, fn_name) {
229        ("gdt", "datum") => (
230            |e, a| Box::pin(crate::std::gdt::datum(e, a).map(|r| r.map(KclValue::continue_))),
231            StdFnProps::default("std::gdt::datum"),
232        ),
233        ("gdt", "flatness") => (
234            |e, a| Box::pin(crate::std::gdt::flatness(e, a).map(|r| r.map(KclValue::continue_))),
235            StdFnProps::default("std::gdt::flatness"),
236        ),
237        ("gdt", "straightness") => (
238            |e, a| Box::pin(crate::std::gdt::straightness(e, a).map(|r| r.map(KclValue::continue_))),
239            StdFnProps::default("std::gdt::straightness"),
240        ),
241        ("gdt", "circularity") => (
242            |e, a| Box::pin(crate::std::gdt::circularity(e, a).map(|r| r.map(KclValue::continue_))),
243            StdFnProps::default("std::gdt::circularity"),
244        ),
245        ("gdt", "cylindricity") => (
246            |e, a| Box::pin(crate::std::gdt::cylindricity(e, a).map(|r| r.map(KclValue::continue_))),
247            StdFnProps::default("std::gdt::cylindricity"),
248        ),
249        ("gdt", "concentricity") => (
250            |e, a| Box::pin(crate::std::gdt::concentricity(e, a).map(|r| r.map(KclValue::continue_))),
251            StdFnProps::default("std::gdt::concentricity"),
252        ),
253        ("gdt", "symmetry") => (
254            |e, a| Box::pin(crate::std::gdt::symmetry(e, a).map(|r| r.map(KclValue::continue_))),
255            StdFnProps::default("std::gdt::symmetry"),
256        ),
257        ("gdt", "runout") => (
258            |e, a| Box::pin(crate::std::gdt::runout(e, a).map(|r| r.map(KclValue::continue_))),
259            StdFnProps::default("std::gdt::runout"),
260        ),
261        ("gdt", "angularity") => (
262            |e, a| Box::pin(crate::std::gdt::angularity(e, a).map(|r| r.map(KclValue::continue_))),
263            StdFnProps::default("std::gdt::angularity"),
264        ),
265        ("gdt", "perpendicularity") => (
266            |e, a| Box::pin(crate::std::gdt::perpendicularity(e, a).map(|r| r.map(KclValue::continue_))),
267            StdFnProps::default("std::gdt::perpendicularity"),
268        ),
269        ("gdt", "parallelism") => (
270            |e, a| Box::pin(crate::std::gdt::parallelism(e, a).map(|r| r.map(KclValue::continue_))),
271            StdFnProps::default("std::gdt::parallelism"),
272        ),
273        ("gdt", "annotation") => (
274            |e, a| Box::pin(crate::std::gdt::annotation(e, a).map(|r| r.map(KclValue::continue_))),
275            StdFnProps::default("std::gdt::annotation"),
276        ),
277        ("gdt", "note") => (
278            |e, a| Box::pin(crate::std::gdt::note(e, a).map(|r| r.map(KclValue::continue_))),
279            StdFnProps::default("std::gdt::note"),
280        ),
281        ("gdt", "distance") => (
282            |e, a| Box::pin(crate::std::gdt::distance(e, a).map(|r| r.map(KclValue::continue_))),
283            StdFnProps::default("std::gdt::distance"),
284        ),
285        ("gdt", "profile") => (
286            |e, a| Box::pin(crate::std::gdt::profile(e, a).map(|r| r.map(KclValue::continue_))),
287            StdFnProps::default("std::gdt::profile"),
288        ),
289        ("gdt", "profileLine") => (
290            |e, a| Box::pin(crate::std::gdt::profile_line(e, a).map(|r| r.map(KclValue::continue_))),
291            StdFnProps::default("std::gdt::profileLine"),
292        ),
293        ("gdt", "profileSurface") => (
294            |e, a| Box::pin(crate::std::gdt::profile_surface(e, a).map(|r| r.map(KclValue::continue_))),
295            StdFnProps::default("std::gdt::profileSurface"),
296        ),
297        ("gdt", "position") => (
298            |e, a| Box::pin(crate::std::gdt::position(e, a).map(|r| r.map(KclValue::continue_))),
299            StdFnProps::default("std::gdt::position"),
300        ),
301        ("math", "cos") => (
302            |e, a| Box::pin(crate::std::math::cos(e, a).map(|r| r.map(KclValue::continue_))),
303            StdFnProps::default("std::math::cos"),
304        ),
305        ("math", "sin") => (
306            |e, a| Box::pin(crate::std::math::sin(e, a).map(|r| r.map(KclValue::continue_))),
307            StdFnProps::default("std::math::sin"),
308        ),
309        ("math", "tan") => (
310            |e, a| Box::pin(crate::std::math::tan(e, a).map(|r| r.map(KclValue::continue_))),
311            StdFnProps::default("std::math::tan"),
312        ),
313        ("math", "acos") => (
314            |e, a| Box::pin(crate::std::math::acos(e, a).map(|r| r.map(KclValue::continue_))),
315            StdFnProps::default("std::math::acos"),
316        ),
317        ("math", "asin") => (
318            |e, a| Box::pin(crate::std::math::asin(e, a).map(|r| r.map(KclValue::continue_))),
319            StdFnProps::default("std::math::asin"),
320        ),
321        ("math", "atan") => (
322            |e, a| Box::pin(crate::std::math::atan(e, a).map(|r| r.map(KclValue::continue_))),
323            StdFnProps::default("std::math::atan"),
324        ),
325        ("math", "atan2") => (
326            |e, a| Box::pin(crate::std::math::atan2(e, a).map(|r| r.map(KclValue::continue_))),
327            StdFnProps::default("std::math::atan2"),
328        ),
329        ("math", "sqrt") => (
330            |e, a| Box::pin(crate::std::math::sqrt(e, a).map(|r| r.map(KclValue::continue_))),
331            StdFnProps::default("std::math::sqrt"),
332        ),
333
334        ("math", "abs") => (
335            |e, a| Box::pin(crate::std::math::abs(e, a).map(|r| r.map(KclValue::continue_))),
336            StdFnProps::default("std::math::abs"),
337        ),
338        ("math", "rem") => (
339            |e, a| Box::pin(crate::std::math::rem(e, a).map(|r| r.map(KclValue::continue_))),
340            StdFnProps::default("std::math::rem"),
341        ),
342        ("math", "round") => (
343            |e, a| Box::pin(crate::std::math::round(e, a).map(|r| r.map(KclValue::continue_))),
344            StdFnProps::default("std::math::round"),
345        ),
346        ("math", "floor") => (
347            |e, a| Box::pin(crate::std::math::floor(e, a).map(|r| r.map(KclValue::continue_))),
348            StdFnProps::default("std::math::floor"),
349        ),
350        ("math", "ceil") => (
351            |e, a| Box::pin(crate::std::math::ceil(e, a).map(|r| r.map(KclValue::continue_))),
352            StdFnProps::default("std::math::ceil"),
353        ),
354        ("math", "min") => (
355            |e, a| Box::pin(crate::std::math::min(e, a).map(|r| r.map(KclValue::continue_))),
356            StdFnProps::default("std::math::min"),
357        ),
358        ("math", "max") => (
359            |e, a| Box::pin(crate::std::math::max(e, a).map(|r| r.map(KclValue::continue_))),
360            StdFnProps::default("std::math::max"),
361        ),
362        ("math", "pow") => (
363            |e, a| Box::pin(crate::std::math::pow(e, a).map(|r| r.map(KclValue::continue_))),
364            StdFnProps::default("std::math::pow"),
365        ),
366        ("math", "log") => (
367            |e, a| Box::pin(crate::std::math::log(e, a).map(|r| r.map(KclValue::continue_))),
368            StdFnProps::default("std::math::log"),
369        ),
370        ("math", "log2") => (
371            |e, a| Box::pin(crate::std::math::log2(e, a).map(|r| r.map(KclValue::continue_))),
372            StdFnProps::default("std::math::log2"),
373        ),
374        ("math", "log10") => (
375            |e, a| Box::pin(crate::std::math::log10(e, a).map(|r| r.map(KclValue::continue_))),
376            StdFnProps::default("std::math::log10"),
377        ),
378        ("math", "ln") => (
379            |e, a| Box::pin(crate::std::math::ln(e, a).map(|r| r.map(KclValue::continue_))),
380            StdFnProps::default("std::math::ln"),
381        ),
382        ("math", "legLen") => (
383            |e, a| Box::pin(crate::std::math::leg_length(e, a).map(|r| r.map(KclValue::continue_))),
384            StdFnProps::default("std::math::legLen"),
385        ),
386        ("math", "legAngX") => (
387            |e, a| Box::pin(crate::std::math::leg_angle_x(e, a).map(|r| r.map(KclValue::continue_))),
388            StdFnProps::default("std::math::legAngX"),
389        ),
390        ("math", "legAngY") => (
391            |e, a| Box::pin(crate::std::math::leg_angle_y(e, a).map(|r| r.map(KclValue::continue_))),
392            StdFnProps::default("std::math::legAngY"),
393        ),
394        ("sketch", "circle") => (
395            |e, a| Box::pin(crate::std::shapes::circle(e, a).map(|r| r.map(KclValue::continue_))),
396            StdFnProps::default("std::sketch::circle").reads_regions_locally(),
397        ),
398        ("sketch", "ellipse") => (
399            |e, a| Box::pin(crate::std::shapes::ellipse(e, a).map(|r| r.map(KclValue::continue_))),
400            StdFnProps::default("std::sketch::ellipse").reads_regions_locally(),
401        ),
402        ("prelude", "helix") => (
403            |e, a| Box::pin(crate::std::helix::helix(e, a).map(|r| r.map(KclValue::continue_))),
404            StdFnProps::default("std::helix"),
405        ),
406        ("transform", "mirror2d") => (
407            |e, a| Box::pin(crate::std::mirror::mirror_2d(e, a).map(|r| r.map(KclValue::continue_))),
408            StdFnProps::default("std::transform::mirror2d"),
409        ),
410        ("transform", "mirror3d") => (
411            |e, a| Box::pin(crate::std::mirror::mirror_3d(e, a).map(|r| r.map(KclValue::continue_))),
412            StdFnProps::default("std::transform::mirror3d"),
413        ),
414        ("transform", "translate") => (
415            |e, a| Box::pin(crate::std::transform::translate(e, a).map(|r| r.map(KclValue::continue_))),
416            StdFnProps::default("std::transform::translate"),
417        ),
418        ("transform", "rotate") => (
419            |e, a| Box::pin(crate::std::transform::rotate(e, a).map(|r| r.map(KclValue::continue_))),
420            StdFnProps::default("std::transform::rotate"),
421        ),
422        ("transform", "scale") => (
423            |e, a| Box::pin(crate::std::transform::scale(e, a).map(|r| r.map(KclValue::continue_))),
424            StdFnProps::default("std::transform::scale"),
425        ),
426        ("transform", "hide") => (
427            |e, a| Box::pin(crate::std::transform::hide(e, a).map(|r| r.map(KclValue::continue_))),
428            StdFnProps::default("std::transform::hide").warn_deprecated_on_consumed_solid_args(),
429        ),
430        ("transform", "delete") => (
431            |e, a| Box::pin(crate::std::transform::delete(e, a).map(|r| r.map(KclValue::continue_))),
432            StdFnProps::default("std::transform::delete").consumes_regions(
433                ConsumedRegionArg::new(ConsumedRegionOperation::Delete)
434                    .deduplicate()
435                    .warn_if_already_consumed(),
436            ),
437        ),
438        ("prelude", "offsetPlane") => (
439            |e, a| Box::pin(crate::std::planes::offset_plane(e, a).map(|r| r.map(KclValue::continue_))),
440            StdFnProps::default("std::offsetPlane"),
441        ),
442        ("prelude", "assert") => (
443            |e, a| Box::pin(crate::std::assert::assert(e, a).map(|r| r.map(KclValue::continue_))),
444            StdFnProps::default("std::assert"),
445        ),
446        ("prelude", "assertIs") => (
447            |e, a| Box::pin(crate::std::assert::assert_is(e, a).map(|r| r.map(KclValue::continue_))),
448            StdFnProps::default("std::assertIs"),
449        ),
450        ("prelude", "fail") => (
451            |e, a| Box::pin(crate::std::fail::fail(e, a).map(|r| r.map(KclValue::continue_))),
452            StdFnProps::default("std::fail"),
453        ),
454        ("runtime", "exit") => (
455            |e, a| Box::pin(crate::std::runtime::exit(e, a)),
456            StdFnProps::default("std::runtime::exit"),
457        ),
458        ("string", "uppercase") => (
459            |e, a| Box::pin(crate::std::string::uppercase(e, a).map(|r| r.map(KclValue::continue_))),
460            StdFnProps::default("std::string::uppercase"),
461        ),
462        ("string", "lowercase") => (
463            |e, a| Box::pin(crate::std::string::lowercase(e, a).map(|r| r.map(KclValue::continue_))),
464            StdFnProps::default("std::string::lowercase"),
465        ),
466        ("string", "isEqual") => (
467            |e, a| Box::pin(crate::std::string::is_equal(e, a).map(|r| r.map(KclValue::continue_))),
468            StdFnProps::default("std::string::isEqual"),
469        ),
470        ("string", "trim") => (
471            |e, a| Box::pin(crate::std::string::trim(e, a).map(|r| r.map(KclValue::continue_))),
472            StdFnProps::default("std::string::trim"),
473        ),
474        ("string", "trimStart") => (
475            |e, a| Box::pin(crate::std::string::trim_start(e, a).map(|r| r.map(KclValue::continue_))),
476            StdFnProps::default("std::string::trimStart"),
477        ),
478        ("string", "trimEnd") => (
479            |e, a| Box::pin(crate::std::string::trim_end(e, a).map(|r| r.map(KclValue::continue_))),
480            StdFnProps::default("std::string::trimEnd"),
481        ),
482        ("string", "toString") => (
483            |e, a| Box::pin(crate::std::string::number_to_string(e, a).map(|r| r.map(KclValue::continue_))),
484            StdFnProps::default("std::string::toString"),
485        ),
486        ("solid", "fillet") => (
487            |e, a| Box::pin(crate::std::fillet::fillet(e, a).map(|r| r.map(KclValue::continue_))),
488            StdFnProps::default("std::solid::fillet"),
489        ),
490        ("solid", "chamfer") => (
491            |e, a| Box::pin(crate::std::chamfer::chamfer(e, a).map(|r| r.map(KclValue::continue_))),
492            StdFnProps::default("std::solid::chamfer"),
493        ),
494        ("solid", "shell") => (
495            |e, a| Box::pin(crate::std::shell::shell(e, a).map(|r| r.map(KclValue::continue_))),
496            StdFnProps::default("std::solid::shell"),
497        ),
498        ("solid", "hollow") => (
499            |e, a| Box::pin(crate::std::shell::hollow(e, a).map(|r| r.map(KclValue::continue_))),
500            StdFnProps::default("std::solid::hollow"),
501        ),
502        ("solid", "union") => (
503            |e, a| Box::pin(crate::std::csg::union(e, a).map(|r| r.map(KclValue::continue_))),
504            StdFnProps::default("std::solid::union"),
505        ),
506        ("solid", "intersect") => (
507            |e, a| Box::pin(crate::std::csg::intersect(e, a).map(|r| r.map(KclValue::continue_))),
508            StdFnProps::default("std::solid::intersect"),
509        ),
510        ("solid", "subtract") => (
511            |e, a| Box::pin(crate::std::csg::subtract(e, a).map(|r| r.map(KclValue::continue_))),
512            StdFnProps::default("std::solid::subtract"),
513        ),
514        ("solid", "patternTransform") => (
515            |e, a| Box::pin(crate::std::patterns::pattern_transform(e, a)),
516            StdFnProps::default("std::solid::patternTransform").resumable(ResumableKind::PatternTransform),
517        ),
518        ("solid", "patternLinear3d") => (
519            |e, a| Box::pin(crate::std::patterns::pattern_linear_3d(e, a).map(|r| r.map(KclValue::continue_))),
520            StdFnProps::default("std::solid::patternLinear3d"),
521        ),
522        ("solid", "patternCircular3d") => (
523            |e, a| Box::pin(crate::std::patterns::pattern_circular_3d(e, a).map(|r| r.map(KclValue::continue_))),
524            StdFnProps::default("std::solid::patternCircular3d"),
525        ),
526        ("solid", "appearance") => (
527            |e, a| Box::pin(crate::std::appearance::appearance(e, a).map(|r| r.map(KclValue::continue_))),
528            StdFnProps::default("std::solid::appearance"),
529        ),
530        ("solid", "flipSurface") => (
531            |e, a| Box::pin(crate::std::surfaces::flip_surface(e, a).map(|r| r.map(KclValue::continue_))),
532            StdFnProps::default("std::solid::flipSurface"),
533        ),
534        ("solid", "split") => (
535            |e, a| Box::pin(crate::std::csg::split(e, a).map(|r| r.map(KclValue::continue_))),
536            StdFnProps::default("std::solid::split"),
537        ),
538        ("array", "map") => (
539            |e, a| Box::pin(crate::std::array::map(e, a)),
540            StdFnProps::default("std::array::map")
541                .reads_regions_locally()
542                .resumable(ResumableKind::Map),
543        ),
544        ("array", "reduce") => (
545            |e, a| Box::pin(crate::std::array::reduce(e, a)),
546            StdFnProps::default("std::array::reduce")
547                .reads_regions_locally()
548                .resumable(ResumableKind::Reduce),
549        ),
550        ("array", "push") => (
551            |e, a| Box::pin(crate::std::array::push(e, a).map(|r| r.map(KclValue::continue_))),
552            StdFnProps::default("std::array::push").reads_regions_locally(),
553        ),
554        ("array", "pop") => (
555            |e, a| Box::pin(crate::std::array::pop(e, a).map(|r| r.map(KclValue::continue_))),
556            StdFnProps::default("std::array::pop").reads_regions_locally(),
557        ),
558        ("array", "concat") => (
559            |e, a| Box::pin(crate::std::array::concat(e, a).map(|r| r.map(KclValue::continue_))),
560            StdFnProps::default("std::array::concat").reads_regions_locally(),
561        ),
562        ("array", "slice") => (
563            |e, a| Box::pin(crate::std::array::slice(e, a).map(|r| r.map(KclValue::continue_))),
564            StdFnProps::default("std::array::slice").reads_regions_locally(),
565        ),
566        ("array", "flatten") => (
567            |e, a| Box::pin(crate::std::array::flatten(e, a).map(|r| r.map(KclValue::continue_))),
568            StdFnProps::default("std::array::flatten")
569                .warn_deprecated_on_consumed_solid_args()
570                .reads_regions_locally(),
571        ),
572        ("prelude", "clone") => (
573            |e, a| Box::pin(crate::std::clone::clone(e, a).map(|r| r.map(KclValue::continue_))),
574            StdFnProps::default("std::clone"),
575        ),
576        ("prelude", "faceId") => (
577            |e, a| Box::pin(crate::std::ids::face_id(e, a).map(|r| r.map(KclValue::continue_))),
578            StdFnProps::default("std::faceId"),
579        ),
580        ("prelude", "edgeId") => (
581            |e, a| Box::pin(crate::std::ids::edge_id(e, a).map(|r| r.map(KclValue::continue_))),
582            StdFnProps::default("std::edgeId"),
583        ),
584        ("sketch", "conic") => (
585            |e, a| Box::pin(crate::std::sketch::conic(e, a).map(|r| r.map(KclValue::continue_))),
586            StdFnProps::default("std::sketch::conic"),
587        ),
588        ("sketch", "parabolic") => (
589            |e, a| Box::pin(crate::std::sketch::parabolic(e, a).map(|r| r.map(KclValue::continue_))),
590            StdFnProps::default("std::sketch::parabolic"),
591        ),
592        ("sketch", "parabolicPoint") => (
593            |e, a| Box::pin(crate::std::sketch::parabolic_point(e, a).map(|r| r.map(KclValue::continue_))),
594            StdFnProps::default("std::sketch::parabolicPoint"),
595        ),
596        ("sketch", "hyperbolic") => (
597            |e, a| Box::pin(crate::std::sketch::hyperbolic(e, a).map(|r| r.map(KclValue::continue_))),
598            StdFnProps::default("std::sketch::hyperbolic"),
599        ),
600        ("sketch", "hyperbolicPoint") => (
601            |e, a| Box::pin(crate::std::sketch::hyperbolic_point(e, a).map(|r| r.map(KclValue::continue_))),
602            StdFnProps::default("std::sketch::hyperbolicPoint"),
603        ),
604        ("sketch", "elliptic") => (
605            |e, a| Box::pin(crate::std::sketch::elliptic(e, a).map(|r| r.map(KclValue::continue_))),
606            StdFnProps::default("std::sketch::elliptic"),
607        ),
608        ("sketch", "ellipticPoint") => (
609            |e, a| Box::pin(crate::std::sketch::elliptic_point(e, a).map(|r| r.map(KclValue::continue_))),
610            StdFnProps::default("std::sketch::ellipticPoint"),
611        ),
612        ("sketch", "rectangle") => (
613            |e, a| Box::pin(crate::std::shapes::rectangle(e, a).map(|r| r.map(KclValue::continue_))),
614            StdFnProps::default("std::sketch::rectangle").reads_regions_locally(),
615        ),
616        ("sketch", "planeOf") => (
617            |e, a| Box::pin(crate::std::planes::plane_of(e, a).map(|r| r.map(KclValue::continue_))),
618            StdFnProps::default("std::sketch::planeOf"),
619        ),
620        ("sketch", "faceOf") => (
621            |e, a| Box::pin(crate::std::faces::face_of(e, a).map(|r| r.map(KclValue::continue_))),
622            StdFnProps::default("std::sketch::faceOf"),
623        ),
624        ("sketch", "extrude") => (
625            |e, a| Box::pin(crate::std::extrude::extrude(e, a).map(|r| r.map(KclValue::continue_))),
626            StdFnProps::default("std::sketch::extrude")
627                .consumes_regions(ConsumedRegionArg::new(ConsumedRegionOperation::Extrude).reject_alias_with("to")),
628        ),
629        ("sketch", "patternTransform2d") => (
630            |e, a| Box::pin(crate::std::patterns::pattern_transform_2d(e, a)),
631            StdFnProps::default("std::sketch::patternTransform2d").resumable(ResumableKind::PatternTransform2d),
632        ),
633        ("sketch", "revolve") => (
634            |e, a| Box::pin(crate::std::revolve::revolve(e, a).map(|r| r.map(KclValue::continue_))),
635            StdFnProps::default("std::sketch::revolve")
636                .consumes_regions(ConsumedRegionArg::new(ConsumedRegionOperation::Revolve)),
637        ),
638        ("sketch", "sweep") => (
639            |e, a| Box::pin(crate::std::sweep::sweep(e, a).map(|r| r.map(KclValue::continue_))),
640            StdFnProps::default("std::sketch::sweep")
641                .consumes_regions(ConsumedRegionArg::new(ConsumedRegionOperation::Sweep).preserve_alias_with("path")),
642        ),
643        ("sketch", "loft") => (
644            |e, a| Box::pin(crate::std::loft::loft(e, a).map(|r| r.map(KclValue::continue_))),
645            StdFnProps::default("std::sketch::loft"),
646        ),
647        ("sketch", "polygon") => (
648            |e, a| Box::pin(crate::std::shapes::polygon(e, a).map(|r| r.map(KclValue::continue_))),
649            StdFnProps::default("std::sketch::polygon").reads_regions_locally(),
650        ),
651        ("sketch", "circleThreePoint") => (
652            |e, a| Box::pin(crate::std::shapes::circle_three_point(e, a).map(|r| r.map(KclValue::continue_))),
653            StdFnProps::default("std::sketch::circleThreePoint").reads_regions_locally(),
654        ),
655        ("sketch", "getCommonEdge") => (
656            |e, a| Box::pin(crate::std::edge::get_common_edge(e, a).map(|r| r.map(KclValue::continue_))),
657            StdFnProps::default("std::sketch::getCommonEdge"),
658        ),
659        ("sketch", "getBoundedEdge") => (
660            |e, a| Box::pin(crate::std::edge::get_bounded_edge(e, a).map(|r| r.map(KclValue::continue_))),
661            StdFnProps::default("std::sketch::getBoundedEdge"),
662        ),
663        ("sketch", "getNextAdjacentEdge") => (
664            |e, a| Box::pin(crate::std::edge::get_next_adjacent_edge(e, a).map(|r| r.map(KclValue::continue_))),
665            StdFnProps::default("std::sketch::getNextAdjacentEdge"),
666        ),
667        ("sketch", "getOppositeEdge") => (
668            |e, a| Box::pin(crate::std::edge::get_opposite_edge(e, a).map(|r| r.map(KclValue::continue_))),
669            StdFnProps::default("std::sketch::getOppositeEdge"),
670        ),
671        ("sketch", "getPreviousAdjacentEdge") => (
672            |e, a| Box::pin(crate::std::edge::get_previous_adjacent_edge(e, a).map(|r| r.map(KclValue::continue_))),
673            StdFnProps::default("std::sketch::getPreviousAdjacentEdge"),
674        ),
675        ("sketch", "patternLinear2d") => (
676            |e, a| Box::pin(crate::std::patterns::pattern_linear_2d(e, a).map(|r| r.map(KclValue::continue_))),
677            StdFnProps::default("std::sketch::patternLinear2d"),
678        ),
679        ("sketch", "patternCircular2d") => (
680            |e, a| Box::pin(crate::std::patterns::pattern_circular_2d(e, a).map(|r| r.map(KclValue::continue_))),
681            StdFnProps::default("std::sketch::patternCircular2d"),
682        ),
683        ("sketch", "segEnd") => (
684            |e, a| Box::pin(crate::std::segment::segment_end(e, a).map(|r| r.map(KclValue::continue_))),
685            StdFnProps::default("std::sketch::segEnd"),
686        ),
687        ("sketch", "segEndX") => (
688            |e, a| Box::pin(crate::std::segment::segment_end_x(e, a).map(|r| r.map(KclValue::continue_))),
689            StdFnProps::default("std::sketch::segEndX"),
690        ),
691        ("sketch", "segEndY") => (
692            |e, a| Box::pin(crate::std::segment::segment_end_y(e, a).map(|r| r.map(KclValue::continue_))),
693            StdFnProps::default("std::sketch::segEndY"),
694        ),
695        ("sketch", "segStart") => (
696            |e, a| Box::pin(crate::std::segment::segment_start(e, a).map(|r| r.map(KclValue::continue_))),
697            StdFnProps::default("std::sketch::segStart"),
698        ),
699        ("sketch", "segStartX") => (
700            |e, a| Box::pin(crate::std::segment::segment_start_x(e, a).map(|r| r.map(KclValue::continue_))),
701            StdFnProps::default("std::sketch::segStartX"),
702        ),
703        ("sketch", "segStartY") => (
704            |e, a| Box::pin(crate::std::segment::segment_start_y(e, a).map(|r| r.map(KclValue::continue_))),
705            StdFnProps::default("std::sketch::segStartY"),
706        ),
707        ("sketch", "lastSegX") => (
708            |e, a| Box::pin(crate::std::segment::last_segment_x(e, a).map(|r| r.map(KclValue::continue_))),
709            StdFnProps::default("std::sketch::lastSegX").reads_regions_locally(),
710        ),
711        ("sketch", "lastSegY") => (
712            |e, a| Box::pin(crate::std::segment::last_segment_y(e, a).map(|r| r.map(KclValue::continue_))),
713            StdFnProps::default("std::sketch::lastSegY").reads_regions_locally(),
714        ),
715        ("sketch", "segLen") => (
716            |e, a| Box::pin(crate::std::segment::segment_length(e, a).map(|r| r.map(KclValue::continue_))),
717            StdFnProps::default("std::sketch::segLen"),
718        ),
719        ("sketch", "segAng") => (
720            |e, a| Box::pin(crate::std::segment::segment_angle(e, a).map(|r| r.map(KclValue::continue_))),
721            StdFnProps::default("std::sketch::segAng"),
722        ),
723        ("sketch", "tangentToEnd") => (
724            |e, a| Box::pin(crate::std::segment::tangent_to_end(e, a).map(|r| r.map(KclValue::continue_))),
725            StdFnProps::default("std::sketch::tangentToEnd"),
726        ),
727        ("sketch", "profileStart") => (
728            |e, a| Box::pin(crate::std::sketch::profile_start(e, a).map(|r| r.map(KclValue::continue_))),
729            StdFnProps::default("std::sketch::profileStart").reads_regions_locally(),
730        ),
731        ("sketch", "profileStartX") => (
732            |e, a| Box::pin(crate::std::sketch::profile_start_x(e, a).map(|r| r.map(KclValue::continue_))),
733            StdFnProps::default("std::sketch::profileStartX").reads_regions_locally(),
734        ),
735        ("sketch", "profileStartY") => (
736            |e, a| Box::pin(crate::std::sketch::profile_start_y(e, a).map(|r| r.map(KclValue::continue_))),
737            StdFnProps::default("std::sketch::profileStartY").reads_regions_locally(),
738        ),
739        ("sketch", "startSketchOn") => (
740            |e, a| Box::pin(crate::std::sketch::start_sketch_on(e, a).map(|r| r.map(KclValue::continue_))),
741            StdFnProps::default("std::sketch::startSketchOn"),
742        ),
743        ("sketch", "startProfile") => (
744            |e, a| Box::pin(crate::std::sketch::start_profile(e, a).map(|r| r.map(KclValue::continue_))),
745            StdFnProps::default("std::sketch::startProfile"),
746        ),
747        ("sketch", "involuteCircular") => (
748            |e, a| Box::pin(crate::std::sketch::involute_circular(e, a).map(|r| r.map(KclValue::continue_))),
749            StdFnProps::default("std::sketch::involuteCircular"),
750        ),
751        ("sketch", "line") => (
752            |e, a| Box::pin(crate::std::sketch::line(e, a).map(|r| r.map(KclValue::continue_))),
753            StdFnProps::default("std::sketch::line"),
754        ),
755        ("sketch", "xLine") => (
756            |e, a| Box::pin(crate::std::sketch::x_line(e, a).map(|r| r.map(KclValue::continue_))),
757            StdFnProps::default("std::sketch::xLine"),
758        ),
759        ("sketch", "yLine") => (
760            |e, a| Box::pin(crate::std::sketch::y_line(e, a).map(|r| r.map(KclValue::continue_))),
761            StdFnProps::default("std::sketch::yLine"),
762        ),
763        ("sketch", "angledLine") => (
764            |e, a| Box::pin(crate::std::sketch::angled_line(e, a).map(|r| r.map(KclValue::continue_))),
765            StdFnProps::default("std::sketch::angledLine"),
766        ),
767        ("sketch", "angledLineThatIntersects") => (
768            |e, a| Box::pin(crate::std::sketch::angled_line_that_intersects(e, a).map(|r| r.map(KclValue::continue_))),
769            StdFnProps::default("std::sketch::angledLineThatIntersects"),
770        ),
771        ("sketch", "close") => (
772            |e, a| Box::pin(crate::std::sketch::close(e, a).map(|r| r.map(KclValue::continue_))),
773            StdFnProps::default("std::sketch::close"),
774        ),
775        ("sketch", "arc") => (
776            |e, a| Box::pin(crate::std::sketch::arc(e, a).map(|r| r.map(KclValue::continue_))),
777            StdFnProps::default("std::sketch::arc"),
778        ),
779        ("sketch", "tangentialArc") => (
780            |e, a| Box::pin(crate::std::sketch::tangential_arc(e, a).map(|r| r.map(KclValue::continue_))),
781            StdFnProps::default("std::sketch::tangentialArc"),
782        ),
783        ("sketch", "bezierCurve") => (
784            |e, a| Box::pin(crate::std::sketch::bezier_curve(e, a).map(|r| r.map(KclValue::continue_))),
785            StdFnProps::default("std::sketch::bezierCurve"),
786        ),
787        ("sketch", "subtract2d") => (
788            |e, a| Box::pin(crate::std::sketch::subtract_2d(e, a).map(|r| r.map(KclValue::continue_))),
789            StdFnProps::default("std::sketch::subtract2d"),
790        ),
791        ("appearance", "hexString") => (
792            |e, a| Box::pin(crate::std::appearance::hex_string(e, a).map(|r| r.map(KclValue::continue_))),
793            StdFnProps::default("std::appearance::hexString"),
794        ),
795        ("solver", "point") => (
796            |e, a| Box::pin(crate::std::constraints::point(e, a).map(|r| r.map(KclValue::continue_))),
797            StdFnProps::default("std::solver::point"),
798        ),
799        ("solver", "line") => (
800            |e, a| Box::pin(crate::std::constraints::line(e, a).map(|r| r.map(KclValue::continue_))),
801            StdFnProps::default("std::solver::line"),
802        ),
803        ("solver", "arc") => (
804            |e, a| Box::pin(crate::std::constraints::arc(e, a).map(|r| r.map(KclValue::continue_))),
805            StdFnProps::default("std::solver::arc"),
806        ),
807        ("solver", "circle") => (
808            |e, a| Box::pin(crate::std::constraints::circle(e, a).map(|r| r.map(KclValue::continue_))),
809            StdFnProps::default("std::solver::circle"),
810        ),
811        ("solver", "controlPointSpline") => (
812            |e, a| Box::pin(crate::std::constraints::control_point_spline(e, a).map(|r| r.map(KclValue::continue_))),
813            StdFnProps::default("std::solver::controlPointSpline"),
814        ),
815        ("solver", "coincident") => (
816            |e, a| Box::pin(crate::std::constraints::coincident(e, a).map(|r| r.map(KclValue::continue_))),
817            StdFnProps::default("std::solver::coincident"),
818        ),
819        ("solver", "distance") => (
820            |e, a| Box::pin(crate::std::constraints::distance(e, a).map(|r| r.map(KclValue::continue_))),
821            StdFnProps::default("std::solver::distance"),
822        ),
823        ("solver", "radius") => (
824            |e, a| Box::pin(crate::std::constraints::radius(e, a).map(|r| r.map(KclValue::continue_))),
825            StdFnProps::default("std::solver::radius"),
826        ),
827        ("solver", "diameter") => (
828            |e, a| Box::pin(crate::std::constraints::diameter(e, a).map(|r| r.map(KclValue::continue_))),
829            StdFnProps::default("std::solver::diameter"),
830        ),
831        ("solver", "horizontalDistance") => (
832            |e, a| Box::pin(crate::std::constraints::horizontal_distance(e, a).map(|r| r.map(KclValue::continue_))),
833            StdFnProps::default("std::solver::horizontalDistance"),
834        ),
835        ("solver", "verticalDistance") => (
836            |e, a| Box::pin(crate::std::constraints::vertical_distance(e, a).map(|r| r.map(KclValue::continue_))),
837            StdFnProps::default("std::solver::verticalDistance"),
838        ),
839        ("solver", "equalLength") => (
840            |e, a| Box::pin(crate::std::constraints::equal_length(e, a).map(|r| r.map(KclValue::continue_))),
841            StdFnProps::default("std::solver::equalLength"),
842        ),
843        ("solver", "midpoint") => (
844            |e, a| Box::pin(crate::std::constraints::midpoint(e, a).map(|r| r.map(KclValue::continue_))),
845            StdFnProps::default("std::solver::midpoint"),
846        ),
847        ("solver", "equalRadius") => (
848            |e, a| Box::pin(crate::std::constraints::equal_radius(e, a).map(|r| r.map(KclValue::continue_))),
849            StdFnProps::default("std::solver::equalRadius"),
850        ),
851        ("solver", "angle") => (
852            |e, a| Box::pin(crate::std::constraints::angle(e, a).map(|r| r.map(KclValue::continue_))),
853            StdFnProps::default("std::solver::angle"),
854        ),
855        ("solver", "angleDimension") => (
856            |e, a| Box::pin(crate::std::constraints::angle_dimension(e, a).map(|r| r.map(KclValue::continue_))),
857            StdFnProps::default("std::solver::angleDimension"),
858        ),
859        ("solver", "tangent") => (
860            |e, a| Box::pin(crate::std::constraints::tangent(e, a).map(|r| r.map(KclValue::continue_))),
861            StdFnProps::default("std::solver::tangent"),
862        ),
863        ("solver", "symmetric") => (
864            |e, a| Box::pin(crate::std::constraints::symmetric(e, a).map(|r| r.map(KclValue::continue_))),
865            StdFnProps::default("std::solver::symmetric"),
866        ),
867        ("solver", "horizontal") => (
868            |e, a| Box::pin(crate::std::constraints::horizontal(e, a).map(|r| r.map(KclValue::continue_))),
869            StdFnProps::default("std::solver::horizontal"),
870        ),
871        ("solver", "parallel") => (
872            |e, a| Box::pin(crate::std::constraints::parallel(e, a).map(|r| r.map(KclValue::continue_))),
873            StdFnProps::default("std::solver::parallel"),
874        ),
875        ("solver", "perpendicular") => (
876            |e, a| Box::pin(crate::std::constraints::perpendicular(e, a).map(|r| r.map(KclValue::continue_))),
877            StdFnProps::default("std::solver::perpendicular"),
878        ),
879        ("solver", "vertical") => (
880            |e, a| Box::pin(crate::std::constraints::vertical(e, a).map(|r| r.map(KclValue::continue_))),
881            StdFnProps::default("std::solver::vertical"),
882        ),
883        ("sketch", "region") => (
884            |e, a| Box::pin(crate::std::sketch::region(e, a).map(|r| r.map(KclValue::continue_))),
885            StdFnProps::default("std::sketch::region"),
886        ),
887        ("solid", "isSurface") => (
888            |e, a| Box::pin(crate::std::surfaces::is_surface(e, a).map(|r| r.map(KclValue::continue_))),
889            StdFnProps::default("std::solid::isSurface"),
890        ),
891        ("solid", "isSolid") => (
892            |e, a| Box::pin(crate::std::surfaces::is_solid(e, a).map(|r| r.map(KclValue::continue_))),
893            StdFnProps::default("std::solid::isSolid"),
894        ),
895        ("solid", "deleteFace") => (
896            |e, a| Box::pin(crate::std::surfaces::delete_face(e, a).map(|r| r.map(KclValue::continue_))),
897            StdFnProps::default("std::solid::deleteFace"),
898        ),
899        ("solid", "blend") => (
900            |e, a| Box::pin(crate::std::surfaces::blend(e, a).map(|r| r.map(KclValue::continue_))),
901            StdFnProps::default("std::solid::blend"),
902        ),
903        ("solid", "joinSurfaces") => (
904            |e, a| Box::pin(crate::std::surfaces::join(e, a).map(|r| r.map(KclValue::continue_))),
905            StdFnProps::default("std::solid::joinSurfaces"),
906        ),
907        ("view", "oriented") => (
908            |e, a| Box::pin(crate::std::view::oriented(e, a).map(|r| r.map(KclValue::continue_))),
909            StdFnProps::default("std::view::oriented"),
910        ),
911        ("view", "directed") => (
912            |e, a| Box::pin(crate::std::view::directed(e, a).map(|r| r.map(KclValue::continue_))),
913            StdFnProps::default("std::view::directed"),
914        ),
915        ("view", "named") => (
916            |e, a| Box::pin(crate::std::view::named(e, a).map(|r| r.map(KclValue::continue_))),
917            StdFnProps::default("std::view::named"),
918        ),
919        ("operation", "facing") => (
920            |e, a| Box::pin(crate::std::operation::facing(e, a).map(|r| r.map(KclValue::continue_))),
921            StdFnProps::default("std::operation::facing"),
922        ),
923        (module, fn_name) => {
924            panic!("No implementation found for {module}::{fn_name}, please add it to this big match statement")
925        }
926    }
927}
928
929pub(crate) fn std_ty(path: &str, fn_name: &str) -> (PrimitiveType, StdFnProps) {
930    match (path, fn_name) {
931        ("types", "Segment") => (PrimitiveType::Segment, StdFnProps::default("std::types::Segment")),
932        ("types", "Sketch") => (PrimitiveType::Sketch, StdFnProps::default("std::types::Sketch")),
933        ("types", "Solid") => (PrimitiveType::Solid, StdFnProps::default("std::types::Solid")),
934        ("types", "Plane") => (PrimitiveType::Plane, StdFnProps::default("std::types::Plane")),
935        ("types", "Face") => (PrimitiveType::Face, StdFnProps::default("std::types::Face")),
936        ("types", "GdtAnnotation") => (
937            PrimitiveType::GdtAnnotation,
938            StdFnProps::default("std::types::GdtAnnotation"),
939        ),
940        ("types", "Helix") => (PrimitiveType::Helix, StdFnProps::default("std::types::Helix")),
941        ("types", "Edge") => (PrimitiveType::Edge, StdFnProps::default("std::types::Edge")),
942        ("types", "Axis2d") => (PrimitiveType::Axis2d, StdFnProps::default("std::types::Axis2d")),
943        ("types", "Axis3d") => (PrimitiveType::Axis3d, StdFnProps::default("std::types::Axis3d")),
944        ("types", "TaggedEdge") => (PrimitiveType::TaggedEdge, StdFnProps::default("std::types::TaggedEdge")),
945        ("types", "TaggedFace") => (PrimitiveType::TaggedFace, StdFnProps::default("std::types::TaggedFace")),
946        ("types", "BoundedEdge") => (
947            PrimitiveType::BoundedEdge,
948            StdFnProps::default("std::types::BoundedEdge"),
949        ),
950        ("view", "CameraView") => (PrimitiveType::CameraView, StdFnProps::default("std::view::CameraView")),
951        ("view", "NamedView") => (PrimitiveType::NamedView, StdFnProps::default("std::view::NamedView")),
952        _ => unreachable!(),
953    }
954}
955
956/// The default tolerance for modeling commands in millimeters.
957const DEFAULT_TOLERANCE_MM: f64 = 0.0000001;
958
959/// The default tolerance for testing the equality of points.
960/// WARNING: This must match the tolerance in engine/cpp/engine/scene/constants.h
961#[allow(clippy::excessive_precision)]
962const EQUAL_POINTS_DIST_EPSILON: f64 = 2.3283064365386962890625e-10;
963
964#[derive(Debug, Clone, Copy, PartialEq, Eq)]
965pub(crate) enum CircularDirection {
966    Counterclockwise,
967    Clockwise,
968}
969
970impl CircularDirection {
971    pub fn is_clockwise(self) -> bool {
972        match self {
973            CircularDirection::Counterclockwise => false,
974            CircularDirection::Clockwise => true,
975        }
976    }
977}