Refactoring: use typed versions of args getters (#7262)

* Replace uses of get_unlabeled_kw_arg with _typed version

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Remove more untyped arg getters

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-05-29 16:48:47 +12:00
committed by GitHub
parent c4d2e33a99
commit 87e3588ceb
18 changed files with 84 additions and 96 deletions

View File

@ -1232,7 +1232,7 @@ secondSketch = startSketchOn(part001, face = '')
let err = err.as_kcl_error().unwrap(); let err = err.as_kcl_error().unwrap();
assert_eq!( assert_eq!(
err.message(), err.message(),
"The arg face was given, but it was the wrong type. It should be type FaceTag but it was string" "This function expected the input argument to be tag but it's actually of type string"
); );
} }

View File

@ -44,6 +44,10 @@ impl RuntimeType {
RuntimeType::Primitive(PrimitiveType::Sketch) RuntimeType::Primitive(PrimitiveType::Sketch)
} }
pub fn sketch_or_surface() -> Self {
RuntimeType::Union(vec![Self::sketch(), Self::plane(), Self::face()])
}
/// `[Sketch; 1+]` /// `[Sketch; 1+]`
pub fn sketches() -> Self { pub fn sketches() -> Self {
RuntimeType::Array( RuntimeType::Array(

View File

@ -28,6 +28,8 @@ use crate::{
ModuleId, ModuleId,
}; };
use super::fillet::EdgeReference;
const ERROR_STRING_SKETCH_TO_SOLID_HELPER: &str = const ERROR_STRING_SKETCH_TO_SOLID_HELPER: &str =
"You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`"; "You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`";
@ -214,10 +216,10 @@ impl Args {
/// Get a labelled keyword arg, check it's an array, and return all items in the array /// Get a labelled keyword arg, check it's an array, and return all items in the array
/// plus their source range. /// plus their source range.
pub(crate) fn kw_arg_array_and_source<T>(&self, label: &str) -> Result<Vec<(T, SourceRange)>, KclError> pub(crate) fn kw_arg_edge_array_and_source(
where &self,
T: for<'a> FromKclValue<'a>, label: &str,
{ ) -> Result<Vec<(EdgeReference, SourceRange)>, KclError> {
let Some(arg) = self.kw_args.labeled.get(label) else { let Some(arg) = self.kw_args.labeled.get(label) else {
let err = KclError::Semantic(KclErrorDetails::new( let err = KclError::Semantic(KclErrorDetails::new(
format!("This function requires a keyword argument '{label}'"), format!("This function requires a keyword argument '{label}'"),
@ -233,11 +235,7 @@ impl Args {
let source = SourceRange::from(item); let source = SourceRange::from(item);
let val = FromKclValue::from_kcl_val(item).ok_or_else(|| { let val = FromKclValue::from_kcl_val(item).ok_or_else(|| {
KclError::Semantic(KclErrorDetails::new( KclError::Semantic(KclErrorDetails::new(
format!( format!("Expected an Edge but found {}", arg.value.human_friendly_type()),
"Expected a {} but found {}",
tynm::type_name::<T>(),
arg.value.human_friendly_type()
),
arg.source_ranges(), arg.source_ranges(),
)) ))
})?; })?;
@ -259,30 +257,6 @@ impl Args {
}) })
} }
/// Get the unlabeled keyword argument. If not set, returns Err. If it
/// can't be converted to the given type, returns Err.
pub(crate) fn get_unlabeled_kw_arg<'a, T>(&'a self, label: &str) -> Result<T, KclError>
where
T: FromKclValue<'a>,
{
let arg = self
.unlabeled_kw_arg_unconverted()
.ok_or(KclError::Semantic(KclErrorDetails::new(
format!("This function requires a value for the special unlabeled first parameter, '{label}'"),
vec![self.source_range],
)))?;
T::from_kcl_val(&arg.value).ok_or_else(|| {
let expected_type_name = tynm::type_name::<T>();
let actual_type_name = arg.value.human_friendly_type();
let message = format!("This function expected the input argument to be of type {expected_type_name} but it's actually of type {actual_type_name}");
KclError::Semantic(KclErrorDetails::new(
message,
arg.source_ranges(),
))
})
}
/// Get the unlabeled keyword argument. If not set, returns Err. If it /// Get the unlabeled keyword argument. If not set, returns Err. If it
/// can't be converted to the given type, returns Err. /// can't be converted to the given type, returns Err.
pub(crate) fn get_unlabeled_kw_arg_typed<T>( pub(crate) fn get_unlabeled_kw_arg_typed<T>(

View File

@ -70,7 +70,7 @@ async fn call_map_closure(
pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let array: Vec<KclValue> = args.get_unlabeled_kw_arg_typed("array", &RuntimeType::any_array(), exec_state)?; let array: Vec<KclValue> = args.get_unlabeled_kw_arg_typed("array", &RuntimeType::any_array(), exec_state)?;
let f: &FunctionSource = args.get_kw_arg("f")?; let f: &FunctionSource = args.get_kw_arg("f")?;
let initial: KclValue = args.get_kw_arg("initial")?; let initial: KclValue = args.get_kw_arg_typed("initial", &RuntimeType::any(), exec_state)?;
inner_reduce(array, initial, f, exec_state, &args).await inner_reduce(array, initial, f, exec_state, &args).await
} }
@ -128,7 +128,7 @@ async fn call_reduce_closure(
pub async fn push(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn push(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (mut array, ty) = args.get_unlabeled_kw_arg_array_and_type("array", exec_state)?; let (mut array, ty) = args.get_unlabeled_kw_arg_array_and_type("array", exec_state)?;
let item: KclValue = args.get_kw_arg("item")?; let item: KclValue = args.get_kw_arg_typed("item", &RuntimeType::any(), exec_state)?;
array.push(item); array.push(item);

View File

@ -6,7 +6,7 @@ use kcl_derive_docs::stdlib;
use super::args::TyF64; use super::args::TyF64;
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
execution::{ExecState, KclValue}, execution::{types::RuntimeType, ExecState, KclValue},
std::Args, std::Args,
}; };
@ -20,24 +20,24 @@ async fn _assert(value: bool, message: &str, args: &Args) -> Result<(), KclError
Ok(()) Ok(())
} }
pub async fn assert_is(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn assert_is(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let actual = args.get_unlabeled_kw_arg("actual")?; let actual = args.get_unlabeled_kw_arg_typed("actual", &RuntimeType::bool(), exec_state)?;
let error = args.get_kw_arg_opt("error")?; let error = args.get_kw_arg_opt_typed("error", &RuntimeType::string(), exec_state)?;
inner_assert_is(actual, error, &args).await?; inner_assert_is(actual, error, &args).await?;
Ok(KclValue::none()) Ok(KclValue::none())
} }
/// Check that the provided value is true, or raise a [KclError] /// Check that the provided value is true, or raise a [KclError]
/// with the provided description. /// with the provided description.
pub async fn assert(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn assert(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let actual = args.get_unlabeled_kw_arg("actual")?; let actual = args.get_unlabeled_kw_arg_typed("actual", &RuntimeType::num_any(), exec_state)?;
let gt = args.get_kw_arg_opt("isGreaterThan")?; let gt = args.get_kw_arg_opt_typed("isGreaterThan", &RuntimeType::num_any(), exec_state)?;
let lt = args.get_kw_arg_opt("isLessThan")?; let lt = args.get_kw_arg_opt_typed("isLessThan", &RuntimeType::num_any(), exec_state)?;
let gte = args.get_kw_arg_opt("isGreaterThanOrEqual")?; let gte = args.get_kw_arg_opt_typed("isGreaterThanOrEqual", &RuntimeType::num_any(), exec_state)?;
let lte = args.get_kw_arg_opt("isLessThanOrEqual")?; let lte = args.get_kw_arg_opt_typed("isLessThanOrEqual", &RuntimeType::num_any(), exec_state)?;
let eq = args.get_kw_arg_opt("isEqualTo")?; let eq = args.get_kw_arg_opt_typed("isEqualTo", &RuntimeType::num_any(), exec_state)?;
let tolerance = args.get_kw_arg_opt("tolerance")?; let tolerance = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::num_any(), exec_state)?;
let error = args.get_kw_arg_opt("error")?; let error = args.get_kw_arg_opt_typed("error", &RuntimeType::string(), exec_state)?;
inner_assert(actual, gt, lt, gte, lte, eq, tolerance, error, &args).await?; inner_assert(actual, gt, lt, gte, lte, eq, tolerance, error, &args).await?;
Ok(KclValue::none()) Ok(KclValue::none())
} }

View File

@ -21,7 +21,7 @@ pub(crate) const DEFAULT_TOLERANCE: f64 = 0.0000001;
pub async fn chamfer(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn chamfer(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let solid = args.get_unlabeled_kw_arg_typed("solid", &RuntimeType::Primitive(PrimitiveType::Solid), exec_state)?; let solid = args.get_unlabeled_kw_arg_typed("solid", &RuntimeType::Primitive(PrimitiveType::Solid), exec_state)?;
let length: TyF64 = args.get_kw_arg_typed("length", &RuntimeType::length(), exec_state)?; let length: TyF64 = args.get_kw_arg_typed("length", &RuntimeType::length(), exec_state)?;
let tags = args.kw_arg_array_and_source::<EdgeReference>("tags")?; let tags = args.kw_arg_edge_array_and_source("tags")?;
let tag = args.get_kw_arg_opt("tag")?; let tag = args.get_kw_arg_opt("tag")?;
super::fillet::validate_unique(&tags)?; super::fillet::validate_unique(&tags)?;

View File

@ -31,7 +31,7 @@ use crate::{
pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?; let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
let length: TyF64 = args.get_kw_arg_typed("length", &RuntimeType::length(), exec_state)?; let length: TyF64 = args.get_kw_arg_typed("length", &RuntimeType::length(), exec_state)?;
let symmetric = args.get_kw_arg_opt("symmetric")?; let symmetric = args.get_kw_arg_opt_typed("symmetric", &RuntimeType::bool(), exec_state)?;
let bidirectional_length: Option<TyF64> = let bidirectional_length: Option<TyF64> =
args.get_kw_arg_opt_typed("bidirectionalLength", &RuntimeType::length(), exec_state)?; args.get_kw_arg_opt_typed("bidirectionalLength", &RuntimeType::length(), exec_state)?;
let tag_start = args.get_kw_arg_opt("tagStart")?; let tag_start = args.get_kw_arg_opt("tagStart")?;

View File

@ -63,7 +63,7 @@ pub async fn fillet(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
let solid = args.get_unlabeled_kw_arg_typed("solid", &RuntimeType::solid(), exec_state)?; let solid = args.get_unlabeled_kw_arg_typed("solid", &RuntimeType::solid(), exec_state)?;
let radius: TyF64 = args.get_kw_arg_typed("radius", &RuntimeType::length(), exec_state)?; let radius: TyF64 = args.get_kw_arg_typed("radius", &RuntimeType::length(), exec_state)?;
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?; let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
let tags = args.kw_arg_array_and_source::<EdgeReference>("tags")?; let tags = args.kw_arg_edge_array_and_source("tags")?;
let tag = args.get_kw_arg_opt("tag")?; let tag = args.get_kw_arg_opt("tag")?;
// Run the function. // Run the function.

View File

@ -18,7 +18,7 @@ use crate::{
pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let angle_start: TyF64 = args.get_kw_arg_typed("angleStart", &RuntimeType::degrees(), exec_state)?; let angle_start: TyF64 = args.get_kw_arg_typed("angleStart", &RuntimeType::degrees(), exec_state)?;
let revolutions: TyF64 = args.get_kw_arg_typed("revolutions", &RuntimeType::count(), exec_state)?; let revolutions: TyF64 = args.get_kw_arg_typed("revolutions", &RuntimeType::count(), exec_state)?;
let ccw = args.get_kw_arg_opt("ccw")?; let ccw = args.get_kw_arg_opt_typed("ccw", &RuntimeType::bool(), exec_state)?;
let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?; let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?;
let axis: Option<Axis3dOrEdgeReference> = args.get_kw_arg_opt_typed( let axis: Option<Axis3dOrEdgeReference> = args.get_kw_arg_opt_typed(
"axis", "axis",

View File

@ -24,14 +24,17 @@ const DEFAULT_V_DEGREE: u32 = 2;
pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?; let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
let v_degree: NonZeroU32 = args let v_degree: NonZeroU32 = args
.get_kw_arg_opt("vDegree")? .get_kw_arg_opt_typed("vDegree", &RuntimeType::count(), exec_state)?
.unwrap_or(NonZeroU32::new(DEFAULT_V_DEGREE).unwrap()); .unwrap_or(NonZeroU32::new(DEFAULT_V_DEGREE).unwrap());
// Attempt to approximate rational curves (such as arcs) using a bezier. // Attempt to approximate rational curves (such as arcs) using a bezier.
// This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios // This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios
// Over time, this field won't be necessary. // Over time, this field won't be necessary.
let bez_approximate_rational = args.get_kw_arg_opt("bezApproximateRational")?.unwrap_or(false); let bez_approximate_rational = args
.get_kw_arg_opt_typed("bezApproximateRational", &RuntimeType::bool(), exec_state)?
.unwrap_or(false);
// This can be set to override the automatically determined topological base curve, which is usually the first section encountered. // This can be set to override the automatically determined topological base curve, which is usually the first section encountered.
let base_curve_index: Option<u32> = args.get_kw_arg_opt("baseCurveIndex")?; let base_curve_index: Option<u32> =
args.get_kw_arg_opt_typed("baseCurveIndex", &RuntimeType::count(), exec_state)?;
// Tolerance for the loft operation. // Tolerance for the loft operation.
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?; let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
let tag_start = args.get_kw_arg_opt("tagStart")?; let tag_start = args.get_kw_arg_opt("tagStart")?;

View File

@ -37,9 +37,9 @@ const MUST_HAVE_ONE_INSTANCE: &str = "There must be at least 1 instance of your
/// Repeat some 3D solid, changing each repetition slightly. /// Repeat some 3D solid, changing each repetition slightly.
pub async fn pattern_transform(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn pattern_transform(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?; let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
let instances: u32 = args.get_kw_arg("instances")?; let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
let transform: &FunctionSource = args.get_kw_arg("transform")?; let transform: &FunctionSource = args.get_kw_arg("transform")?;
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?; let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
let solids = inner_pattern_transform(solids, instances, transform, use_original, exec_state, &args).await?; let solids = inner_pattern_transform(solids, instances, transform, use_original, exec_state, &args).await?;
Ok(solids.into()) Ok(solids.into())
@ -48,9 +48,9 @@ pub async fn pattern_transform(exec_state: &mut ExecState, args: Args) -> Result
/// Repeat some 2D sketch, changing each repetition slightly. /// Repeat some 2D sketch, changing each repetition slightly.
pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?; let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
let instances: u32 = args.get_kw_arg("instances")?; let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
let transform: &FunctionSource = args.get_kw_arg("transform")?; let transform: &FunctionSource = args.get_kw_arg("transform")?;
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?; let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
let sketches = inner_pattern_transform_2d(sketches, instances, transform, use_original, exec_state, &args).await?; let sketches = inner_pattern_transform_2d(sketches, instances, transform, use_original, exec_state, &args).await?;
Ok(sketches.into()) Ok(sketches.into())
@ -521,7 +521,7 @@ mod tests {
/// A linear pattern on a 2D sketch. /// A linear pattern on a 2D sketch.
pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?; let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
let instances: u32 = args.get_kw_arg("instances")?; let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?; let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?;
let axis: Axis2dOrPoint2d = args.get_kw_arg_typed( let axis: Axis2dOrPoint2d = args.get_kw_arg_typed(
"axis", "axis",
@ -531,7 +531,7 @@ pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result
]), ]),
exec_state, exec_state,
)?; )?;
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?; let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
let axis = axis.to_point2d(); let axis = axis.to_point2d();
if axis[0].n == 0.0 && axis[1].n == 0.0 { if axis[0].n == 0.0 && axis[1].n == 0.0 {
@ -622,7 +622,7 @@ async fn inner_pattern_linear_2d(
/// A linear pattern on a 3D model. /// A linear pattern on a 3D model.
pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?; let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
let instances: u32 = args.get_kw_arg("instances")?; let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?; let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?;
let axis: Axis3dOrPoint3d = args.get_kw_arg_typed( let axis: Axis3dOrPoint3d = args.get_kw_arg_typed(
"axis", "axis",
@ -632,7 +632,7 @@ pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result
]), ]),
exec_state, exec_state,
)?; )?;
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?; let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
let axis = axis.to_point3d(); let axis = axis.to_point3d();
if axis[0].n == 0.0 && axis[1].n == 0.0 && axis[2].n == 0.0 { if axis[0].n == 0.0 && axis[1].n == 0.0 && axis[2].n == 0.0 {
@ -790,11 +790,11 @@ impl CircularPattern {
/// A circular pattern on a 2D sketch. /// A circular pattern on a 2D sketch.
pub async fn pattern_circular_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn pattern_circular_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?; let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
let instances: u32 = args.get_kw_arg("instances")?; let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
let center: [TyF64; 2] = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?; let center: [TyF64; 2] = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?;
let arc_degrees: Option<TyF64> = args.get_kw_arg_opt_typed("arcDegrees", &RuntimeType::degrees(), exec_state)?; let arc_degrees: Option<TyF64> = args.get_kw_arg_opt_typed("arcDegrees", &RuntimeType::degrees(), exec_state)?;
let rotate_duplicates: Option<bool> = args.get_kw_arg_opt("rotateDuplicates")?; let rotate_duplicates = args.get_kw_arg_opt_typed("rotateDuplicates", &RuntimeType::bool(), exec_state)?;
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?; let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
let sketches = inner_pattern_circular_2d( let sketches = inner_pattern_circular_2d(
sketches, sketches,
@ -915,10 +915,10 @@ pub async fn pattern_circular_3d(exec_state: &mut ExecState, args: Args) -> Resu
// The arc angle (in degrees) to place the repetitions. Must be greater than 0. // The arc angle (in degrees) to place the repetitions. Must be greater than 0.
let arc_degrees: Option<TyF64> = args.get_kw_arg_opt_typed("arcDegrees", &RuntimeType::degrees(), exec_state)?; let arc_degrees: Option<TyF64> = args.get_kw_arg_opt_typed("arcDegrees", &RuntimeType::degrees(), exec_state)?;
// Whether or not to rotate the duplicates as they are copied. // Whether or not to rotate the duplicates as they are copied.
let rotate_duplicates: Option<bool> = args.get_kw_arg_opt("rotateDuplicates")?; let rotate_duplicates = args.get_kw_arg_opt_typed("rotateDuplicates", &RuntimeType::bool(), exec_state)?;
// If the target being patterned is itself a pattern, then, should you use the original solid, // If the target being patterned is itself a pattern, then, should you use the original solid,
// or the pattern? // or the pattern?
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?; let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
let solids = inner_pattern_circular_3d( let solids = inner_pattern_circular_3d(
solids, solids,

View File

@ -12,7 +12,7 @@ use crate::{
/// Offset a plane by a distance along its normal. /// Offset a plane by a distance along its normal.
pub async fn offset_plane(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn offset_plane(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let std_plane = args.get_unlabeled_kw_arg("plane")?; let std_plane = args.get_unlabeled_kw_arg_typed("plane", &RuntimeType::plane(), exec_state)?;
let offset: TyF64 = args.get_kw_arg_typed("offset", &RuntimeType::length(), exec_state)?; let offset: TyF64 = args.get_kw_arg_typed("offset", &RuntimeType::length(), exec_state)?;
let plane = inner_offset_plane(std_plane, offset, exec_state, &args).await?; let plane = inner_offset_plane(std_plane, offset, exec_state, &args).await?;
Ok(KclValue::Plane { value: Box::new(plane) }) Ok(KclValue::Plane { value: Box::new(plane) })

View File

@ -37,7 +37,7 @@ pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?; let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
let tag_start = args.get_kw_arg_opt("tagStart")?; let tag_start = args.get_kw_arg_opt("tagStart")?;
let tag_end = args.get_kw_arg_opt("tagEnd")?; let tag_end = args.get_kw_arg_opt("tagEnd")?;
let symmetric = args.get_kw_arg_opt("symmetric")?; let symmetric = args.get_kw_arg_opt_typed("symmetric", &RuntimeType::bool(), exec_state)?;
let bidirectional_angle: Option<TyF64> = let bidirectional_angle: Option<TyF64> =
args.get_kw_arg_opt_typed("bidirectionalAngle", &RuntimeType::angle(), exec_state)?; args.get_kw_arg_opt_typed("bidirectionalAngle", &RuntimeType::angle(), exec_state)?;

View File

@ -16,7 +16,7 @@ use crate::{
/// Returns the point at the end of the given segment. /// Returns the point at the end of the given segment.
pub async fn segment_end(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_end(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let pt = inner_segment_end(&tag, exec_state, args.clone())?; let pt = inner_segment_end(&tag, exec_state, args.clone())?;
args.make_kcl_val_from_point([pt[0].n, pt[1].n], pt[0].ty.clone()) args.make_kcl_val_from_point([pt[0].n, pt[1].n], pt[0].ty.clone())
@ -72,7 +72,7 @@ fn inner_segment_end(tag: &TagIdentifier, exec_state: &mut ExecState, args: Args
/// Returns the segment end of x. /// Returns the segment end of x.
pub async fn segment_end_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_end_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let result = inner_segment_end_x(&tag, exec_state, args.clone())?; let result = inner_segment_end_x(&tag, exec_state, args.clone())?;
Ok(args.make_user_val_from_f64_with_type(result)) Ok(args.make_user_val_from_f64_with_type(result))
@ -113,7 +113,7 @@ fn inner_segment_end_x(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
/// Returns the segment end of y. /// Returns the segment end of y.
pub async fn segment_end_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_end_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let result = inner_segment_end_y(&tag, exec_state, args.clone())?; let result = inner_segment_end_y(&tag, exec_state, args.clone())?;
Ok(args.make_user_val_from_f64_with_type(result)) Ok(args.make_user_val_from_f64_with_type(result))
@ -155,7 +155,7 @@ fn inner_segment_end_y(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
/// Returns the point at the start of the given segment. /// Returns the point at the start of the given segment.
pub async fn segment_start(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_start(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let pt = inner_segment_start(&tag, exec_state, args.clone())?; let pt = inner_segment_start(&tag, exec_state, args.clone())?;
args.make_kcl_val_from_point([pt[0].n, pt[1].n], pt[0].ty.clone()) args.make_kcl_val_from_point([pt[0].n, pt[1].n], pt[0].ty.clone())
@ -211,7 +211,7 @@ fn inner_segment_start(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
/// Returns the segment start of x. /// Returns the segment start of x.
pub async fn segment_start_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_start_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let result = inner_segment_start_x(&tag, exec_state, args.clone())?; let result = inner_segment_start_x(&tag, exec_state, args.clone())?;
Ok(args.make_user_val_from_f64_with_type(result)) Ok(args.make_user_val_from_f64_with_type(result))
@ -252,7 +252,7 @@ fn inner_segment_start_x(tag: &TagIdentifier, exec_state: &mut ExecState, args:
/// Returns the segment start of y. /// Returns the segment start of y.
pub async fn segment_start_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_start_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let result = inner_segment_start_y(&tag, exec_state, args.clone())?; let result = inner_segment_start_y(&tag, exec_state, args.clone())?;
Ok(args.make_user_val_from_f64_with_type(result)) Ok(args.make_user_val_from_f64_with_type(result))
@ -385,7 +385,7 @@ fn inner_last_segment_y(sketch: Sketch, args: Args) -> Result<TyF64, KclError> {
/// Returns the length of the segment. /// Returns the length of the segment.
pub async fn segment_length(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_length(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let result = inner_segment_length(&tag, exec_state, args.clone())?; let result = inner_segment_length(&tag, exec_state, args.clone())?;
Ok(args.make_user_val_from_f64_with_type(result)) Ok(args.make_user_val_from_f64_with_type(result))
} }
@ -431,7 +431,7 @@ fn inner_segment_length(tag: &TagIdentifier, exec_state: &mut ExecState, args: A
/// Returns the angle of the segment. /// Returns the angle of the segment.
pub async fn segment_angle(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn segment_angle(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let result = inner_segment_angle(&tag, exec_state, args.clone())?; let result = inner_segment_angle(&tag, exec_state, args.clone())?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees()))) Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees())))
@ -476,7 +476,7 @@ fn inner_segment_angle(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
/// Returns the angle coming out of the end of the segment in degrees. /// Returns the angle coming out of the end of the segment in degrees.
pub async fn tangent_to_end(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn tangent_to_end(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag")?; let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
let result = inner_tangent_to_end(&tag, exec_state, args.clone()).await?; let result = inner_tangent_to_end(&tag, exec_state, args.clone()).await?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees()))) Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees())))

View File

@ -43,7 +43,8 @@ pub enum SketchOrSurface {
/// Sketch a circle. /// Sketch a circle.
pub async fn circle(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn circle(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch_or_surface = args.get_unlabeled_kw_arg("sketchOrSurface")?; let sketch_or_surface =
args.get_unlabeled_kw_arg_typed("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
let center = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?; let center = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?;
let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?; let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?;
let diameter: Option<TyF64> = args.get_kw_arg_opt_typed("diameter", &RuntimeType::length(), exec_state)?; let diameter: Option<TyF64> = args.get_kw_arg_opt_typed("diameter", &RuntimeType::length(), exec_state)?;
@ -129,13 +130,14 @@ async fn inner_circle(
/// Sketch a 3-point circle. /// Sketch a 3-point circle.
pub async fn circle_three_point(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn circle_three_point(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch_surface_or_group = args.get_unlabeled_kw_arg("sketch_surface_or_group")?; let sketch_or_surface =
args.get_unlabeled_kw_arg_typed("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
let p1 = args.get_kw_arg_typed("p1", &RuntimeType::point2d(), exec_state)?; let p1 = args.get_kw_arg_typed("p1", &RuntimeType::point2d(), exec_state)?;
let p2 = args.get_kw_arg_typed("p2", &RuntimeType::point2d(), exec_state)?; let p2 = args.get_kw_arg_typed("p2", &RuntimeType::point2d(), exec_state)?;
let p3 = args.get_kw_arg_typed("p3", &RuntimeType::point2d(), exec_state)?; let p3 = args.get_kw_arg_typed("p3", &RuntimeType::point2d(), exec_state)?;
let tag = args.get_kw_arg_opt("tag")?; let tag = args.get_kw_arg_opt("tag")?;
let sketch = inner_circle_three_point(sketch_surface_or_group, p1, p2, p3, tag, exec_state, args).await?; let sketch = inner_circle_three_point(sketch_or_surface, p1, p2, p3, tag, exec_state, args).await?;
Ok(KclValue::Sketch { Ok(KclValue::Sketch {
value: Box::new(sketch), value: Box::new(sketch),
}) })
@ -257,14 +259,15 @@ pub enum PolygonType {
/// Create a regular polygon with the specified number of sides and radius. /// Create a regular polygon with the specified number of sides and radius.
pub async fn polygon(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn polygon(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch_surface_or_group = args.get_unlabeled_kw_arg("sketchOrSurface")?; let sketch_or_surface =
args.get_unlabeled_kw_arg_typed("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
let radius: TyF64 = args.get_kw_arg_typed("radius", &RuntimeType::length(), exec_state)?; let radius: TyF64 = args.get_kw_arg_typed("radius", &RuntimeType::length(), exec_state)?;
let num_sides: TyF64 = args.get_kw_arg_typed("numSides", &RuntimeType::count(), exec_state)?; let num_sides: TyF64 = args.get_kw_arg_typed("numSides", &RuntimeType::count(), exec_state)?;
let center = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?; let center = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?;
let inscribed = args.get_kw_arg_opt_typed("inscribed", &RuntimeType::bool(), exec_state)?; let inscribed = args.get_kw_arg_opt_typed("inscribed", &RuntimeType::bool(), exec_state)?;
let sketch = inner_polygon( let sketch = inner_polygon(
sketch_surface_or_group, sketch_or_surface,
radius, radius,
num_sides.n as u64, num_sides.n as u64,
center, center,

View File

@ -107,7 +107,7 @@ pub async fn involute_circular(exec_state: &mut ExecState, args: Args) -> Result
let start_radius: TyF64 = args.get_kw_arg_typed("startRadius", &RuntimeType::length(), exec_state)?; let start_radius: TyF64 = args.get_kw_arg_typed("startRadius", &RuntimeType::length(), exec_state)?;
let end_radius: TyF64 = args.get_kw_arg_typed("endRadius", &RuntimeType::length(), exec_state)?; let end_radius: TyF64 = args.get_kw_arg_typed("endRadius", &RuntimeType::length(), exec_state)?;
let angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::angle(), exec_state)?; let angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::angle(), exec_state)?;
let reverse = args.get_kw_arg_opt("reverse")?; let reverse = args.get_kw_arg_opt_typed("reverse", &RuntimeType::bool(), exec_state)?;
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?; let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
let new_sketch = let new_sketch =
inner_involute_circular(sketch, start_radius, end_radius, angle, reverse, tag, exec_state, args).await?; inner_involute_circular(sketch, start_radius, end_radius, angle, reverse, tag, exec_state, args).await?;
@ -839,9 +839,10 @@ async fn inner_angled_line_to_y(
pub async fn angled_line_that_intersects(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn angled_line_that_intersects(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketch = let sketch =
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?; args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
let angle: TyF64 = args.get_kw_arg("angle")?; let angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::angle(), exec_state)?;
let intersect_tag: TagIdentifier = args.get_kw_arg("intersectTag")?; let intersect_tag: TagIdentifier =
let offset: Option<TyF64> = args.get_kw_arg_opt("offset")?; args.get_kw_arg_typed("intersectTag", &RuntimeType::tag_identifier(), exec_state)?;
let offset = args.get_kw_arg_opt_typed("offset", &RuntimeType::length(), exec_state)?;
let tag: Option<TagNode> = args.get_kw_arg_opt("tag")?; let tag: Option<TagNode> = args.get_kw_arg_opt("tag")?;
let new_sketch = let new_sketch =
inner_angled_line_that_intersects(sketch, angle, intersect_tag, offset, tag, exec_state, args).await?; inner_angled_line_that_intersects(sketch, angle, intersect_tag, offset, tag, exec_state, args).await?;
@ -963,7 +964,7 @@ pub async fn start_sketch_on(exec_state: &mut ExecState, args: Args) -> Result<K
&RuntimeType::Union(vec![RuntimeType::solid(), RuntimeType::plane()]), &RuntimeType::Union(vec![RuntimeType::solid(), RuntimeType::plane()]),
exec_state, exec_state,
)?; )?;
let face = args.get_kw_arg_opt("face")?; let face = args.get_kw_arg_opt_typed("face", &RuntimeType::tag(), exec_state)?;
match inner_start_sketch_on(data, face, exec_state, &args).await? { match inner_start_sketch_on(data, face, exec_state, &args).await? {
SketchSurface::Plane(value) => Ok(KclValue::Plane { value }), SketchSurface::Plane(value) => Ok(KclValue::Plane { value }),
@ -1266,8 +1267,11 @@ async fn make_sketch_plane_from_orientation(
/// Start a new profile at a given point. /// Start a new profile at a given point.
pub async fn start_profile(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn start_profile(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
// let (start, sketch_surface, tag) = args.get_data_and_sketch_surface()?; let sketch_surface = args.get_unlabeled_kw_arg_typed(
let sketch_surface = args.get_unlabeled_kw_arg("startProfileOn")?; "startProfileOn",
&RuntimeType::Union(vec![RuntimeType::plane(), RuntimeType::face()]),
exec_state,
)?;
let start: [TyF64; 2] = args.get_kw_arg_typed("at", &RuntimeType::point2d(), exec_state)?; let start: [TyF64; 2] = args.get_kw_arg_typed("at", &RuntimeType::point2d(), exec_state)?;
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?; let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;

View File

@ -35,7 +35,7 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
&RuntimeType::Union(vec![RuntimeType::sketch(), RuntimeType::helix()]), &RuntimeType::Union(vec![RuntimeType::sketch(), RuntimeType::helix()]),
exec_state, exec_state,
)?; )?;
let sectional = args.get_kw_arg_opt("sectional")?; let sectional = args.get_kw_arg_opt_typed("sectional", &RuntimeType::bool(), exec_state)?;
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?; let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
let relative_to: Option<String> = args.get_kw_arg_opt_typed("relativeTo", &RuntimeType::string(), exec_state)?; let relative_to: Option<String> = args.get_kw_arg_opt_typed("relativeTo", &RuntimeType::string(), exec_state)?;
let tag_start = args.get_kw_arg_opt("tagStart")?; let tag_start = args.get_kw_arg_opt("tagStart")?;

View File

@ -33,7 +33,7 @@ pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
let scale_x: Option<TyF64> = args.get_kw_arg_opt_typed("x", &RuntimeType::count(), exec_state)?; let scale_x: Option<TyF64> = args.get_kw_arg_opt_typed("x", &RuntimeType::count(), exec_state)?;
let scale_y: Option<TyF64> = args.get_kw_arg_opt_typed("y", &RuntimeType::count(), exec_state)?; let scale_y: Option<TyF64> = args.get_kw_arg_opt_typed("y", &RuntimeType::count(), exec_state)?;
let scale_z: Option<TyF64> = args.get_kw_arg_opt_typed("z", &RuntimeType::count(), exec_state)?; let scale_z: Option<TyF64> = args.get_kw_arg_opt_typed("z", &RuntimeType::count(), exec_state)?;
let global = args.get_kw_arg_opt("global")?; let global = args.get_kw_arg_opt_typed("global", &RuntimeType::bool(), exec_state)?;
// Ensure at least one scale value is provided. // Ensure at least one scale value is provided.
if scale_x.is_none() && scale_y.is_none() && scale_z.is_none() { if scale_x.is_none() && scale_y.is_none() && scale_z.is_none() {
@ -115,7 +115,7 @@ pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValu
let translate_x: Option<TyF64> = args.get_kw_arg_opt_typed("x", &RuntimeType::length(), exec_state)?; let translate_x: Option<TyF64> = args.get_kw_arg_opt_typed("x", &RuntimeType::length(), exec_state)?;
let translate_y: Option<TyF64> = args.get_kw_arg_opt_typed("y", &RuntimeType::length(), exec_state)?; let translate_y: Option<TyF64> = args.get_kw_arg_opt_typed("y", &RuntimeType::length(), exec_state)?;
let translate_z: Option<TyF64> = args.get_kw_arg_opt_typed("z", &RuntimeType::length(), exec_state)?; let translate_z: Option<TyF64> = args.get_kw_arg_opt_typed("z", &RuntimeType::length(), exec_state)?;
let global = args.get_kw_arg_opt("global")?; let global = args.get_kw_arg_opt_typed("global", &RuntimeType::bool(), exec_state)?;
// Ensure at least one translation value is provided. // Ensure at least one translation value is provided.
if translate_x.is_none() && translate_y.is_none() && translate_z.is_none() { if translate_x.is_none() && translate_y.is_none() && translate_z.is_none() {
@ -198,7 +198,7 @@ pub async fn rotate(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
)?; )?;
let axis = axis.map(|a| a.to_point3d()); let axis = axis.map(|a| a.to_point3d());
let angle: Option<TyF64> = args.get_kw_arg_opt_typed("angle", &RuntimeType::degrees(), exec_state)?; let angle: Option<TyF64> = args.get_kw_arg_opt_typed("angle", &RuntimeType::degrees(), exec_state)?;
let global = args.get_kw_arg_opt("global")?; let global = args.get_kw_arg_opt_typed("global", &RuntimeType::bool(), exec_state)?;
// Check if no rotation values are provided. // Check if no rotation values are provided.
if roll.is_none() && pitch.is_none() && yaw.is_none() && axis.is_none() && angle.is_none() { if roll.is_none() && pitch.is_none() && yaw.is_none() && axis.is_none() && angle.is_none() {