Turn on uom checks

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-04-11 09:01:35 +12:00
parent e4e18dfd4b
commit 6288ab5f2f
68 changed files with 16164 additions and 1319 deletions

View File

@ -4,8 +4,12 @@ excerpt: "Converts a number from centimeters to the current default unit."
layout: manual
---
**WARNING:** This function is deprecated.
Converts a number from centimeters to the current default unit.
*DEPRECATED* prefer using explicit numberic suffixes (e.g., `42cm`) or the `to...` conversion functions.
No matter what units the current file uses, this function will always return a number equivalent to the input in centimeters.
For example, if the current file uses inches, `fromCm(1)` will return `0.393701`. If the current file uses millimeters, `fromCm(1)` will return `10`. If the current file uses centimeters, `fromCm(1)` will return `1`.

View File

@ -4,8 +4,12 @@ excerpt: "Converts a number from feet to the current default unit."
layout: manual
---
**WARNING:** This function is deprecated.
Converts a number from feet to the current default unit.
*DEPRECATED* prefer using explicit numberic suffixes (e.g., `42ft`) or the `to...` conversion functions.
No matter what units the current file uses, this function will always return a number equivalent to the input in feet.
For example, if the current file uses inches, `fromFt(1)` will return `12`. If the current file uses millimeters, `fromFt(1)` will return `304.8`. If the current file uses feet, `fromFt(1)` will return `1`.

View File

@ -4,8 +4,12 @@ excerpt: "Converts a number from inches to the current default unit."
layout: manual
---
**WARNING:** This function is deprecated.
Converts a number from inches to the current default unit.
*DEPRECATED* prefer using explicit numberic suffixes (e.g., `42inch`) or the `to...` conversion functions.
No matter what units the current file uses, this function will always return a number equivalent to the input in inches.
For example, if the current file uses inches, `fromInches(1)` will return `1`. If the current file uses millimeters, `fromInches(1)` will return `25.4`.

View File

@ -4,8 +4,12 @@ excerpt: "Converts a number from meters to the current default unit."
layout: manual
---
**WARNING:** This function is deprecated.
Converts a number from meters to the current default unit.
*DEPRECATED* prefer using explicit numberic suffixes (e.g., `42m`) or the `to...` conversion functions.
No matter what units the current file uses, this function will always return a number equivalent to the input in meters.
For example, if the current file uses inches, `fromM(1)` will return `39.3701`. If the current file uses millimeters, `fromM(1)` will return `1000`. If the current file uses meters, `fromM(1)` will return `1`.

View File

@ -4,8 +4,12 @@ excerpt: "Converts a number from mm to the current default unit."
layout: manual
---
**WARNING:** This function is deprecated.
Converts a number from mm to the current default unit.
*DEPRECATED* prefer using explicit numberic suffixes (e.g., `42mm`) or the `to...` conversion functions.
No matter what units the current file uses, this function will always return a number equivalent to the input in millimeters.
For example, if the current file uses inches, `fromMm(1)` will return `1/25.4`. If the current file uses millimeters, `fromMm(1)` will return `1`.

View File

@ -4,8 +4,12 @@ excerpt: "Converts a number from yards to the current default unit."
layout: manual
---
**WARNING:** This function is deprecated.
Converts a number from yards to the current default unit.
*DEPRECATED* prefer using explicit numberic suffixes (e.g., `42yd`) or the `to...` conversion functions.
No matter what units the current file uses, this function will always return a number equivalent to the input in yards.
For example, if the current file uses inches, `fromYd(1)` will return `36`. If the current file uses millimeters, `fromYd(1)` will return `914.4`. If the current file uses yards, `fromYd(1)` will return `1`.

View File

@ -55,12 +55,6 @@ layout: manual
* [`extrude`](kcl/extrude)
* [`fillet`](kcl/fillet)
* [`floor`](kcl/floor)
* [`fromCm`](kcl/fromCm)
* [`fromFt`](kcl/fromFt)
* [`fromInches`](kcl/fromInches)
* [`fromM`](kcl/fromM)
* [`fromMm`](kcl/fromMm)
* [`fromYd`](kcl/fromYd)
* [`getCommonEdge`](kcl/getCommonEdge)
* [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge)
* [`getOppositeEdge`](kcl/getOppositeEdge)
@ -120,8 +114,14 @@ layout: manual
* [`sweep`](kcl/sweep)
* [`tangentToEnd`](kcl/tangentToEnd)
* [`tangentialArc`](kcl/tangentialArc)
* [`toDegrees`](kcl/toDegrees)
* [`toRadians`](kcl/toRadians)
* [`toCentimeters`](kcl/std-toCentimeters)
* [`toDegrees`](kcl/std-toDegrees)
* [`toFeet`](kcl/std-toFeet)
* [`toInches`](kcl/std-toInches)
* [`toMeters`](kcl/std-toMeters)
* [`toMillimeters`](kcl/std-toMillimeters)
* [`toRadians`](kcl/std-toRadians)
* [`toYards`](kcl/std-toYards)
* [`translate`](kcl/translate)
* [`union`](kcl/union)
* [`xLine`](kcl/xLine)

View File

