Tag as top level construct (#2769)

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* udpages

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* better functions

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* backwards compat everywhere

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* udpates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add lsp symbols stuff;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* tests for dupes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Revert "tests for dupes"

This reverts commit 6acaf5a9fa.

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* initial test updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* test

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2024-06-24 14:45:07 -07:00
committed by GitHub
parent f4877cb160
commit 3304a74064
77 changed files with 40447 additions and 7883 deletions

View File

@ -13,6 +13,7 @@ pub mod segment;
pub mod shapes;
pub mod shell;
pub mod sketch;
pub mod string_or_struct;
pub mod types;
pub mod utils;
@ -27,12 +28,12 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
ast::types::parse_json_number_as_f64,
ast::types::{parse_json_number_as_f64, TagDeclarator},
docs::StdLibFn,
errors::{KclError, KclErrorDetails},
executor::{
ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata, ProgramMemory,
SketchGroup, SketchGroupSet, SketchSurface, SourceRange,
SketchGroup, SketchGroupSet, SketchSurface, SourceRange, TagIdentifier,
},
std::{kcl_stdlib::KclStdLibFn, sketch::FaceTag},
};
@ -361,7 +362,15 @@ impl Args {
fn get_circle_args(
&self,
) -> Result<([f64; 2], f64, crate::std::shapes::SketchSurfaceOrGroup, Option<String>), KclError> {
) -> Result<
(
[f64; 2],
f64,
crate::std::shapes::SketchSurfaceOrGroup,
Option<TagDeclarator>,
),
KclError,
> {
let first_value = self
.args
.first()
@ -443,41 +452,26 @@ impl Args {
}));
};
if let Some(fourth_value) = self.args.get(3) {
let tag: String = serde_json::from_value(fourth_value.get_json_value()?).map_err(|e| {
KclError::Type(KclErrorDetails {
message: format!("Failed to deserialize String from JSON: {}", e),
source_ranges: vec![self.source_range],
})
})?;
Ok((center, radius, sketch_group_or_surface, Some(tag)))
let tag = if let Some(tag) = self.args.get(3) {
tag.get_tag_declarator_opt()?
} else {
Ok((center, radius, sketch_group_or_surface, None))
}
None
};
Ok((center, radius, sketch_group_or_surface, tag))
}
fn get_segment_name_sketch_group(&self) -> Result<(String, Box<SketchGroup>), KclError> {
fn get_segment_name_sketch_group(&self) -> Result<(TagIdentifier, Box<SketchGroup>), KclError> {
// Iterate over our args, the first argument should be a UserVal with a string value.
// The second argument should be a SketchGroup.
let first_value = self
.args
.first()
.ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
source_ranges: vec![self.source_range],
})
})?
.get_json_value()?;
let segment_name = if let serde_json::Value::String(s) = first_value {
s.to_string()
} else {
return Err(KclError::Type(KclErrorDetails {
let first_value = self.args.first().ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
source_ranges: vec![self.source_range],
}));
};
})
})?;
let segment_name = first_value.get_tag_identifier()?;
let second_value = self.args.get(1).ok_or_else(|| {
KclError::Type(KclErrorDetails {
@ -609,7 +603,7 @@ impl Args {
}
}
fn get_sketch_group_and_optional_tag(&self) -> Result<(Box<SketchGroup>, Option<String>), KclError> {
fn get_sketch_group_and_optional_tag(&self) -> Result<(Box<SketchGroup>, Option<TagDeclarator>), KclError> {
let first_value = self.args.first().ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a SketchGroup as the first argument, found `{:?}`", self.args),
@ -626,17 +620,13 @@ impl Args {
}));
};
if let Some(second_value) = self.args.get(1) {
let tag: String = serde_json::from_value(second_value.get_json_value()?).map_err(|e| {
KclError::Type(KclErrorDetails {
message: format!("Failed to deserialize String from JSON: {}", e),
source_ranges: vec![self.source_range],
})
})?;
Ok((sketch_group, Some(tag)))
let tag = if let Some(tag) = self.args.get(1) {
tag.get_tag_declarator_opt()?
} else {
Ok((sketch_group, None))
}
None
};
Ok((sketch_group, tag))
}
fn get_data_and_optional_tag<T: serde::de::DeserializeOwned>(&self) -> Result<(T, Option<FaceTag>), KclError> {
@ -750,7 +740,7 @@ impl Args {
fn get_data_and_sketch_group_and_tag<T: serde::de::DeserializeOwned>(
&self,
) -> Result<(T, Box<SketchGroup>, Option<String>), KclError> {
) -> Result<(T, Box<SketchGroup>, Option<TagDeclarator>), KclError> {
let first_value = self
.args
.first()
@ -785,7 +775,7 @@ impl Args {
}));
};
let tag = if let Some(tag) = self.args.get(2) {
tag.get_json_opt()?
tag.get_tag_declarator_opt()?
} else {
None
};
@ -795,7 +785,7 @@ impl Args {
fn get_data_and_sketch_surface<T: serde::de::DeserializeOwned>(
&self,
) -> Result<(T, SketchSurface, Option<String>), KclError> {
) -> Result<(T, SketchSurface, Option<TagDeclarator>), KclError> {
let first_value = self
.args
.first()
@ -834,8 +824,9 @@ impl Args {
source_ranges: vec![self.source_range],
}));
};
let tag = if let Some(tag) = self.args.get(2) {
tag.get_json_opt()?
tag.get_tag_declarator_opt()?
} else {
None
};
@ -931,7 +922,7 @@ impl Args {
fn get_data_and_extrude_group_and_tag<T: serde::de::DeserializeOwned>(
&self,
) -> Result<(T, Box<ExtrudeGroup>, Option<String>), KclError> {
) -> Result<(T, Box<ExtrudeGroup>, Option<TagDeclarator>), KclError> {
let first_value = self
.args
.first()
@ -971,8 +962,9 @@ impl Args {
source_ranges: vec![self.source_range],
}));
};
let tag = if let Some(tag) = self.args.get(2) {
tag.get_json_opt()?
tag.get_tag_declarator_opt()?
} else {
None
};
@ -980,30 +972,54 @@ impl Args {
Ok((data, extrude_group, tag))
}
fn get_segment_name_to_number_sketch_group(&self) -> Result<(String, f64, Box<SketchGroup>), KclError> {
// Iterate over our args, the first argument should be a UserVal with a string value.
// The second argument should be a number.
// The third argument should be a SketchGroup.
let first_value = self
.args
.first()
.ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
source_ranges: vec![self.source_range],
})
})?
.get_json_value()?;
fn get_tag_and_extrude_group(&self) -> Result<(TagIdentifier, Box<ExtrudeGroup>), KclError> {
let first_value = self.args.first().ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a struct as the first argument, found `{:?}`", self.args),
source_ranges: vec![self.source_range],
})
})?;
let segment_name = if let serde_json::Value::String(s) = first_value {
s.to_string()
let tag = first_value.get_tag_identifier()?;
let second_value = self.args.get(1).ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!(
"Expected an ExtrudeGroup as the second argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
})
})?;
let extrude_group = if let MemoryItem::ExtrudeGroup(eg) = second_value {
eg.clone()
} else {
return Err(KclError::Type(KclErrorDetails {
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
message: format!(
"Expected an ExtrudeGroup as the second argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
}));
};
Ok((tag, extrude_group))
}
fn get_segment_name_to_number_sketch_group(&self) -> Result<(TagIdentifier, f64, Box<SketchGroup>), KclError> {
// Iterate over our args, the first argument should be a UserVal with a string value.
// The second argument should be a number.
// The third argument should be a SketchGroup.
let first_value = self.args.first().ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a string as the first argument, found `{:?}`", self.args),
source_ranges: vec![self.source_range],
})
})?;
let segment_name = first_value.get_tag_identifier()?;
let second_value = self
.args
.get(1)
@ -1075,10 +1091,10 @@ impl Args {
pub async fn get_adjacent_face_to_tag(
&self,
extrude_group: &ExtrudeGroup,
tag: &str,
tag: &TagIdentifier,
must_be_planar: bool,
) -> Result<uuid::Uuid, KclError> {
if tag.is_empty() {
if tag.value.is_empty() {
return Err(KclError::Type(KclErrorDetails {
message: "Expected a non-empty tag for the face".to_string(),
source_ranges: vec![self.source_range],
@ -1089,16 +1105,33 @@ impl Args {
.value
.iter()
.find_map(|extrude_surface| match extrude_surface {
ExtrudeSurface::ExtrudePlane(extrude_plane) if extrude_plane.name == tag => {
Some(Ok(extrude_plane.face_id))
ExtrudeSurface::ExtrudePlane(extrude_plane) => {
if let Some(plane_tag) = &extrude_plane.tag {
if plane_tag.name == tag.value {
Some(Ok(extrude_plane.face_id))
} else {
None
}
} else {
None
}
}
// The must be planar check must be called before the arc check.
ExtrudeSurface::ExtrudeArc(_) if must_be_planar => Some(Err(KclError::Type(KclErrorDetails {
message: format!("Tag `{}` is a non-planar surface", tag),
message: format!("Tag `{}` is a non-planar surface", tag.value),
source_ranges: vec![self.source_range],
}))),
ExtrudeSurface::ExtrudeArc(extrude_arc) if extrude_arc.name == tag => Some(Ok(extrude_arc.face_id)),
ExtrudeSurface::ExtrudePlane(_) | ExtrudeSurface::ExtrudeArc(_) => None,
ExtrudeSurface::ExtrudeArc(extrude_arc) => {
if let Some(arc_tag) = &extrude_arc.tag {
if arc_tag.name == tag.value {
Some(Ok(extrude_arc.face_id))
} else {
None
}
} else {
None
}
}
})
{
return face_from_surface;
@ -1106,8 +1139,12 @@ impl Args {
// A face could also be the result of a chamfer or fillet.
if let Some(face_from_chamfer_fillet) = extrude_group.fillet_or_chamfers.iter().find_map(|fc| {
if fc.tag() == Some(tag) {
Some(Ok(fc.id()))
if let Some(ntag) = &fc.tag() {
if ntag.name == tag.value {
Some(Ok(fc.id()))
} else {
None
}
} else {
None
}
@ -1120,7 +1157,7 @@ impl Args {
// If we still haven't found the face, return an error.
Err(KclError::Type(KclErrorDetails {
message: format!("Expected a face with the tag `{}`", tag),
message: format!("Expected a face with the tag `{}`", tag.value),
source_ranges: vec![self.source_range],
}))
}