More types stuff (#5901)

* parse union and fancy array types

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

* type aliases

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

* Treat Helix and Face as primitive types

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

* code motion: factor our execution::types module

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

* Tests for type coercion and subtyping

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

* Add Point2D/3D to std

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

* Rebasing and fixes

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

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-03-21 10:56:55 +13:00
committed by GitHub
parent 9da8574103
commit 1d550da40b
47 changed files with 1773 additions and 1050 deletions

View File

@ -194,9 +194,21 @@ impl Type {
hasher.update(b"FnArgType::Primitive");
hasher.update(prim.compute_digest())
}
Type::Array(prim) => {
Type::Array { ty, len } => {
hasher.update(b"FnArgType::Array");
hasher.update(prim.compute_digest())
hasher.update(ty.compute_digest());
match len {
crate::execution::types::ArrayLen::None => {}
crate::execution::types::ArrayLen::NonEmpty => hasher.update(usize::MAX.to_ne_bytes()),
crate::execution::types::ArrayLen::Known(n) => hasher.update(n.to_ne_bytes()),
}
}
Type::Union { tys } => {
hasher.update(b"FnArgType::Union");
hasher.update(tys.len().to_ne_bytes());
for t in tys.iter_mut() {
hasher.update(t.compute_digest());
}
}
Type::Object { properties } => {
hasher.update(b"FnArgType::Object");
@ -300,6 +312,9 @@ impl TypeDeclaration {
hasher.update(a.compute_digest());
}
}
if let Some(alias) = &mut slf.alias {
hasher.update(alias.compute_digest());
}
});
}

View File

@ -25,7 +25,7 @@ pub use crate::parsing::ast::types::{
use crate::{
docs::StdLibFn,
errors::KclError,
execution::{annotations, KclValue, Metadata, TagIdentifier},
execution::{annotations, types::ArrayLen, KclValue, Metadata, TagIdentifier},
parsing::{ast::digest::Digest, token::NumericSuffix, PIPE_OPERATOR},
source_range::SourceRange,
ModuleId,
@ -150,7 +150,7 @@ impl<T> Node<T> {
self.start <= pos && pos <= self.end
}
pub fn map<U>(self, f: fn(T) -> U) -> Node<U> {
pub fn map<U>(self, f: impl Fn(T) -> U) -> Node<U> {
Node {
inner: f(self.inner),
start: self.start,
@ -1895,6 +1895,7 @@ pub struct TypeDeclaration {
pub args: Option<NodeList<Identifier>>,
#[serde(default, skip_serializing_if = "ItemVisibility::is_default")]
pub visibility: ItemVisibility,
pub alias: Option<Node<Type>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
@ -3024,7 +3025,14 @@ pub enum Type {
/// A primitive type.
Primitive(PrimitiveType),
// An array of a primitive type.
Array(PrimitiveType),
Array {
ty: PrimitiveType,
len: ArrayLen,
},
// Union/enum types
Union {
tys: NodeList<PrimitiveType>,
},
// An object type.
Object {
properties: Vec<Parameter>,
@ -3035,7 +3043,22 @@ impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Type::Primitive(primitive_type) => primitive_type.fmt(f),
Type::Array(primitive_type) => write!(f, "[{primitive_type}]"),
Type::Array { ty, len } => {
write!(f, "[{ty}")?;
match len {
ArrayLen::None => {}
ArrayLen::NonEmpty => write!(f, "; 1+")?,
ArrayLen::Known(n) => write!(f, "; {n}")?,
}
write!(f, "]")
}
Type::Union { tys } => {
write!(
f,
"{}",
tys.iter().map(|t| t.to_string()).collect::<Vec<_>>().join(" | ")
)
}
Type::Object { properties } => {
write!(f, "{{")?;
let mut first = true;
@ -3624,11 +3647,17 @@ const cylinder = startSketchOn('-XZ')
assert_eq!(params.len(), 3);
assert_eq!(
params[0].type_.as_ref().unwrap().inner,
Type::Array(PrimitiveType::Number(NumericSuffix::None))
Type::Array {
ty: PrimitiveType::Number(NumericSuffix::None),
len: ArrayLen::None
}
);
assert_eq!(
params[1].type_.as_ref().unwrap().inner,
Type::Array(PrimitiveType::String)
Type::Array {
ty: PrimitiveType::String,
len: ArrayLen::None
}
);
assert_eq!(
params[2].type_.as_ref().unwrap().inner,
@ -3656,7 +3685,10 @@ const cylinder = startSketchOn('-XZ')
assert_eq!(params.len(), 3);
assert_eq!(
params[0].type_.as_ref().unwrap().inner,
Type::Array(PrimitiveType::Number(NumericSuffix::None))
Type::Array {
ty: PrimitiveType::Number(NumericSuffix::None),
len: ArrayLen::None
}
);
assert_eq!(
params[1].type_.as_ref().unwrap().inner,
@ -3692,7 +3724,15 @@ const cylinder = startSketchOn('-XZ')
56,
module_id,
),
type_: Some(Node::new(Type::Array(PrimitiveType::String), 59, 65, module_id)),
type_: Some(Node::new(
Type::Array {
ty: PrimitiveType::String,
len: ArrayLen::None
},
59,
65,
module_id
)),
default_value: None,
labeled: true,
digest: None
@ -3773,7 +3813,15 @@ const cylinder = startSketchOn('-XZ')
34,
module_id,
),
type_: Some(Node::new(Type::Array(PrimitiveType::String), 37, 43, module_id)),
type_: Some(Node::new(
Type::Array {
ty: PrimitiveType::String,
len: ArrayLen::None
},
37,
43,
module_id
)),
default_value: None,
labeled: true,
digest: None
@ -3946,7 +3994,7 @@ startSketchOn('XY')"#;
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Inches
crate::execution::types::UnitLen::Inches
);
}
@ -3962,13 +4010,13 @@ startSketchOn('XY')"#;
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Inches
crate::execution::types::UnitLen::Inches
);
// Edit the ast.
let new_program = program
.change_meta_settings(crate::execution::MetaSettings {
default_length_units: crate::execution::kcl_value::UnitLen::Mm,
default_length_units: crate::execution::types::UnitLen::Mm,
..Default::default()
})
.unwrap();
@ -3977,10 +4025,7 @@ startSketchOn('XY')"#;
assert!(result.is_some());
let meta_settings = result.unwrap();
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Mm
);
assert_eq!(meta_settings.default_length_units, crate::execution::types::UnitLen::Mm);
let formatted = new_program.recast(&Default::default(), 0);
@ -4003,7 +4048,7 @@ startSketchOn('XY')
// Edit the ast.
let new_program = program
.change_meta_settings(crate::execution::MetaSettings {
default_length_units: crate::execution::kcl_value::UnitLen::Mm,
default_length_units: crate::execution::types::UnitLen::Mm,
..Default::default()
})
.unwrap();
@ -4012,10 +4057,7 @@ startSketchOn('XY')
assert!(result.is_some());
let meta_settings = result.unwrap();
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Mm
);
assert_eq!(meta_settings.default_length_units, crate::execution::types::UnitLen::Mm);
let formatted = new_program.recast(&Default::default(), 0);