Implement coercion of numeric types for ascription and arithmetic (off by default) (#6175)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
@ -8,7 +8,7 @@ use kcmc::{
|
||||
};
|
||||
use kittycad_modeling_cmds as kcmc;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
@ -72,7 +72,7 @@ impl KwArgs {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TyF64 {
|
||||
@ -92,7 +92,7 @@ impl TyF64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map(mut self, n: f64) -> Self {
|
||||
pub fn map_value(mut self, n: f64) -> Self {
|
||||
self.n = n;
|
||||
self
|
||||
}
|
||||
@ -209,7 +209,7 @@ impl Args {
|
||||
}));
|
||||
};
|
||||
|
||||
let arg = arg.value.coerce(ty, exec_state).ok_or_else(|| {
|
||||
let arg = arg.value.coerce(ty, exec_state).map_err(|_| {
|
||||
let actual_type_name = arg.value.human_friendly_type();
|
||||
let msg_base = format!(
|
||||
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
||||
@ -332,7 +332,7 @@ impl Args {
|
||||
message: format!("This function requires a value for the special unlabeled first parameter, '{label}'"),
|
||||
}))?;
|
||||
|
||||
let arg = arg.value.coerce(ty, exec_state).ok_or_else(|| {
|
||||
let arg = arg.value.coerce(ty, exec_state).map_err(|_| {
|
||||
let actual_type_name = arg.value.human_friendly_type();
|
||||
let msg_base = format!(
|
||||
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
|
||||
@ -523,7 +523,7 @@ impl Args {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn make_user_val_from_f64(&self, f: f64) -> KclValue {
|
||||
pub(super) fn make_user_val_from_f64(&self, f: f64) -> KclValue {
|
||||
KclValue::from_number(
|
||||
f,
|
||||
vec![Metadata {
|
||||
@ -532,7 +532,7 @@ impl Args {
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn make_user_val_from_f64_with_type(&self, f: TyF64) -> KclValue {
|
||||
pub(super) fn make_user_val_from_f64_with_type(&self, f: TyF64) -> KclValue {
|
||||
KclValue::from_number_with_type(
|
||||
f.n,
|
||||
f.ty,
|
||||
@ -542,7 +542,7 @@ impl Args {
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn make_user_val_from_f64_array(&self, f: Vec<f64>, ty: &NumericType) -> Result<KclValue, KclError> {
|
||||
pub(super) fn make_user_val_from_f64_array(&self, f: Vec<f64>, ty: &NumericType) -> Result<KclValue, KclError> {
|
||||
let array = f
|
||||
.into_iter()
|
||||
.map(|n| KclValue::Number {
|
||||
@ -616,8 +616,7 @@ impl Args {
|
||||
let mut numbers = numbers.into_iter();
|
||||
let a = numbers.next().unwrap();
|
||||
let b = numbers.next().unwrap();
|
||||
let ty = a.ty.combine_eq(&b.ty);
|
||||
Ok((a.n, b.n, ty))
|
||||
Ok(NumericType::combine_eq(a, b))
|
||||
}
|
||||
|
||||
pub(crate) fn get_sketches(&self, exec_state: &mut ExecState) -> Result<(Vec<Sketch>, Sketch), KclError> {
|
||||
@ -627,16 +626,15 @@ impl Args {
|
||||
source_ranges: vec![self.source_range],
|
||||
}));
|
||||
};
|
||||
let sarg = arg0
|
||||
.value
|
||||
.coerce(&RuntimeType::sketches(), exec_state)
|
||||
.ok_or(KclError::Type(KclErrorDetails {
|
||||
let sarg = arg0.value.coerce(&RuntimeType::sketches(), exec_state).map_err(|_| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected an array of sketches, found {}",
|
||||
arg0.value.human_friendly_type()
|
||||
),
|
||||
source_ranges: vec![self.source_range],
|
||||
}))?;
|
||||
})
|
||||
})?;
|
||||
let sketches = match sarg {
|
||||
KclValue::HomArray { value, .. } => value.iter().map(|v| v.as_sketch().unwrap().clone()).collect(),
|
||||
_ => unreachable!(),
|
||||
@ -651,10 +649,12 @@ impl Args {
|
||||
let sarg = arg1
|
||||
.value
|
||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
||||
.ok_or(KclError::Type(KclErrorDetails {
|
||||
message: format!("Expected a sketch, found {}", arg1.value.human_friendly_type()),
|
||||
source_ranges: vec![self.source_range],
|
||||
}))?;
|
||||
.map_err(|_| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!("Expected a sketch, found {}", arg1.value.human_friendly_type()),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?;
|
||||
let sketch = match sarg {
|
||||
KclValue::Sketch { value } => *value,
|
||||
_ => unreachable!(),
|
||||
@ -673,10 +673,12 @@ impl Args {
|
||||
let sarg = arg0
|
||||
.value
|
||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
||||
.ok_or(KclError::Type(KclErrorDetails {
|
||||
message: format!("Expected a sketch, found {}", arg0.value.human_friendly_type()),
|
||||
source_ranges: vec![self.source_range],
|
||||
}))?;
|
||||
.map_err(|_| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!("Expected a sketch, found {}", arg0.value.human_friendly_type()),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?;
|
||||
match sarg {
|
||||
KclValue::Sketch { value } => Ok(*value),
|
||||
_ => unreachable!(),
|
||||
@ -718,13 +720,15 @@ impl Args {
|
||||
let sarg = arg1
|
||||
.value
|
||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)
|
||||
.ok_or(KclError::Type(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected a sketch for second argument, found {}",
|
||||
arg1.value.human_friendly_type()
|
||||
),
|
||||
source_ranges: vec![self.source_range],
|
||||
}))?;
|
||||
.map_err(|_| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected a sketch for second argument, found {}",
|
||||
arg1.value.human_friendly_type()
|
||||
),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?;
|
||||
let sketch = match sarg {
|
||||
KclValue::Sketch { value } => *value,
|
||||
_ => unreachable!(),
|
||||
@ -754,13 +758,15 @@ impl Args {
|
||||
let sarg = arg1
|
||||
.value
|
||||
.coerce(&RuntimeType::Primitive(PrimitiveType::Solid), exec_state)
|
||||
.ok_or(KclError::Type(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected a solid for second argument, found {}",
|
||||
arg1.value.human_friendly_type()
|
||||
),
|
||||
source_ranges: vec![self.source_range],
|
||||
}))?;
|
||||
.map_err(|_| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected a solid for second argument, found {}",
|
||||
arg1.value.human_friendly_type()
|
||||
),
|
||||
source_ranges: vec![self.source_range],
|
||||
})
|
||||
})?;
|
||||
let solid = match sarg {
|
||||
KclValue::Solid { value } => value,
|
||||
_ => unreachable!(),
|
||||
|
@ -13,7 +13,7 @@ pub async fn int(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
let num = args.get_number_with_type()?;
|
||||
let converted = inner_int(num.n)?;
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(num.map(converted)))
|
||||
Ok(args.make_user_val_from_f64_with_type(num.map_value(converted)))
|
||||
}
|
||||
|
||||
/// Convert a number to an integer.
|
||||
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
errors::KclError,
|
||||
execution::{ExecState, KclValue},
|
||||
std::args::{Args, TyF64},
|
||||
std::args::Args,
|
||||
};
|
||||
|
||||
/// Data for polar coordinates.
|
||||
@ -19,7 +19,7 @@ pub struct PolarCoordsData {
|
||||
/// The angle of the line (in degrees).
|
||||
pub angle: f64,
|
||||
/// The length of the line.
|
||||
pub length: TyF64,
|
||||
pub length: f64,
|
||||
}
|
||||
|
||||
/// Convert from polar/sphere coordinates to cartesian coordinates.
|
||||
@ -27,7 +27,7 @@ pub async fn polar(_exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
let data: PolarCoordsData = args.get_data()?;
|
||||
let result = inner_polar(&data)?;
|
||||
|
||||
args.make_user_val_from_f64_array(result.to_vec(), &data.length.ty)
|
||||
args.make_user_val_from_f64_array(result.to_vec(), &crate::execution::types::NumericType::Unknown)
|
||||
}
|
||||
|
||||
/// Convert polar/sphere (azimuth, elevation, distance) coordinates to
|
||||
@ -49,7 +49,7 @@ pub async fn polar(_exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
}]
|
||||
fn inner_polar(data: &PolarCoordsData) -> Result<[f64; 2], KclError> {
|
||||
let angle = data.angle.to_radians();
|
||||
let x = data.length.n * angle.cos();
|
||||
let y = data.length.n * angle.sin();
|
||||
let x = data.length * angle.cos();
|
||||
let y = data.length * angle.sin();
|
||||
Ok([x, y])
|
||||
}
|
||||
|
Reference in New Issue
Block a user