@ -174,7 +174,7 @@ t = 0.005 // taper factor [0-1)
// Defines how to modify each layer of the vase.
// Each replica is shifted up the Z axis, and has a smoothly-varying radius
fn transform(replicaId) {
scale = r * abs(1 - (t * replicaId)) * (5 + cos(replicaId / 8))
scale = r * abs(1 - (t * replicaId)) * (5 + cos(replicaId / 8: number(rad)))
return {
translate = [0, 0, replicaId * 10],
scale = [scale, scale, 0]

View File

@ -26,7 +26,7 @@ helix(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `revolutions` | `number(_)` | Number of revolutions. | Yes |
| `angleStart` | `number(Angle)` | Start angle (in degrees). | Yes |
| `angleStart` | `number(Angle)` | Start angle. | Yes |
| `ccw` | [`bool`](/docs/kcl/types/bool) | Is the helix rotation counter clockwise? The default is `false`. | No |
| `radius` | `number(Length)` | Radius of the helix. | No |
| `axis` | `Axis3d | Edge` | Axis to use for the helix. | No |

View File

@ -31,7 +31,7 @@ exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(
angle = 30,
length = 3 / cos(toRadians(30)),
length = 3 / cos(30deg),
)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -11,7 +11,7 @@ cartesian (x/y/z grid) coordinates.
```js
polar(
angle: number(Angle),
angle: number(rad),
length: number(Length),
): Point2d
```
@ -21,7 +21,7 @@ polar(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `angle` | `number(Angle)` | | Yes |
| `angle` | `number(rad)` | | Yes |
| `length` | `number(Length)` | | Yes |
### Returns

View File

@ -31,7 +31,7 @@ exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(
angle = 50,
length = 15 / sin(toRadians(135)),
length = 15 / sin(135deg),
)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -31,7 +31,7 @@ exampleSketch = startSketchOn(XZ)
|> startProfileAt([0, 0], %)
|> angledLine(
angle = 50,
length = 50 * tan(1/2),
length = 50 * tan((1/2): number(rad)),
)
|> yLine(endAbsolute = 0)
|> close()

View File

@ -0,0 +1,27 @@
---
title: "std::toCentimeters"
excerpt: "Convert a number to centimeters from its current units."
layout: manual
---
Convert a number to centimeters from its current units.
```js
toCentimeters(@num: number(cm)): number(cm)
```
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `num` | `number(cm)` | | Yes |
### Returns
`number(cm)`

44
docs/kcl/std-toDegrees.md Normal file

File diff suppressed because one or more lines are too long

27
docs/kcl/std-toFeet.md Normal file
View File

@ -0,0 +1,27 @@
---
title: "std::toFeet"
excerpt: "Convert a number to feet from its current units."
layout: manual
---
Convert a number to feet from its current units.
```js
toFeet(@num: number(ft)): number(ft)
```
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `num` | `number(ft)` | | Yes |
### Returns
`number(ft)`

27
docs/kcl/std-toInches.md Normal file
View File

@ -0,0 +1,27 @@
---
title: "std::toInches"
excerpt: "Convert a number to inches from its current units."
layout: manual
---
Convert a number to inches from its current units.
```js
toInches(@num: number(in)): number(in)
```
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `num` | `number(in)` | | Yes |
### Returns
`number(in)`

27
docs/kcl/std-toMeters.md Normal file
View File

@ -0,0 +1,27 @@
---
title: "std::toMeters"
excerpt: "Convert a number to meters from its current units."
layout: manual
---
Convert a number to meters from its current units.
```js
toMeters(@num: number(m)): number(m)
```
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `num` | `number(m)` | | Yes |
### Returns
`number(m)`

View File

@ -0,0 +1,27 @@
---
title: "std::toMillimeters"
excerpt: "Convert a number to millimeters from its current units."
layout: manual
---
Convert a number to millimeters from its current units.
```js
toMillimeters(@num: number(mm)): number(mm)
```
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `num` | `number(mm)` | | Yes |
### Returns
`number(mm)`

44
docs/kcl/std-toRadians.md Normal file

File diff suppressed because one or more lines are too long

27
docs/kcl/std-toYards.md Normal file
View File

@ -0,0 +1,27 @@
---
title: "std::toYards"
excerpt: "Converts a number to yards from its current units."
layout: manual
---
Converts a number to yards from its current units.
```js
toYards(@num: number(yd)): number(yd)
```
### Arguments
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `num` | `number(yd)` | | Yes |
### Returns
`number(yd)`

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -33,11 +33,11 @@ invas = map(angles, fn(a) {
// Map the involute curve
xs = map([0..cmo], fn(i) {
return rs[i] * cos(invas[i])
return rs[i] * cos(invas[i]: number(rad))
})
ys = map([0..cmo], fn(i) {
return rs[i] * sin(invas[i])
return rs[i] * sin(invas[i]: number(rad))
})
// Extrude the gear body

View File

@ -29,7 +29,7 @@ sketch001 = startSketchOn(XZ)
)
|> yLine(endAbsolute = -templateThickness, tag = $seg03)
|> xLine(length = templateThickness, tag = $seg07)
|> yLine(endAbsolute = (segEndY(seg01) + templateThickness) / 2 - templateThickness, tag = $seg02)
|> yLine(endAbsolute = (segEndY(seg01) + templateThickness) / 2_ - templateThickness, tag = $seg02)
|> xLine(endAbsolute = segEndX(seg03) + minClampingDistance, tag = $seg06)
|> yLine(length = templateThickness * 2, tag = $seg08)
|> xLine(endAbsolute = segEndX(seg02) + 0, tag = $seg05)

View File

@ -5,7 +5,7 @@ const t = 0.005 // taper factor [0-1)
// Defines how to modify each layer of the vase.
// Each replica is shifted up the Z axis, and has a smoothly-varying radius
fn transform = (replicaId) => {
let scale = r * abs(1 - (t * replicaId)) * (5 + cos(replicaId / 8))
let scale = r * abs(1 - (t * replicaId)) * (5 + cos((replicaId / 8): number(rad)))
return {
translate: [0, 0, replicaId * 10],
scale: [scale, scale, 0],

View File

@ -3,11 +3,7 @@ use std::collections::HashMap;
use async_recursion::async_recursion;
use indexmap::IndexMap;
use super::{
cad_op::Group,
kcl_value::TypeDef,
types::{PrimitiveType, CHECK_NUMERIC_TYPES},
};
use super::{cad_op::Group, kcl_value::TypeDef, types::PrimitiveType};
use crate::{
errors::{KclError, KclErrorDetails},
execution::{
@ -873,7 +869,10 @@ impl Node<MemberExpression> {
source_ranges: vec![self.clone().into()],
}))
}
(KclValue::MixedArray { value: arr, meta: _ }, Property::UInt(index)) => {
(
KclValue::MixedArray { value: arr, .. } | KclValue::HomArray { value: arr, .. },
Property::UInt(index),
) => {
let value_of_arr = arr.get(index);
if let Some(value) = value_of_arr {
Ok(value.to_owned())
@ -884,7 +883,7 @@ impl Node<MemberExpression> {
}))
}
}
(KclValue::MixedArray { .. }, p) => {
(KclValue::MixedArray { .. } | KclValue::HomArray { .. }, p) => {
let t = p.type_name();
let article = article_for(t);
Err(KclError::Semantic(KclErrorDetails {
@ -1051,7 +1050,7 @@ impl Node<BinaryExpression> {
BinaryOperator::Pow => KclValue::Number {
value: left.n.powf(right.n),
meta,
ty: NumericType::Unknown,
ty: exec_state.current_default_units(),
},
BinaryOperator::Neq => {
let (l, r, ty) = NumericType::combine_eq(left, right);
@ -1090,7 +1089,7 @@ impl Node<BinaryExpression> {
}
fn warn_on_unknown(&self, ty: &NumericType, verb: &str, exec_state: &mut ExecState) {
if *CHECK_NUMERIC_TYPES && ty == &NumericType::Unknown {
if ty == &NumericType::Unknown {
// TODO suggest how to fix this
exec_state.warn(CompilationError::err(
self.as_source_range(),
@ -1999,11 +1998,39 @@ fn assign_args_to_params(
for (index, param) in function_expression.params.iter().enumerate() {
if let Some(arg) = args.get(index) {
// Argument was provided.
exec_state.mut_stack().add(
param.identifier.name.clone(),
arg.value.clone(),
(&param.identifier).into(),
)?;
if let Some(ty) = &param.type_ {
let value = arg
.value
.coerce(
&RuntimeType::from_parsed(ty.inner.clone(), exec_state, arg.source_range).unwrap(),
exec_state,
)
.map_err(|e| {
let mut message = format!(
"Argument requires a value with type `{}`, but found {}",
ty.inner,
arg.value.human_friendly_type(),
);
if let Some(ty) = e.explicit_coercion {
// TODO if we have access to the AST for the argument we could choose which example to suggest.
message = format!("{message}\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`");
}
KclError::Semantic(KclErrorDetails {
message,
source_ranges: vec![arg.source_range],
})
})?;
exec_state
.mut_stack()
.add(param.identifier.name.clone(), value, (&param.identifier).into())?;
} else {
exec_state.mut_stack().add(
param.identifier.name.clone(),
arg.value.clone(),
(&param.identifier).into(),
)?;
}
} else {
// Argument was not provided.
if let Some(ref default_val) = param.default_value {

View File

@ -18,16 +18,6 @@ use crate::{
CompilationError, SourceRange,
};
lazy_static::lazy_static! {
pub(crate) static ref CHECK_NUMERIC_TYPES: bool = {
let env_var = std::env::var("ZOO_NUM_TYS");
let Ok(env_var) = env_var else {
return false;
};
!env_var.is_empty()
};
}
#[derive(Debug, Clone, PartialEq)]
pub enum RuntimeType {
Primitive(PrimitiveType),
@ -62,6 +52,10 @@ impl RuntimeType {
RuntimeType::Primitive(PrimitiveType::Solid)
}
pub fn helix() -> Self {
RuntimeType::Primitive(PrimitiveType::Helix)
}
pub fn plane() -> Self {
RuntimeType::Primitive(PrimitiveType::Plane)
}
@ -94,6 +88,10 @@ impl RuntimeType {
))))
}
pub fn known_length(len: UnitLen) -> Self {
RuntimeType::Primitive(PrimitiveType::Number(NumericType::Known(UnitType::Length(len))))
}
pub fn angle() -> Self {
RuntimeType::Primitive(PrimitiveType::Number(NumericType::Known(UnitType::Angle(
UnitAngle::Unknown,
@ -370,6 +368,7 @@ impl fmt::Display for PrimitiveType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PrimitiveType::Number(NumericType::Known(unit)) => write!(f, "number({unit})"),
PrimitiveType::Number(NumericType::Unknown) => write!(f, "number(unknown units)"),
PrimitiveType::Number(_) => write!(f, "number"),
PrimitiveType::String => write!(f, "string"),
PrimitiveType::Boolean => write!(f, "bool"),
@ -427,8 +426,45 @@ impl NumericType {
NumericType::Known(UnitType::Angle(UnitAngle::Degrees))
}
pub fn expect_default_length(&self) -> Self {
match self {
NumericType::Default { len, .. } => NumericType::Known(UnitType::Length(*len)),
_ => unreachable!(),
}
}
pub fn expect_default_angle(&self) -> Self {
match self {
NumericType::Default { angle, .. } => NumericType::Known(UnitType::Angle(*angle)),
_ => unreachable!(),
}
}
/// Combine two types when we expect them to be equal.
pub fn combine_eq(a: TyF64, b: TyF64) -> (f64, f64, NumericType) {
use NumericType::*;
match (a.ty, b.ty) {
(at, bt) if at == bt => (a.n, b.n, at),
(at, Any) => (a.n, b.n, at),
(Any, bt) => (a.n, b.n, bt),
(t @ Known(UnitType::Length(l1)), Known(UnitType::Length(l2))) => (a.n, l2.adjust_to(b.n, l1).0, t),
(t @ Known(UnitType::Angle(a1)), Known(UnitType::Angle(a2))) => (a.n, a2.adjust_to(b.n, a1).0, t),
(Known(UnitType::Count), Default { .. }) | (Default { .. }, Known(UnitType::Count)) => {
(a.n, b.n, Known(UnitType::Count))
}
(t @ Known(UnitType::Length(l1)), Default { len: l2, .. }) if l1 == l2 => (a.n, b.n, t),
(Default { len: l1, .. }, t @ Known(UnitType::Length(l2))) if l1 == l2 => (a.n, b.n, t),
(t @ Known(UnitType::Angle(a1)), Default { angle: a2, .. }) if a1 == a2 => (a.n, b.n, t),
(Default { angle: a1, .. }, t @ Known(UnitType::Angle(a2))) if a1 == a2 => (a.n, b.n, t),
_ => (a.n, b.n, Unknown),
}
}
/// Combine two types when we expect them to be equal.
pub fn combine_eq_coerce(a: TyF64, b: TyF64) -> (f64, f64, NumericType) {
use NumericType::*;
match (a.ty, b.ty) {
(at, bt) if at == bt => (a.n, b.n, at),
@ -458,12 +494,9 @@ impl NumericType {
pub fn combine_eq_array(input: &[TyF64]) -> (Vec<f64>, NumericType) {
use NumericType::*;
let mut result = input.iter().map(|t| t.n).collect();
let result = input.iter().map(|t| t.n).collect();
let mut ty = Any;
// Invariant mismatch is true => ty is fully known
let mut mismatch = false;
for i in input {
if i.ty == Any || ty == i.ty {
continue;
@ -475,58 +508,24 @@ impl NumericType {
}
(_, Unknown) | (Default { .. }, Default { .. }) => return (result, Unknown),
// Known types and compatible, but needs adjustment.
(Known(UnitType::Length(_)), Known(UnitType::Length(_)))
| (Known(UnitType::Angle(_)), Known(UnitType::Angle(_))) => {
mismatch = true;
}
// Known but incompatible.
(Known(_), Known(_)) => return (result, Unknown),
// Known and unknown, no adjustment for counting numbers.
(Known(UnitType::Count), Default { .. }) | (Default { .. }, Known(UnitType::Count)) => {
ty = Known(UnitType::Count);
}
(Known(UnitType::Length(l1)), Default { len: l2, .. }) => {
mismatch |= l1 != l2;
}
(Known(UnitType::Angle(a1)), Default { angle: a2, .. }) => {
mismatch |= a1 != a2;
}
(Known(UnitType::Length(l1)), Default { len: l2, .. }) if l1 == l2 => {}
(Known(UnitType::Angle(a1)), Default { angle: a2, .. }) if a1 == a2 => {}
(Default { len: l1, .. }, Known(UnitType::Length(l2))) => {
mismatch |= l1 != l2;
(Default { len: l1, .. }, Known(UnitType::Length(l2))) if l1 == l2 => {
ty = Known(UnitType::Length(*l2));
}
(Default { angle: a1, .. }, Known(UnitType::Angle(a2))) => {
mismatch |= a1 != a2;
(Default { angle: a1, .. }, Known(UnitType::Angle(a2))) if a1 == a2 => {
ty = Known(UnitType::Angle(*a2));
}
(Unknown, _) | (_, Any) => unreachable!(),
_ => return (result, Unknown),
}
}
if !mismatch {
return (result, ty);
}
result = result
.into_iter()
.zip(input)
.map(|(n, i)| match (&ty, &i.ty) {
(Known(UnitType::Length(l1)), Known(UnitType::Length(l2)) | Default { len: l2, .. }) => {
l2.adjust_to(n, *l1).0
}
(Known(UnitType::Angle(a1)), Known(UnitType::Angle(a2)) | Default { angle: a2, .. }) => {
a2.adjust_to(n, *a1).0
}
_ => unreachable!(),
})
.collect();
(result, ty)
}
@ -534,11 +533,11 @@ impl NumericType {
pub fn combine_mul(a: TyF64, b: TyF64) -> (f64, f64, NumericType) {
use NumericType::*;
match (a.ty, b.ty) {
(at @ Default { .. }, bt @ Default { .. }) if at != bt => (a.n, b.n, Unknown),
(at @ Default { .. }, bt @ Default { .. }) if at == bt => (a.n, b.n, at),
(Default { .. }, Default { .. }) => (a.n, b.n, Unknown),
(Known(UnitType::Count), bt) => (a.n, b.n, bt),
(at, Known(UnitType::Count)) => (a.n, b.n, at),
(Default { .. }, bt) => (a.n, b.n, bt),
(at, Default { .. }) => (a.n, b.n, at),
(at @ Known(_), Default { .. }) | (Default { .. }, at @ Known(_)) => (a.n, b.n, at),
(Any, Any) => (a.n, b.n, Any),
_ => (a.n, b.n, Unknown),
}
@ -552,18 +551,7 @@ impl NumericType {
(at, bt) if at == bt => (a.n, b.n, Known(UnitType::Count)),
(Default { .. }, Default { .. }) => (a.n, b.n, Unknown),
(at, Known(UnitType::Count) | Any) => (a.n, b.n, at),
(Known(UnitType::Length(l1)), Known(UnitType::Length(l2))) => {
(a.n, l2.adjust_to(b.n, l1).0, Known(UnitType::Count))
}
(Known(UnitType::Angle(a1)), Known(UnitType::Angle(a2))) => {
(a.n, a2.adjust_to(b.n, a1).0, Known(UnitType::Count))
}
(Default { len: l1, .. }, Known(UnitType::Length(l2))) => {
(l1.adjust_to(a.n, l2).0, b.n, Known(UnitType::Count))
}
(Default { angle: a1, .. }, Known(UnitType::Angle(a2))) => {
(a1.adjust_to(a.n, a2).0, b.n, Known(UnitType::Count))
}
(at @ Known(_), Default { .. }) => (a.n, b.n, at),
(Known(UnitType::Count), _) => (a.n, b.n, Known(UnitType::Count)),
_ => (a.n, b.n, Unknown),
}
@ -608,9 +596,18 @@ impl NumericType {
}
}
fn is_unknown(&self) -> bool {
match self {
NumericType::Unknown
| NumericType::Known(UnitType::Angle(UnitAngle::Unknown))
| NumericType::Known(UnitType::Length(UnitLen::Unknown)) => true,
_ => false,
}
}
fn example_ty(&self) -> Option<String> {
match self {
Self::Known(t) => Some(t.to_string()),
Self::Known(t) if !self.is_unknown() => Some(t.to_string()),
Self::Default { len, .. } => Some(len.to_string()),
_ => None,
}
@ -621,10 +618,6 @@ impl NumericType {
return Err(val.into());
};
if !*CHECK_NUMERIC_TYPES {
return Ok(val.clone());
}
if ty.subtype(self) {
return Ok(KclValue::Number {
value: *value,
@ -778,7 +771,7 @@ impl UnitLen {
fn adjust_to(self, value: f64, to: UnitLen) -> (f64, UnitLen) {
use UnitLen::*;
if !*CHECK_NUMERIC_TYPES || self == to {
if self == to {
return (value, to);
}
@ -903,10 +896,6 @@ impl UnitAngle {
use UnitAngle::*;
if !*CHECK_NUMERIC_TYPES {
return (value, to);
}
if to == Unknown {
return (value, self);
}
@ -1952,10 +1941,6 @@ mod test {
assert_coerce_results(&unknown, &NumericType::Any.into(), &unknown, &mut exec_state);
assert_coerce_results(&default, &NumericType::Any.into(), &default, &mut exec_state);
if !*CHECK_NUMERIC_TYPES {
return;
}
assert_eq!(
default
.coerce(
@ -2068,20 +2053,14 @@ u = min(3rad, 4in)
"#;
let result = parse_execute(program).await.unwrap();
if *CHECK_NUMERIC_TYPES {
assert_eq!(result.exec_state.errors().len(), 3);
} else {
assert!(result.exec_state.errors().is_empty());
}
assert_eq!(result.exec_state.errors().len(), 5);
assert_value_and_type("a", &result, 9.0, NumericType::default());
assert_value_and_type("b", &result, 3.0, NumericType::default());
assert_value_and_type("c", &result, 13.0, NumericType::mm());
assert_value_and_type("d", &result, 13.0, NumericType::mm());
assert_value_and_type("e", &result, 13.0, NumericType::mm());
if *CHECK_NUMERIC_TYPES {
assert_value_and_type("f", &result, 5.0, NumericType::mm());
}
assert_value_and_type("f", &result, 5.0, NumericType::mm());
assert_value_and_type("g", &result, 20.0, NumericType::default());
assert_value_and_type("h", &result, 20.0, NumericType::mm());
@ -2091,16 +2070,14 @@ u = min(3rad, 4in)
assert_value_and_type("l", &result, 0.0, NumericType::default());
assert_value_and_type("m", &result, 2.0, NumericType::count());
if *CHECK_NUMERIC_TYPES {
assert_value_and_type("n", &result, 127.0, NumericType::count());
}
assert_value_and_type("o", &result, 1.0, NumericType::Unknown);
assert_value_and_type("n", &result, 5.0, NumericType::Unknown);
assert_value_and_type("o", &result, 1.0, NumericType::mm());
assert_value_and_type("p", &result, 1.0, NumericType::count());
assert_value_and_type("q", &result, 2.0, NumericType::Known(UnitType::Length(UnitLen::Inches)));
assert_value_and_type("r", &result, 0.0, NumericType::default());
assert_value_and_type("s", &result, -42.0, NumericType::mm());
assert_value_and_type("t", &result, 3.0, NumericType::Known(UnitType::Length(UnitLen::Inches)));
assert_value_and_type("t", &result, 3.0, NumericType::Unknown);
assert_value_and_type("u", &result, 3.0, NumericType::Unknown);
}
@ -2114,7 +2091,24 @@ b = 180 / PI * a + 360
let result = parse_execute(program).await.unwrap();
assert_value_and_type("a", &result, 1.0, NumericType::radians());
// TODO type is not ideal
assert_value_and_type("b", &result, 417.0, NumericType::radians());
assert_value_and_type("b", &result, 417.0, NumericType::Unknown);
}
#[tokio::test(flavor = "multi_thread")]
async fn cos_coercions() {
let program = r#"
a = cos(toRadians(30))
b = 3 / a
c = cos(30deg)
d = cos(30)
"#;
let result = parse_execute(program).await.unwrap();
assert_eq!(result.exec_state.errors().len(), 1);
assert_value_and_type("a", &result, 1.0, NumericType::count());
assert_value_and_type("b", &result, 3.0, NumericType::default());
assert_value_and_type("c", &result, 1.0, NumericType::count());
assert_value_and_type("d", &result, 0.0, NumericType::count());
}
}

View File

@ -530,13 +530,6 @@ pub(crate) fn unsigned_number_literal(i: &mut TokenSlice) -> PResult<Node<Litera
CompilationError::fatal(token.as_source_range(), format!("Invalid float: {}", token.value))
})?;
if token.numeric_suffix().is_some() {
ParseContext::warn(CompilationError::err(
(&token).into(),
"Unit of Measure suffixes are experimental and currently do nothing.",
));
}
Ok((
LiteralValue::Number {
value,
@ -2015,8 +2008,6 @@ fn expression_but_not_pipe(i: &mut TokenSlice) -> PResult<Expr> {
let ty = opt((colon, opt(whitespace), argument_type)).parse_next(i)?;
if let Some((_, _, ty)) = ty {
ParseContext::warn(CompilationError::err((&ty).into(), "Type ascription is experimental."));
expr = Expr::AscribedExpression(Box::new(Ascription::new(expr, ty)))
}
let label = opt(label).parse_next(i)?;
@ -2811,13 +2802,6 @@ fn primitive_type(i: &mut TokenSlice) -> PResult<Node<PrimitiveType>> {
let mut result = Node::new(PrimitiveType::Boolean, ident.start, ident.end, ident.module_id);
result.inner = PrimitiveType::primitive_from_str(&ident.name, suffix).unwrap_or(PrimitiveType::Named(ident));
if suffix.is_some() {
ParseContext::warn(CompilationError::err(
result.as_source_range(),
"Unit of Measure types are experimental and currently do nothing.",
));
}
Ok(result)
}
@ -4532,7 +4516,7 @@ export fn cos(num: number(rad)): number(_) {}"#;
fn fn_decl_uom_ty() {
let some_program_string = r#"fn foo(x: number(mm)): number(_) { return 1 }"#;
let (_, errs) = assert_no_fatal(some_program_string);
assert_eq!(errs.len(), 2);
assert!(errs.is_empty());
}
#[test]
@ -4544,7 +4528,7 @@ export fn cos(num: number(rad)): number(_) {}"#;
#[test]
fn error_type_ascription() {
let (_, errs) = assert_no_fatal("a + b: number");
assert_eq!(errs.len(), 1, "found: {:#?}", errs);
assert!(errs.is_empty());
}
#[test]

View File

@ -547,6 +547,29 @@ impl Args {
FromArgs::from_args(self, 0)
}
pub(crate) fn get_number_typed(&self, ty: &RuntimeType, exec_state: &mut ExecState) -> Result<f64, KclError> {
let Some(arg) = self.args.get(0) else {
return Err(KclError::Semantic(KclErrorDetails {
message: format!("Expected an argument"),
source_ranges: vec![self.source_range],
}));
};
arg.value.coerce(ty, exec_state).map_err(|_| {
let actual_type_name = arg.value.human_friendly_type();
let message = format!(
"This function expected the input argument to be {} but it's actually of type {actual_type_name}",
ty.human_friendly_type(),
);
KclError::Semantic(KclErrorDetails {
source_ranges: arg.source_ranges(),
message,
})
})?;
Ok(TyF64::from_kcl_val(&arg.value).unwrap().n)
}
pub(crate) fn get_number_array_with_types(&self) -> Result<Vec<TyF64>, KclError> {
let numbers = self
.args
@ -577,7 +600,7 @@ impl Args {
let mut numbers = numbers.into_iter();
let a = numbers.next().unwrap();
let b = numbers.next().unwrap();
Ok(NumericType::combine_eq(a, b))
Ok(NumericType::combine_eq_coerce(a, b))
}
pub(crate) fn get_sketches(&self, exec_state: &mut ExecState) -> Result<(Vec<Sketch>, Sketch), KclError> {

View File

@ -17,7 +17,7 @@ use super::args::TyF64;
/// Create a helix.
pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let angle_start: TyF64 = args.get_kw_arg_typed("angleStart", &RuntimeType::angle(), 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 ccw = args.get_kw_arg_opt("ccw")?;
let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?;

View File

@ -6,7 +6,7 @@ use kcl_derive_docs::stdlib;
use crate::{
errors::{KclError, KclErrorDetails},
execution::{
types::{self, NumericType, RuntimeType},
types::{NumericType, RuntimeType, UnitAngle, UnitType},
ExecState, KclValue,
},
std::args::{Args, TyF64},
@ -20,11 +20,10 @@ pub async fn rem(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
let d: TyF64 = args.get_kw_arg_typed("divisor", &RuntimeType::num_any(), exec_state)?;
let (n, d, ty) = NumericType::combine_div(n, d);
if *types::CHECK_NUMERIC_TYPES && ty == NumericType::Unknown {
// TODO suggest how to fix this
if ty == NumericType::Unknown {
exec_state.warn(CompilationError::err(
args.source_range,
"Remainder of numbers which have unknown or incompatible units.",
"Calling `rem` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`"
));
}
let remainder = inner_rem(n, d);
@ -59,20 +58,63 @@ fn inner_rem(num: f64, divisor: f64) -> f64 {
/// Compute the cosine of a number (in radians).
pub async fn cos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::radians(), exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.n.cos())))
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
let num = match num.ty {
NumericType::Default {
angle: UnitAngle::Degrees,
..
} => {
exec_state.warn(CompilationError::err(
args.source_range,
"`cos` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `toRadians` to convert from degrees to radians",
));
num.n
}
NumericType::Known(UnitType::Angle(UnitAngle::Degrees)) => num.n.to_radians(),
_ => num.n,
};
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.cos())))
}
/// Compute the sine of a number (in radians).
pub async fn sin(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::radians(), exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.n.sin())))
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
let num = match num.ty {
NumericType::Default {
angle: UnitAngle::Degrees,
..
} => {
exec_state.warn(CompilationError::err(
args.source_range,
"`sin` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `toRadians` to convert from degrees to radians",
));
num.n
}
NumericType::Known(UnitType::Angle(UnitAngle::Degrees)) => num.n.to_radians(),
_ => num.n,
};
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.sin())))
}
/// Compute the tangent of a number (in radians).
pub async fn tan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::radians(), exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.n.tan())))
let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
let num = match num.ty {
NumericType::Default {
angle: UnitAngle::Degrees,
..
} => {
exec_state.warn(CompilationError::err(
args.source_range,
"`tan` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `toRadians` to convert from degrees to radians",
));
num.n
}
NumericType::Known(UnitType::Angle(UnitAngle::Degrees)) => num.n.to_radians(),
_ => num.n,
};
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.tan())))
}
/// Return the value of `pi`. Archimedes constant (π).
@ -258,11 +300,10 @@ fn inner_ceil(num: f64) -> Result<f64, KclError> {
pub async fn min(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let nums = args.get_number_array_with_types()?;
let (nums, ty) = NumericType::combine_eq_array(&nums);
if *types::CHECK_NUMERIC_TYPES && ty == NumericType::Unknown {
// TODO suggest how to fix this
if ty == NumericType::Unknown {
exec_state.warn(CompilationError::err(
args.source_range,
"Calling `min` on numbers which have unknown or incompatible units.",
"Calling `min` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`",
));
}
let result = inner_min(nums);
@ -303,11 +344,10 @@ fn inner_min(args: Vec<f64>) -> f64 {
pub async fn max(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let nums = args.get_number_array_with_types()?;
let (nums, ty) = NumericType::combine_eq_array(&nums);
if *types::CHECK_NUMERIC_TYPES && ty == NumericType::Unknown {
// TODO suggest how to fix this
if ty == NumericType::Unknown {
exec_state.warn(CompilationError::err(
args.source_range,
"Calling `max` on numbers which have unknown or incompatible units.",
"Calling `max` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n using a numeric suffix: `42{ty}`\n or using type ascription: `foo(): number({ty})`",
));
}
let result = inner_max(nums);
@ -389,8 +429,20 @@ fn inner_pow(num: f64, pow: f64) -> Result<f64, KclError> {
}
/// Compute the arccosine of a number (in radians).
pub async fn acos(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
pub async fn acos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let num = args.get_number_with_type()?;
if matches!(
num.ty,
NumericType::Default {
angle: UnitAngle::Degrees,
..
}
) {
exec_state.warn(CompilationError::err(
args.source_range,
"`acos` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `toRadians` to convert from degrees to radians",
));
}
let result = inner_acos(num.n)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
@ -420,8 +472,20 @@ fn inner_acos(num: f64) -> Result<f64, KclError> {
}
/// Compute the arcsine of a number (in radians).
pub async fn asin(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
pub async fn asin(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let num = args.get_number_with_type()?;
if matches!(
num.ty,
NumericType::Default {
angle: UnitAngle::Degrees,
..
}
) {
exec_state.warn(CompilationError::err(
args.source_range,
"`asin` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `toRadians` to convert from degrees to radians",
));
}
let result = inner_asin(num.n)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
@ -450,8 +514,20 @@ fn inner_asin(num: f64) -> Result<f64, KclError> {
}
/// Compute the arctangent of a number (in radians).
pub async fn atan(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
pub async fn atan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let num = args.get_number_with_type()?;
if matches!(
num.ty,
NumericType::Default {
angle: UnitAngle::Degrees,
..
}
) {
exec_state.warn(CompilationError::err(
args.source_range,
"`atan` requires its input in radians, but the input is assumed to be in degrees. You can use a numeric suffix (e.g., `0rad`) or type ascription (e.g., `(1/2): number(rad)`) to show the number is in radians, or `toRadians` to convert from degrees to radians",
));
}
let result = inner_atan(num.n)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
@ -483,7 +559,7 @@ fn inner_atan(num: f64) -> Result<f64, KclError> {
pub async fn atan2(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let y = args.get_kw_arg_typed("y", &RuntimeType::length(), exec_state)?;
let x = args.get_kw_arg_typed("x", &RuntimeType::length(), exec_state)?;
let (y, x, _) = NumericType::combine_eq(y, x);
let (y, x, _) = NumericType::combine_eq_coerce(y, x);
let result = inner_atan2(y, x)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
@ -714,66 +790,6 @@ fn inner_tau() -> Result<f64, KclError> {
Ok(std::f64::consts::TAU)
}
/// Converts a number from degrees to radians.
pub async fn to_radians(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let num = args.get_number_with_type()?;
let result = inner_to_radians(num.n)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
}
/// Converts a number from degrees to radians.
///
/// ```no_run
/// exampleSketch = startSketchOn("XZ")
/// |> startProfileAt([0, 0], %)
/// |> angledLine(
/// angle = 50,
/// length = 70 * cos(toRadians(45)),
/// )
/// |> yLine(endAbsolute = 0)
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
#[stdlib {
name = "toRadians",
tags = ["math"],
}]
fn inner_to_radians(num: f64) -> Result<f64, KclError> {
Ok(num.to_radians())
}
/// Converts a number from radians to degrees.
pub async fn to_degrees(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let num = args.get_number_with_type()?;
let result = inner_to_degrees(num.n)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees())))
}
/// Converts a number from radians to degrees.
///
/// ```no_run
/// exampleSketch = startSketchOn("XZ")
/// |> startProfileAt([0, 0], %)
/// |> angledLine(
/// angle = 50,
/// length = 70 * cos(toDegrees(pi()/4)),
/// )
/// |> yLine(endAbsolute = 0)
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
#[stdlib {
name = "toDegrees",
tags = ["math"],
}]
fn inner_to_degrees(num: f64) -> Result<f64, KclError> {
Ok(num.to_degrees())
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;

View File

@ -128,8 +128,6 @@ lazy_static! {
Box::new(crate::std::math::Log2),
Box::new(crate::std::math::Log10),
Box::new(crate::std::math::Ln),
Box::new(crate::std::math::ToDegrees),
Box::new(crate::std::math::ToRadians),
Box::new(crate::std::units::FromMm),
Box::new(crate::std::units::FromInches),
Box::new(crate::std::units::FromFt),

View File

@ -219,7 +219,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
/// // Defines how to modify each layer of the vase.
/// // Each replica is shifted up the Z axis, and has a smoothly-varying radius
/// fn transform(replicaId) {
/// scale = r * abs(1 - (t * replicaId)) * (5 + cos(replicaId / 8))
/// scale = r * abs(1 - (t * replicaId)) * (5 + cos((replicaId / 8): number(rad)))
/// return {
/// translate = [0, 0, replicaId * 10],
/// scale = [scale, scale, 0],
@ -1045,7 +1045,7 @@ pub async fn pattern_circular_2d(exec_state: &mut ExecState, args: Args) -> Resu
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
let instances: u32 = args.get_kw_arg("instances")?;
let center: [TyF64; 2] = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?;
let arc_degrees: TyF64 = args.get_kw_arg_typed("arcDegrees", &RuntimeType::angle(), exec_state)?;
let arc_degrees: TyF64 = args.get_kw_arg_typed("arcDegrees", &RuntimeType::degrees(), exec_state)?;
let rotate_duplicates: bool = args.get_kw_arg("rotateDuplicates")?;
let use_original: Option<bool> = args.get_kw_arg_opt("useOriginal")?;
@ -1157,7 +1157,7 @@ pub async fn pattern_circular_3d(exec_state: &mut ExecState, args: Args) -> Resu
// The center about which to make the pattern. This is a 3D vector.
let center: [TyF64; 3] = args.get_kw_arg_typed("center", &RuntimeType::point3d(), exec_state)?;
// The arc angle (in degrees) to place the repetitions. Must be greater than 0.
let arc_degrees: TyF64 = args.get_kw_arg_typed("arcDegrees", &RuntimeType::angle(), exec_state)?;
let arc_degrees: TyF64 = args.get_kw_arg_typed("arcDegrees", &RuntimeType::degrees(), exec_state)?;
// Whether or not to rotate the duplicates as they are copied.
let rotate_duplicates: bool = args.get_kw_arg("rotateDuplicates")?;
// If the target being patterned is itself a pattern, then, should you use the original solid,

View File

@ -31,7 +31,7 @@ pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
]),
exec_state,
)?;
let angle: Option<TyF64> = args.get_kw_arg_opt_typed("angle", &RuntimeType::angle(), exec_state)?;
let angle: Option<TyF64> = args.get_kw_arg_opt_typed("angle", &RuntimeType::degrees(), exec_state)?;
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::count(), exec_state)?;
let tag_start = args.get_kw_arg_opt("tagStart")?;
let tag_end = args.get_kw_arg_opt("tagEnd")?;

View File

@ -27,7 +27,11 @@ pub enum SweepPath {
/// Extrude a sketch along a path.
pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
let path: SweepPath = args.get_kw_arg("path")?;
let path: SweepPath = args.get_kw_arg_typed(
"path",
&RuntimeType::Union(vec![RuntimeType::sketch(), RuntimeType::helix()]),
exec_state,
)?;
let sectional = args.get_kw_arg_opt("sectional")?;
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::count(), exec_state)?;
let tag_start = args.get_kw_arg_opt("tagStart")?;

View File

@ -451,11 +451,11 @@ pub async fn rotate(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
]),
exec_state,
)?;
let roll: Option<TyF64> = args.get_kw_arg_opt_typed("roll", &RuntimeType::angle(), exec_state)?;
let pitch: Option<TyF64> = args.get_kw_arg_opt_typed("pitch", &RuntimeType::angle(), exec_state)?;
let yaw: Option<TyF64> = args.get_kw_arg_opt_typed("yaw", &RuntimeType::angle(), exec_state)?;
let roll: Option<TyF64> = args.get_kw_arg_opt_typed("roll", &RuntimeType::degrees(), exec_state)?;
let pitch: Option<TyF64> = args.get_kw_arg_opt_typed("pitch", &RuntimeType::degrees(), exec_state)?;
let yaw: Option<TyF64> = args.get_kw_arg_opt_typed("yaw", &RuntimeType::degrees(), exec_state)?;
let axis: Option<[TyF64; 3]> = args.get_kw_arg_opt_typed("axis", &RuntimeType::point3d(), exec_state)?;
let angle: Option<TyF64> = args.get_kw_arg_opt_typed("angle", &RuntimeType::angle(), 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")?;
// Check if no rotation values are provided.

View File

@ -5,20 +5,28 @@ use kcl_derive_docs::stdlib;
use crate::{
errors::KclError,
execution::{types::UnitLen, ExecState, KclValue},
execution::{
types::{RuntimeType, UnitLen},
ExecState, KclValue,
},
std::{args::TyF64, Args},
};
/// Millimeters conversion factor for current files units.
pub async fn from_mm(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let input = args.get_number_with_type()?;
let result = inner_from_mm(input.n, exec_state)?;
let input = args.get_number_typed(&RuntimeType::known_length(UnitLen::Mm), exec_state)?;
let result = inner_from_mm(input, exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
Ok(args.make_user_val_from_f64_with_type(TyF64::new(
result,
exec_state.current_default_units().expect_default_length(),
)))
}
/// Converts a number from mm to the current default unit.
///
/// *DEPRECATED* prefer using explicit numberic suffixes (e.g., `42mm`) or the `to...` conversion functions.
///
/// No matter what units the current file uses, this function will always return a number equivalent
/// to the input in millimeters.
///
@ -39,6 +47,7 @@ pub async fn from_mm(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
#[stdlib {
name = "fromMm",
tags = ["units"],
deprecated = true,
}]
fn inner_from_mm(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
Ok(match exec_state.length_unit() {
@ -54,14 +63,19 @@ fn inner_from_mm(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
/// Inches conversion factor for current files units.
pub async fn from_inches(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let input = args.get_number_with_type()?;
let result = inner_from_inches(input.n, exec_state)?;
let input = args.get_number_typed(&RuntimeType::known_length(UnitLen::Inches), exec_state)?;
let result = inner_from_inches(input, exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
Ok(args.make_user_val_from_f64_with_type(TyF64::new(
result,
exec_state.current_default_units().expect_default_length(),
)))
}
/// Converts a number from inches to the current default unit.
///
/// *DEPRECATED* prefer using explicit numberic suffixes (e.g., `42inch`) or the `to...` conversion functions.
///
/// No matter what units the current file uses, this function will always return a number equivalent
/// to the input in inches.
///
@ -82,6 +96,7 @@ pub async fn from_inches(exec_state: &mut ExecState, args: Args) -> Result<KclVa
#[stdlib {
name = "fromInches",
tags = ["units"],
deprecated = true,
}]
fn inner_from_inches(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
match exec_state.length_unit() {
@ -97,14 +112,19 @@ fn inner_from_inches(input: f64, exec_state: &ExecState) -> Result<f64, KclError
/// Feet conversion factor for current files units.
pub async fn from_ft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let input = args.get_number_with_type()?;
let result = inner_from_ft(input.n, exec_state)?;
let input = args.get_number_typed(&RuntimeType::known_length(UnitLen::Feet), exec_state)?;
let result = inner_from_ft(input, exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
Ok(args.make_user_val_from_f64_with_type(TyF64::new(
result,
exec_state.current_default_units().expect_default_length(),
)))
}
/// Converts a number from feet to the current default unit.
///
/// *DEPRECATED* prefer using explicit numberic suffixes (e.g., `42ft`) or the `to...` conversion functions.
///
/// No matter what units the current file uses, this function will always return a number equivalent
/// to the input in feet.
///
@ -126,6 +146,7 @@ pub async fn from_ft(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
#[stdlib {
name = "fromFt",
tags = ["units"],
deprecated = true,
}]
fn inner_from_ft(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
match exec_state.length_unit() {
@ -141,14 +162,19 @@ fn inner_from_ft(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
/// Meters conversion factor for current files units.
pub async fn from_m(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let input = args.get_number_with_type()?;
let result = inner_from_m(input.n, exec_state)?;
let input = args.get_number_typed(&RuntimeType::known_length(UnitLen::M), exec_state)?;
let result = inner_from_m(input, exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
Ok(args.make_user_val_from_f64_with_type(TyF64::new(
result,
exec_state.current_default_units().expect_default_length(),
)))
}
/// Converts a number from meters to the current default unit.
///
/// *DEPRECATED* prefer using explicit numberic suffixes (e.g., `42m`) or the `to...` conversion functions.
///
/// No matter what units the current file uses, this function will always return a number equivalent
/// to the input in meters.
///
@ -170,6 +196,7 @@ pub async fn from_m(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
#[stdlib {
name = "fromM",
tags = ["units"],
deprecated = true,
}]
fn inner_from_m(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
match exec_state.length_unit() {
@ -185,14 +212,19 @@ fn inner_from_m(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
/// Centimeters conversion factor for current files units.
pub async fn from_cm(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let input = args.get_number_with_type()?;
let result = inner_from_cm(input.n, exec_state)?;
let input = args.get_number_typed(&RuntimeType::known_length(UnitLen::Cm), exec_state)?;
let result = inner_from_cm(input, exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
Ok(args.make_user_val_from_f64_with_type(TyF64::new(
result,
exec_state.current_default_units().expect_default_length(),
)))
}
/// Converts a number from centimeters to the current default unit.
///
/// *DEPRECATED* prefer using explicit numberic suffixes (e.g., `42cm`) or the `to...` conversion functions.
///
/// No matter what units the current file uses, this function will always return a number equivalent
/// to the input in centimeters.
///
@ -214,6 +246,7 @@ pub async fn from_cm(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
#[stdlib {
name = "fromCm",
tags = ["units"],
deprecated = true,
}]
fn inner_from_cm(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
match exec_state.length_unit() {
@ -229,14 +262,19 @@ fn inner_from_cm(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
/// Yards conversion factor for current files units.
pub async fn from_yd(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let input = args.get_number_with_type()?;
let result = inner_from_yd(input.n, exec_state)?;
let input = args.get_number_typed(&RuntimeType::known_length(UnitLen::Yards), exec_state)?;
let result = inner_from_yd(input, exec_state)?;
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
Ok(args.make_user_val_from_f64_with_type(TyF64::new(
result,
exec_state.current_default_units().expect_default_length(),
)))
}
/// Converts a number from yards to the current default unit.
///
/// *DEPRECATED* prefer using explicit numberic suffixes (e.g., `42yd`) or the `to...` conversion functions.
///
/// No matter what units the current file uses, this function will always return a number equivalent
/// to the input in yards.
///
@ -258,6 +296,7 @@ pub async fn from_yd(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
#[stdlib {
name = "fromYd",
tags = ["units"],
deprecated = true,
}]
fn inner_from_yd(input: f64, exec_state: &ExecState) -> Result<f64, KclError> {
match exec_state.length_unit() {

View File

@ -54,7 +54,7 @@ export TAU = 6.28318530717958647692528676655900577_
/// |> startProfileAt([0, 0], %)
/// |> angledLine(
/// angle = 30,
/// length = 3 / cos(toRadians(30)),
/// length = 3 / cos(30deg),
/// )
/// |> yLine(endAbsolute = 0)
/// |> close()
@ -71,7 +71,7 @@ export fn cos(@num: number(Angle)): number(_) {}
/// |> startProfileAt([0, 0], %)
/// |> angledLine(
/// angle = 50,
/// length = 15 / sin(toRadians(135)),
/// length = 15 / sin(135deg),
/// )
/// |> yLine(endAbsolute = 0)
/// |> close()
@ -88,7 +88,7 @@ export fn sin(@num: number(Angle)): number(_) {}
/// |> startProfileAt([0, 0], %)
/// |> angledLine(
/// angle = 50,
/// length = 50 * tan(1/2),
/// length = 50 * tan((1/2): number(rad)),
/// )
/// |> yLine(endAbsolute = 0)
/// |> close()
@ -112,10 +112,8 @@ export fn tan(@num: number(Angle)): number(_) {}
///
/// example = extrude(exampleSketch, length = 5)
/// ```
export fn polar(angle: number(Angle), length: number(Length)): Point2d {
// TODO could be done by implicit conversion when UoM coercions are activated.
rads = toRadians(angle)
x = length * cos(rads)
y = length * sin(rads)
export fn polar(angle: number(rad), length: number(Length)): Point2d {
x = length * cos(angle)
y = length * sin(angle)
return [x, y]
}

View File

@ -128,7 +128,7 @@ export END = 'end'
export fn helix(
/// Number of revolutions.
revolutions: number(_),
/// Start angle (in degrees).
/// Start angle.
angleStart: number(Angle),
/// Is the helix rotation counter clockwise? The default is `false`.
ccw?: bool,
@ -383,3 +383,69 @@ export fn revolve(
/// A named tag for the face at the end of the revolve.
tagEnd?: tag,
): Solid {}
/// Convert a number to millimeters from its current units.
export fn toMillimeters(@num: number(mm)): number(mm) {
return num
}
/// Convert a number to centimeters from its current units.
export fn toCentimeters(@num: number(cm)): number(cm) {
return num
}
/// Convert a number to meters from its current units.
export fn toMeters(@num: number(m)): number(m) {
return num
}
/// Convert a number to inches from its current units.
export fn toInches(@num: number(in)): number(in) {
return num
}
/// Convert a number to feet from its current units.
export fn toFeet(@num: number(ft)): number(ft) {
return num
}
/// Converts a number to yards from its current units.
export fn toYards(@num: number(yd)): number(yd) {
return num
}
/// Converts a number to radians from its current units.
///
/// ```
/// exampleSketch = startSketchOn(XZ)
/// |> startProfileAt([0, 0], %)
/// |> angledLine(
/// angle = 50,
/// length = 70 * cos(toRadians(45)),
/// )
/// |> yLine(endAbsolute = 0)
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
export fn toRadians(@num: number(rad)): number(rad) {
return num
}
/// Converts a number to degrees from its current units.
///
/// ```
/// exampleSketch = startSketchOn(XZ)
/// |> startProfileAt([0, 0], %)
/// |> angledLine(
/// angle = 50,
/// length = 70 * cos(toDegrees((PI/4): number(rad))),
/// )
/// |> yLine(endAbsolute = 0)
/// |> close()
///
/// example = extrude(exampleSketch, length = 5)
/// ```
export fn toDegrees(@num: number(deg)): number(deg) {
return num
}

View File

@ -100,13 +100,8 @@ description: Operations executed helix_ccw.kcl
"type": "Number",
"value": 16.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Count"
}
},
"sourceRange": []

View File

@ -91,13 +91,8 @@ description: Operations executed helix_simple.kcl
"type": "Number",
"value": 5.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Count"
}
},
"sourceRange": []

View File

@ -376,6 +376,24 @@ description: Operations executed ball-bearing.kcl
"type": "StdLibCall",
"unlabeledArg": null
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {

View File

@ -2169,26 +2169,18 @@ description: Operations executed car-wheel-assembly.kcl
"type": "Number",
"value": 2.25,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"y": {
"type": "Number",
"value": -1.1811023622047243,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"z": {

View File

@ -145,26 +145,18 @@ description: Variables in memory after executing car-wheel-assembly.kcl
"type": "Number",
"value": 0.9449,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"lugHeadLength": {
"type": "Number",
"value": 0.4724,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"lugHolePatternDia": {
@ -184,13 +176,9 @@ description: Variables in memory after executing car-wheel-assembly.kcl
"type": "Number",
"value": 1.1811,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"lugNut": {
@ -201,52 +189,36 @@ description: Variables in memory after executing car-wheel-assembly.kcl
"type": "Number",
"value": 4.5,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"lugThreadDepth": {
"type": "Number",
"value": 0.6811,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"lugThreadDiameter": {
"type": "Number",
"value": 0.4016,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"offset": {
"type": "Number",
"value": -1.378,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"rotorDiameter": {

View File

@ -78,6 +78,24 @@ description: Operations executed cycloidal-gear.kcl
"type": "StdLibCall",
"unlabeledArg": null
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -100,11 +118,11 @@ description: Operations executed cycloidal-gear.kcl
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "sin",
"name": "toRadians",
"functionSourceRange": [
0,
0,
0
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
@ -132,6 +150,60 @@ description: Operations executed cycloidal-gear.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "sin",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -239,6 +311,24 @@ description: Operations executed cycloidal-gear.kcl
"type": "StdLibCall",
"unlabeledArg": null
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -261,11 +351,11 @@ description: Operations executed cycloidal-gear.kcl
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "sin",
"name": "toRadians",
"functionSourceRange": [
0,
0,
0
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
@ -293,6 +383,60 @@ description: Operations executed cycloidal-gear.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "sin",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -400,6 +544,24 @@ description: Operations executed cycloidal-gear.kcl
"type": "StdLibCall",
"unlabeledArg": null
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -422,11 +584,11 @@ description: Operations executed cycloidal-gear.kcl
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "sin",
"name": "toRadians",
"functionSourceRange": [
0,
0,
0
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
@ -454,6 +616,60 @@ description: Operations executed cycloidal-gear.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "sin",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {

View File

@ -206,7 +206,7 @@ description: Artifact commands dodecahedron.kcl
"origin": {
"x": -17.76901418668612,
"y": 0.0,
"z": 10.981854713951094
"z": 10.981854713951092
},
"x_axis": {
"x": -0.4472135954999579,

View File

@ -3,6 +3,24 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed dodecahedron.kcl
---
[
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -21,6 +39,42 @@ description: Operations executed dodecahedron.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toDegrees",
"functionSourceRange": [
18380,
18429,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -39,6 +93,42 @@ description: Operations executed dodecahedron.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toDegrees",
"functionSourceRange": [
18380,
18429,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -181,7 +271,7 @@ description: Operations executed dodecahedron.kcl
},
{
"type": "Number",
"value": 10.981854713951094,
"value": 10.981854713951092,
"ty": {
"type": "Default",
"len": {

View File

@ -373,7 +373,7 @@ description: Variables in memory after executing dodecahedron.kcl
"origin": {
"x": -17.76901418668612,
"y": 0.0,
"z": 10.981854713951094,
"z": 10.981854713951092,
"units": {
"type": "Inches"
}
@ -589,7 +589,7 @@ description: Variables in memory after executing dodecahedron.kcl
"origin": {
"x": -17.76901418668612,
"y": 0.0,
"z": 10.981854713951094,
"z": 10.981854713951092,
"units": {
"type": "Inches"
}
@ -805,7 +805,7 @@ description: Variables in memory after executing dodecahedron.kcl
"origin": {
"x": -17.76901418668612,
"y": 0.0,
"z": 10.981854713951094,
"z": 10.981854713951092,
"units": {
"type": "Inches"
}
@ -1021,7 +1021,7 @@ description: Variables in memory after executing dodecahedron.kcl
"origin": {
"x": -17.76901418668612,
"y": 0.0,
"z": 10.981854713951094,
"z": 10.981854713951092,
"units": {
"type": "Inches"
}
@ -1237,7 +1237,7 @@ description: Variables in memory after executing dodecahedron.kcl
"origin": {
"x": -17.76901418668612,
"y": 0.0,
"z": 10.981854713951094,
"z": 10.981854713951092,
"units": {
"type": "Inches"
}
@ -1623,7 +1623,7 @@ description: Variables in memory after executing dodecahedron.kcl
"origin": {
"x": -17.76901418668612,
"y": 0.0,
"z": 10.981854713951094,
"z": 10.981854713951092,
"units": {
"type": "Inches"
}
@ -1798,7 +1798,7 @@ description: Variables in memory after executing dodecahedron.kcl
"origin": {
"x": -17.76901418668612,
"y": 0.0,
"z": 10.981854713951094,
"z": 10.981854713951092,
"units": {
"type": "Inches"
}

View File

@ -1257,7 +1257,7 @@ description: Artifact commands exhaust-manifold.kcl
"z": 0.0
},
"x_axis": {
"x": -0.42577929156507266,
"x": -0.4257792915650726,
"y": 0.9048270524660196,
"z": 0.0
},

View File

@ -18,6 +18,24 @@ description: Operations executed exhaust-manifold.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -36,6 +54,24 @@ description: Operations executed exhaust-manifold.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -320,6 +356,24 @@ description: Operations executed exhaust-manifold.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -338,6 +392,24 @@ description: Operations executed exhaust-manifold.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -622,6 +694,24 @@ description: Operations executed exhaust-manifold.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -640,6 +730,24 @@ description: Operations executed exhaust-manifold.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -924,6 +1032,24 @@ description: Operations executed exhaust-manifold.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -942,6 +1068,24 @@ description: Operations executed exhaust-manifold.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -1015,7 +1159,7 @@ description: Operations executed exhaust-manifold.kcl
"value": [
{
"type": "Number",
"value": -0.42577929156507266,
"value": -0.4257792915650726,
"ty": {
"type": "Known",
"type": "Count"

View File

@ -33,6 +33,42 @@ description: Operations executed food-service-spatula.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toDegrees",
"functionSourceRange": [
18380,
18429,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -51,6 +87,24 @@ description: Operations executed food-service-spatula.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -87,6 +141,42 @@ description: Operations executed food-service-spatula.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toDegrees",
"functionSourceRange": [
18380,
18429,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -105,6 +195,24 @@ description: Operations executed food-service-spatula.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -141,6 +249,42 @@ description: Operations executed food-service-spatula.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toDegrees",
"functionSourceRange": [
18380,
18429,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -159,6 +303,24 @@ description: Operations executed food-service-spatula.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -726,6 +888,24 @@ description: Operations executed food-service-spatula.kcl
},
"sourceRange": []
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -744,6 +924,24 @@ description: Operations executed food-service-spatula.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {

View File

@ -1293,27 +1293,42 @@ description: Result of parsing gear.kcl
"arguments": [
{
"commentStart": 0,
"computed": true,
"end": 0,
"object": {
"expr": {
"commentStart": 0,
"computed": true,
"end": 0,
"name": "invas",
"object": {
"commentStart": 0,
"end": 0,
"name": "invas",
"start": 0,
"type": "Identifier",
"type": "Identifier"
},
"property": {
"commentStart": 0,
"end": 0,
"name": "i",
"start": 0,
"type": "Identifier",
"type": "Identifier"
},
"start": 0,
"type": "Identifier",
"type": "Identifier"
},
"property": {
"commentStart": 0,
"end": 0,
"name": "i",
"start": 0,
"type": "Identifier",
"type": "Identifier"
"type": "MemberExpression",
"type": "MemberExpression"
},
"start": 0,
"type": "MemberExpression",
"type": "MemberExpression"
"ty": {
"Rad": null,
"commentStart": 0,
"end": 0,
"start": 0,
"type": "Primitive",
"type": "Number"
},
"type": "AscribedExpression",
"type": "Ascription"
}
],
"callee": {
@ -1492,27 +1507,42 @@ description: Result of parsing gear.kcl
"arguments": [
{
"commentStart": 0,
"computed": true,
"end": 0,
"object": {
"expr": {
"commentStart": 0,
"computed": true,
"end": 0,
"name": "invas",
"object": {
"commentStart": 0,
"end": 0,
"name": "invas",
"start": 0,
"type": "Identifier",
"type": "Identifier"
},
"property": {
"commentStart": 0,
"end": 0,
"name": "i",
"start": 0,
"type": "Identifier",
"type": "Identifier"
},
"start": 0,
"type": "Identifier",
"type": "Identifier"
},
"property": {
"commentStart": 0,
"end": 0,
"name": "i",
"start": 0,
"type": "Identifier",
"type": "Identifier"
"type": "MemberExpression",
"type": "MemberExpression"
},
"start": 0,
"type": "MemberExpression",
"type": "MemberExpression"
"ty": {
"Rad": null,
"commentStart": 0,
"end": 0,
"start": 0,
"type": "Primitive",
"type": "Number"
},
"type": "AscribedExpression",
"type": "Ascription"
}
],
"callee": {

File diff suppressed because it is too large Load Diff

View File

@ -25,13 +25,9 @@ description: Operations executed i-beam.kcl
"type": "Number",
"value": 72.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"sourceRange": []

View File

@ -20,13 +20,9 @@ description: Variables in memory after executing i-beam.kcl
"type": "Number",
"value": 72.0,
"ty": {
"type": "Default",
"len": {
"type": "Inches"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Inches"
}
},
"flangeThickness": {

View File

@ -187,6 +187,24 @@ description: Operations executed keyboard.kcl
"sourceRange": []
}
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -7177,6 +7195,24 @@ description: Operations executed keyboard.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {

File diff suppressed because it is too large Load Diff

View File

@ -1117,13 +1117,13 @@ description: Result of parsing router-template-cross-bar.kcl
"right": {
"commentStart": 0,
"end": 0,
"raw": "2",
"raw": "2_",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 2.0,
"suffix": "None"
"suffix": "Count"
}
},
"start": 0,

View File

@ -3839,26 +3839,18 @@ description: Variables in memory after executing router-template-slate.kcl
"type": "Number",
"value": 17.4625,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Mm"
}
},
"templateGap": {
"type": "Number",
"value": 1.8812,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
"type": "Known",
"type": "Length",
"type": "Mm"
}
},
"templateThickness": {

View File

@ -3,6 +3,24 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed socket-head-cap-screw.kcl
---
[
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {

View File

@ -142,11 +142,11 @@ description: Operations executed walkie-talkie.kcl
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "cos",
"name": "toRadians",
"functionSourceRange": [
0,
0,
0
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
@ -174,6 +174,24 @@ description: Operations executed walkie-talkie.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -192,6 +210,60 @@ description: Operations executed walkie-talkie.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -513,11 +585,11 @@ description: Operations executed walkie-talkie.kcl
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "cos",
"name": "toRadians",
"functionSourceRange": [
0,
0,
0
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
@ -545,6 +617,24 @@ description: Operations executed walkie-talkie.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
@ -563,6 +653,60 @@ description: Operations executed walkie-talkie.kcl
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "cos",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

View File

@ -3,6 +3,24 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed rotate_after_fillet.kcl
---
[
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {

View File

@ -3,6 +3,24 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed scale_after_fillet.kcl
---
[
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {

View File

@ -3,6 +3,24 @@ source: kcl-lib/src/simulation_tests.rs
description: Operations executed translate_after_fillet.kcl
---
[
{
"type": "GroupBegin",
"group": {
"type": "FunctionCall",
"name": "toRadians",
"functionSourceRange": [
17950,
17999,
1
],
"unlabeledArg": null,
"labeledArgs": {}
},
"sourceRange": []
},
{
"type": "GroupEnd"
},
{
"type": "GroupBegin",
"group": {