More propagation of numeric types (#6177)

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-04-07 19:02:41 +12:00
committed by GitHub
parent bc22d888ee
commit be05dd7ba1
24 changed files with 631 additions and 350 deletions

View File

@ -10,16 +10,16 @@ use serde::{Deserialize, Serialize};
use crate::{
errors::KclError,
execution::{ArtifactId, ExecState, Metadata, TagEngineInfo, TagIdentifier, UnitLen},
execution::{types::NumericType, ArtifactId, ExecState, Metadata, TagEngineInfo, TagIdentifier, UnitLen},
parsing::ast::types::{Node, NodeRef, TagDeclarator, TagNode},
std::sketch::PlaneData,
std::{args::TyF64, sketch::PlaneData},
};
type Point2D = kcmc::shared::Point2d<f64>;
type Point3D = kcmc::shared::Point3d<f64>;
/// A geometry.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
pub enum Geometry {
@ -47,7 +47,7 @@ impl Geometry {
}
/// A set of geometry.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
#[allow(clippy::vec_box)]
@ -66,7 +66,7 @@ impl From<Geometry> for Geometries {
}
/// Data for an imported geometry.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ImportedGeometry {
@ -79,7 +79,7 @@ pub struct ImportedGeometry {
}
/// Data for a solid or an imported geometry.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
#[allow(clippy::vec_box)]
@ -159,7 +159,7 @@ pub struct Helix {
pub meta: Vec<Metadata>,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct Plane {
@ -353,7 +353,7 @@ impl Plane {
}
/// A face.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct Face {
@ -377,7 +377,7 @@ pub struct Face {
}
/// Type for a plane.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)]
#[ts(export)]
#[display(style = "camelCase")]
pub enum PlaneType {
@ -398,7 +398,7 @@ pub enum PlaneType {
Uninit,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
pub struct Sketch {
@ -463,7 +463,7 @@ impl Sketch {
}
/// A sketch type.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum SketchSurface {
@ -582,7 +582,7 @@ impl Sketch {
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
pub struct Solid {
@ -616,7 +616,7 @@ impl Solid {
}
/// A fillet or a chamfer.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum EdgeCut {
@ -678,6 +678,12 @@ impl From<[f64; 2]> for Point2d {
}
}
impl From<[TyF64; 2]> for Point2d {
fn from(p: [TyF64; 2]) -> Self {
Self { x: p[0].n, y: p[1].n }
}
}
impl From<&[f64; 2]> for Point2d {
fn from(p: &[f64; 2]) -> Self {
Self { x: p[0], y: p[1] }
@ -767,7 +773,7 @@ impl Mul<f64> for Point3d {
}
/// A base path.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct BasePath {
@ -786,7 +792,7 @@ pub struct BasePath {
}
/// Geometry metadata.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct GeoMeta {
@ -798,7 +804,7 @@ pub struct GeoMeta {
}
/// A path.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type")]
pub enum Path {
@ -979,19 +985,23 @@ impl Path {
}
/// Where does this path segment start?
pub fn get_from(&self) -> &[f64; 2] {
&self.get_base().from
pub fn get_from(&self) -> [TyF64; 2] {
let p = &self.get_base().from;
let ty: NumericType = self.get_base().units.into();
[TyF64::new(p[0], ty.clone()), TyF64::new(p[1], ty)]
}
/// Where does this path segment end?
pub fn get_to(&self) -> &[f64; 2] {
&self.get_base().to
pub fn get_to(&self) -> [TyF64; 2] {
let p = &self.get_base().to;
let ty: NumericType = self.get_base().units.into();
[TyF64::new(p[0], ty.clone()), TyF64::new(p[1], ty)]
}
/// Length of this path segment, in cartesian plane.
pub fn length(&self) -> f64 {
match self {
pub fn length(&self) -> TyF64 {
let n = match self {
Self::ToPoint { .. } | Self::Base { .. } | Self::Horizontal { .. } | Self::AngledLineTo { .. } => {
linear_distance(self.get_from(), self.get_to())
linear_distance(&self.get_base().from, &self.get_base().to)
}
Self::TangentialArc {
base: _,
@ -1005,10 +1015,10 @@ impl Path {
} => {
// The radius can be calculated as the linear distance between `to` and `center`,
// or between `from` and `center`. They should be the same.
let radius = linear_distance(self.get_from(), center);
debug_assert_eq!(radius, linear_distance(self.get_to(), center));
let radius = linear_distance(&self.get_base().from, center);
debug_assert_eq!(radius, linear_distance(&self.get_base().to, center));
// TODO: Call engine utils to figure this out.
linear_distance(self.get_from(), self.get_to())
linear_distance(&self.get_base().from, &self.get_base().to)
}
Self::Circle { radius, .. } => 2.0 * std::f64::consts::PI * radius,
Self::CircleThreePoint { .. } => {
@ -1022,13 +1032,14 @@ impl Path {
}
Self::Arc { .. } => {
// TODO: Call engine utils to figure this out.
linear_distance(self.get_from(), self.get_to())
linear_distance(&self.get_base().from, &self.get_base().to)
}
Self::ArcThreePoint { .. } => {
// TODO: Call engine utils to figure this out.
linear_distance(self.get_from(), self.get_to())
linear_distance(&self.get_base().from, &self.get_base().to)
}
}
};
TyF64::new(n, self.get_base().units.into())
}
pub fn get_base_mut(&mut self) -> Option<&mut BasePath> {
@ -1103,7 +1114,7 @@ fn linear_distance(
}
/// An extrude surface.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ExtrudeSurface {
@ -1115,7 +1126,7 @@ pub enum ExtrudeSurface {
}
// Chamfer surface.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ChamferSurface {
@ -1129,7 +1140,7 @@ pub struct ChamferSurface {
}
// Fillet surface.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct FilletSurface {
@ -1143,7 +1154,7 @@ pub struct FilletSurface {
}
/// An extruded plane.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ExtrudePlane {
@ -1157,7 +1168,7 @@ pub struct ExtrudePlane {
}
/// An extruded arc.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ExtrudeArc {

View File

@ -175,7 +175,7 @@ impl std::hash::Hash for TagIdentifier {
}
/// Engine information for a tag.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
pub struct TagEngineInfo {

View File

@ -22,6 +22,8 @@ use crate::{
CompilationError,
};
use super::types::NumericType;
/// State for executing a program.
#[derive(Debug, Clone)]
pub struct ExecState {
@ -228,6 +230,13 @@ impl ExecState {
self.global.module_infos.insert(id, module_info);
}
pub fn current_default_units(&self) -> NumericType {
NumericType::Default {
len: self.length_unit(),
angle: self.angle_unit(),
}
}
pub fn length_unit(&self) -> UnitLen {
self.mod_local.settings.default_length_units
}

View File

@ -371,14 +371,22 @@ impl Default for NumericType {
}
impl NumericType {
pub fn count() -> Self {
pub const fn count() -> Self {
NumericType::Known(UnitType::Count)
}
pub fn mm() -> Self {
pub const fn mm() -> Self {
NumericType::Known(UnitType::Length(UnitLen::Mm))
}
pub const fn radians() -> Self {
NumericType::Known(UnitType::Angle(UnitAngle::Radians))
}
pub const fn degrees() -> Self {
NumericType::Known(UnitType::Angle(UnitAngle::Degrees))
}
/// Combine two types when we expect them to be equal.
pub fn combine_eq(a: TyF64, b: TyF64) -> (f64, f64, NumericType) {
use NumericType::*;