Merge remote-tracking branch 'origin/main' into ben/conics
This commit is contained in:
@ -173,7 +173,11 @@ fn generate_example(index: usize, src: &str, props: &ExampleProperties, file_nam
|
||||
return None;
|
||||
}
|
||||
|
||||
let content = if props.inline { "" } else { src };
|
||||
let content = if props.inline {
|
||||
String::new()
|
||||
} else {
|
||||
crate::unparser::fmt(src).unwrap()
|
||||
};
|
||||
|
||||
let image_base64 = if props.norun {
|
||||
String::new()
|
||||
|
@ -676,7 +676,7 @@ impl EdgeCut {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ArtifactGraph {
|
||||
map: IndexMap<ArtifactId, Artifact>,
|
||||
item_count: usize,
|
||||
pub(super) item_count: usize,
|
||||
}
|
||||
|
||||
impl ArtifactGraph {
|
||||
|
@ -1,13 +1,12 @@
|
||||
use indexmap::IndexMap;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
|
||||
use super::{types::NumericType, ArtifactId, KclValue};
|
||||
use crate::{ModuleId, SourceRange};
|
||||
use crate::{ModuleId, NodePath, SourceRange};
|
||||
|
||||
/// A CAD modeling operation for display in the feature tree, AKA operations
|
||||
/// timeline.
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Operation.ts")]
|
||||
#[serde(tag = "type")]
|
||||
pub enum Operation {
|
||||
@ -18,6 +17,8 @@ pub enum Operation {
|
||||
unlabeled_arg: Option<OpArg>,
|
||||
/// The labeled keyword arguments to the function.
|
||||
labeled_args: IndexMap<String, OpArg>,
|
||||
/// The node path of the operation in the source code.
|
||||
node_path: NodePath,
|
||||
/// The source range of the operation in the source code.
|
||||
source_range: SourceRange,
|
||||
/// True if the operation resulted in an error.
|
||||
@ -28,6 +29,8 @@ pub enum Operation {
|
||||
GroupBegin {
|
||||
/// The details of the group.
|
||||
group: Group,
|
||||
/// The node path of the operation in the source code.
|
||||
node_path: NodePath,
|
||||
/// The source range of the operation in the source code.
|
||||
source_range: SourceRange,
|
||||
},
|
||||
@ -64,7 +67,7 @@ impl Operation {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Operation.ts")]
|
||||
#[serde(tag = "type")]
|
||||
#[expect(clippy::large_enum_variant)]
|
||||
@ -95,7 +98,7 @@ pub enum Group {
|
||||
}
|
||||
|
||||
/// An argument to a CAD modeling operation.
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Operation.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct OpArg {
|
||||
@ -119,7 +122,7 @@ fn is_false(b: &bool) -> bool {
|
||||
|
||||
/// A KCL value used in Operations. `ArtifactId`s are used to refer to the
|
||||
/// actual scene objects. Any data not needed in the UI may be omitted.
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Operation.ts")]
|
||||
#[serde(tag = "type")]
|
||||
pub enum OpKclValue {
|
||||
@ -177,21 +180,21 @@ pub enum OpKclValue {
|
||||
|
||||
pub type OpKclObjectFields = IndexMap<String, OpKclValue>;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Operation.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct OpSketch {
|
||||
artifact_id: ArtifactId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Operation.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct OpSolid {
|
||||
artifact_id: ArtifactId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Operation.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct OpHelix {
|
||||
|
@ -19,8 +19,8 @@ use crate::{
|
||||
parsing::ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, AscribedExpression, BinaryExpression, BinaryOperator,
|
||||
BinaryPart, BodyItem, Expr, IfExpression, ImportPath, ImportSelector, ItemVisibility, LiteralIdentifier,
|
||||
LiteralValue, MemberExpression, MemberObject, Name, Node, NodeRef, ObjectExpression, PipeExpression, Program,
|
||||
TagDeclarator, Type, UnaryExpression, UnaryOperator,
|
||||
LiteralValue, MemberExpression, Name, Node, NodeRef, ObjectExpression, PipeExpression, Program, TagDeclarator,
|
||||
Type, UnaryExpression, UnaryOperator,
|
||||
},
|
||||
source_range::SourceRange,
|
||||
std::args::TyF64,
|
||||
@ -307,7 +307,7 @@ impl ExecutorContext {
|
||||
// During the evaluation of the variable's RHS, set context that this is all happening inside a variable
|
||||
// declaration, for the given name. This helps improve user-facing error messages.
|
||||
let lhs = variable_declaration.inner.name().to_owned();
|
||||
let prev_being_declared = exec_state.mod_local.being_declared.clone();
|
||||
let prev_being_declared = exec_state.mod_local.being_declared.take();
|
||||
exec_state.mod_local.being_declared = Some(lhs);
|
||||
let rhs_result = self
|
||||
.execute_expr(
|
||||
@ -739,7 +739,7 @@ impl ExecutorContext {
|
||||
Expr::ArrayExpression(array_expression) => array_expression.execute(exec_state, self).await?,
|
||||
Expr::ArrayRangeExpression(range_expression) => range_expression.execute(exec_state, self).await?,
|
||||
Expr::ObjectExpression(object_expression) => object_expression.execute(exec_state, self).await?,
|
||||
Expr::MemberExpression(member_expression) => member_expression.get_result(exec_state)?,
|
||||
Expr::MemberExpression(member_expression) => member_expression.get_result(exec_state, self).await?,
|
||||
Expr::UnaryExpression(unary_expression) => unary_expression.get_result(exec_state, self).await?,
|
||||
Expr::IfExpression(expr) => expr.get_result(exec_state, self).await?,
|
||||
Expr::LabelledExpression(expr) => {
|
||||
@ -825,7 +825,7 @@ impl BinaryPart {
|
||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, ctx).await,
|
||||
BinaryPart::CallExpressionKw(call_expression) => call_expression.execute(exec_state, ctx).await,
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.get_result(exec_state, ctx).await,
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.get_result(exec_state),
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.get_result(exec_state, ctx).await,
|
||||
BinaryPart::IfExpression(e) => e.get_result(exec_state, ctx).await,
|
||||
BinaryPart::AscribedExpression(e) => e.get_result(exec_state, ctx).await,
|
||||
}
|
||||
@ -942,16 +942,14 @@ impl Node<Name> {
|
||||
}
|
||||
|
||||
impl Node<MemberExpression> {
|
||||
fn get_result(&self, exec_state: &mut ExecState) -> Result<KclValue, KclError> {
|
||||
async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {
|
||||
let property = Property::try_from(self.computed, self.property.clone(), exec_state, self.into())?;
|
||||
let object = match &self.object {
|
||||
// TODO: Don't use recursion here, use a loop.
|
||||
MemberObject::MemberExpression(member_expr) => member_expr.get_result(exec_state)?,
|
||||
MemberObject::Identifier(identifier) => {
|
||||
let value = exec_state.stack().get(&identifier.name, identifier.into())?;
|
||||
value.clone()
|
||||
}
|
||||
let meta = Metadata {
|
||||
source_range: SourceRange::from(self),
|
||||
};
|
||||
let object = ctx
|
||||
.execute_expr(&self.object, exec_state, &meta, &[], StatementKind::Expression)
|
||||
.await?;
|
||||
|
||||
// Check the property and object match -- e.g. ints for arrays, strs for objects.
|
||||
match (object, property, self.computed) {
|
||||
|
@ -14,7 +14,7 @@ use crate::{
|
||||
parsing::ast::types::{CallExpressionKw, DefaultParamVal, FunctionExpression, Node, Program, Type},
|
||||
source_range::SourceRange,
|
||||
std::StdFn,
|
||||
CompilationError,
|
||||
CompilationError, NodePath,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -322,6 +322,7 @@ impl FunctionDefinition<'_> {
|
||||
.unlabeled_kw_arg_unconverted()
|
||||
.map(|arg| OpArg::new(OpKclValue::from(&arg.value), arg.source_range)),
|
||||
labeled_args: op_labeled_args,
|
||||
node_path: NodePath::placeholder(),
|
||||
source_range: callsite,
|
||||
is_error: false,
|
||||
})
|
||||
@ -337,6 +338,7 @@ impl FunctionDefinition<'_> {
|
||||
.map(|arg| OpArg::new(OpKclValue::from(&arg.1.value), arg.1.source_range)),
|
||||
labeled_args: op_labeled_args,
|
||||
},
|
||||
node_path: NodePath::placeholder(),
|
||||
source_range: callsite,
|
||||
});
|
||||
|
||||
|
@ -7,6 +7,7 @@ use anyhow::Result;
|
||||
pub use artifact::{Artifact, ArtifactCommand, ArtifactGraph, CodeRef, StartSketchOnFace, StartSketchOnPlane};
|
||||
use cache::GlobalState;
|
||||
pub use cache::{bust_cache, clear_mem_cache};
|
||||
#[cfg(feature = "artifact-graph")]
|
||||
pub use cad_op::{Group, Operation};
|
||||
pub use geometry::*;
|
||||
pub use id_generator::IdGenerator;
|
||||
@ -842,31 +843,14 @@ impl ExecutorContext {
|
||||
let module_path = module_path.clone();
|
||||
let source_range = SourceRange::from(import_stmt);
|
||||
|
||||
match &module_path {
|
||||
ModulePath::Main => {
|
||||
// This should never happen.
|
||||
}
|
||||
ModulePath::Local { value, .. } => {
|
||||
// We only want to display the top-level module imports in
|
||||
// the Feature Tree, not transitive imports.
|
||||
if universe_map.contains_key(value) {
|
||||
exec_state.push_op(Operation::GroupBegin {
|
||||
group: Group::ModuleInstance {
|
||||
name: value.file_name().unwrap_or_default(),
|
||||
module_id,
|
||||
},
|
||||
source_range,
|
||||
});
|
||||
// Due to concurrent execution, we cannot easily
|
||||
// group operations by module. So we leave the
|
||||
// group empty and close it immediately.
|
||||
exec_state.push_op(Operation::GroupEnd);
|
||||
}
|
||||
}
|
||||
ModulePath::Std { .. } => {
|
||||
// We don't want to display stdlib in the Feature Tree.
|
||||
}
|
||||
}
|
||||
self.add_import_module_ops(
|
||||
exec_state,
|
||||
program,
|
||||
module_id,
|
||||
&module_path,
|
||||
source_range,
|
||||
&universe_map,
|
||||
);
|
||||
|
||||
let repr = repr.clone();
|
||||
let exec_state = exec_state.clone();
|
||||
@ -1009,6 +993,67 @@ impl ExecutorContext {
|
||||
Ok((universe, root_imports))
|
||||
}
|
||||
|
||||
#[cfg(feature = "artifact-graph")]
|
||||
fn add_import_module_ops(
|
||||
&self,
|
||||
exec_state: &mut ExecState,
|
||||
program: &crate::Program,
|
||||
module_id: ModuleId,
|
||||
module_path: &ModulePath,
|
||||
source_range: SourceRange,
|
||||
universe_map: &UniverseMap,
|
||||
) {
|
||||
match module_path {
|
||||
ModulePath::Main => {
|
||||
// This should never happen.
|
||||
}
|
||||
ModulePath::Local { value, .. } => {
|
||||
// We only want to display the top-level module imports in
|
||||
// the Feature Tree, not transitive imports.
|
||||
if universe_map.contains_key(value) {
|
||||
use crate::NodePath;
|
||||
|
||||
let node_path = if source_range.is_top_level_module() {
|
||||
let cached_body_items = exec_state.global.artifacts.cached_body_items();
|
||||
NodePath::from_range(&program.ast, cached_body_items, source_range).unwrap_or_default()
|
||||
} else {
|
||||
// The frontend doesn't care about paths in
|
||||
// files other than the top-level module.
|
||||
NodePath::placeholder()
|
||||
};
|
||||
|
||||
exec_state.push_op(Operation::GroupBegin {
|
||||
group: Group::ModuleInstance {
|
||||
name: value.file_name().unwrap_or_default(),
|
||||
module_id,
|
||||
},
|
||||
node_path,
|
||||
source_range,
|
||||
});
|
||||
// Due to concurrent execution, we cannot easily
|
||||
// group operations by module. So we leave the
|
||||
// group empty and close it immediately.
|
||||
exec_state.push_op(Operation::GroupEnd);
|
||||
}
|
||||
}
|
||||
ModulePath::Std { .. } => {
|
||||
// We don't want to display stdlib in the Feature Tree.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "artifact-graph"))]
|
||||
fn add_import_module_ops(
|
||||
&self,
|
||||
_exec_state: &mut ExecState,
|
||||
_program: &crate::Program,
|
||||
_module_id: ModuleId,
|
||||
_module_path: &ModulePath,
|
||||
_source_range: SourceRange,
|
||||
_universe_map: &UniverseMap,
|
||||
) {
|
||||
}
|
||||
|
||||
/// Perform the execution of a program. Accept all possible parameters and
|
||||
/// output everything.
|
||||
async fn inner_run(
|
||||
@ -1059,6 +1104,11 @@ impl ExecutorContext {
|
||||
// Don't early return! We need to build other outputs regardless of
|
||||
// whether execution failed.
|
||||
|
||||
// Because of execution caching, we may start with operations from a
|
||||
// previous run.
|
||||
#[cfg(feature = "artifact-graph")]
|
||||
let start_op = exec_state.global.artifacts.operations.len();
|
||||
|
||||
self.eval_prelude(exec_state, SourceRange::from(program).start_as_range())
|
||||
.await?;
|
||||
|
||||
@ -1072,6 +1122,29 @@ impl ExecutorContext {
|
||||
)
|
||||
.await;
|
||||
|
||||
#[cfg(feature = "artifact-graph")]
|
||||
{
|
||||
// Fill in NodePath for operations.
|
||||
let cached_body_items = exec_state.global.artifacts.cached_body_items();
|
||||
for op in exec_state.global.artifacts.operations.iter_mut().skip(start_op) {
|
||||
match op {
|
||||
Operation::StdLibCall {
|
||||
node_path,
|
||||
source_range,
|
||||
..
|
||||
}
|
||||
| Operation::GroupBegin {
|
||||
node_path,
|
||||
source_range,
|
||||
..
|
||||
} => {
|
||||
node_path.fill_placeholder(program, cached_body_items, *source_range);
|
||||
}
|
||||
Operation::GroupEnd => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure all the async commands completed.
|
||||
self.engine.ensure_async_commands_completed().await?;
|
||||
|
||||
@ -1949,7 +2022,7 @@ notPipeSub = 1 |> identity(!%))";
|
||||
// a runtime error instead.
|
||||
parse_execute(code11).await.unwrap_err(),
|
||||
KclError::new_syntax(KclErrorDetails::new(
|
||||
"There was an unexpected !. Try removing it.".to_owned(),
|
||||
"There was an unexpected `!`. Try removing it.".to_owned(),
|
||||
vec![SourceRange::new(56, 57, ModuleId::default())],
|
||||
))
|
||||
);
|
||||
|
@ -48,7 +48,7 @@ pub(super) struct GlobalState {
|
||||
pub mod_loader: ModuleLoader,
|
||||
/// Errors and warnings.
|
||||
pub errors: Vec<CompilationError>,
|
||||
#[allow(dead_code)]
|
||||
#[cfg_attr(not(feature = "artifact-graph"), allow(dead_code))]
|
||||
pub artifacts: ArtifactState,
|
||||
}
|
||||
|
||||
@ -381,6 +381,13 @@ impl GlobalState {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "artifact-graph")]
|
||||
impl ArtifactState {
|
||||
pub fn cached_body_items(&self) -> usize {
|
||||
self.graph.item_count
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleState {
|
||||
pub(super) fn new(path: ModulePath, memory: Arc<ProgramMemory>, module_id: Option<ModuleId>) -> Self {
|
||||
ModuleState {
|
||||
|
@ -40,6 +40,10 @@ impl RuntimeType {
|
||||
RuntimeType::Primitive(PrimitiveType::Edge)
|
||||
}
|
||||
|
||||
pub fn function() -> Self {
|
||||
RuntimeType::Primitive(PrimitiveType::Function)
|
||||
}
|
||||
|
||||
pub fn sketch() -> Self {
|
||||
RuntimeType::Primitive(PrimitiveType::Sketch)
|
||||
}
|
||||
@ -84,6 +88,10 @@ impl RuntimeType {
|
||||
RuntimeType::Primitive(PrimitiveType::Tag)
|
||||
}
|
||||
|
||||
pub fn tag_decl() -> Self {
|
||||
RuntimeType::Primitive(PrimitiveType::TagDecl)
|
||||
}
|
||||
|
||||
pub fn tag_identifier() -> Self {
|
||||
RuntimeType::Primitive(PrimitiveType::TagId)
|
||||
}
|
||||
@ -376,8 +384,8 @@ pub enum PrimitiveType {
|
||||
String,
|
||||
Boolean,
|
||||
Tag,
|
||||
// Annoyingly some functions only want a TagIdentifier, not any kind of tag.
|
||||
TagId,
|
||||
TagDecl,
|
||||
Sketch,
|
||||
Solid,
|
||||
Plane,
|
||||
@ -409,6 +417,7 @@ impl PrimitiveType {
|
||||
PrimitiveType::ImportedGeometry => "imported geometries".to_owned(),
|
||||
PrimitiveType::Function => "functions".to_owned(),
|
||||
PrimitiveType::Tag => "tags".to_owned(),
|
||||
PrimitiveType::TagDecl => "tag declarators".to_owned(),
|
||||
PrimitiveType::TagId => "tag identifiers".to_owned(),
|
||||
}
|
||||
}
|
||||
@ -417,7 +426,7 @@ impl PrimitiveType {
|
||||
match (self, other) {
|
||||
(_, PrimitiveType::Any) => true,
|
||||
(PrimitiveType::Number(n1), PrimitiveType::Number(n2)) => n1.subtype(n2),
|
||||
(PrimitiveType::TagId, PrimitiveType::Tag) => true,
|
||||
(PrimitiveType::TagId, PrimitiveType::Tag) | (PrimitiveType::TagDecl, PrimitiveType::Tag) => true,
|
||||
(t1, t2) => t1 == t2,
|
||||
}
|
||||
}
|
||||
@ -434,6 +443,7 @@ impl fmt::Display for PrimitiveType {
|
||||
PrimitiveType::String => write!(f, "string"),
|
||||
PrimitiveType::Boolean => write!(f, "bool"),
|
||||
PrimitiveType::Tag => write!(f, "tag"),
|
||||
PrimitiveType::TagDecl => write!(f, "tag declarator"),
|
||||
PrimitiveType::TagId => write!(f, "tag identifier"),
|
||||
PrimitiveType::Sketch => write!(f, "Sketch"),
|
||||
PrimitiveType::Solid => write!(f, "Solid"),
|
||||
@ -1291,6 +1301,10 @@ impl KclValue {
|
||||
KclValue::TagIdentifier { .. } => Ok(self.clone()),
|
||||
_ => Err(self.into()),
|
||||
},
|
||||
PrimitiveType::TagDecl => match self {
|
||||
KclValue::TagDeclarator { .. } => Ok(self.clone()),
|
||||
_ => Err(self.into()),
|
||||
},
|
||||
PrimitiveType::Tag => match self {
|
||||
KclValue::TagDeclarator { .. } | KclValue::TagIdentifier { .. } | KclValue::Uuid { .. } => {
|
||||
Ok(self.clone())
|
||||
@ -1490,7 +1504,8 @@ impl KclValue {
|
||||
Some(RuntimeType::Array(Box::new(ty.clone()), ArrayLen::Known(value.len())))
|
||||
}
|
||||
KclValue::TagIdentifier(_) => Some(RuntimeType::Primitive(PrimitiveType::TagId)),
|
||||
KclValue::TagDeclarator(_) | KclValue::Uuid { .. } => Some(RuntimeType::Primitive(PrimitiveType::Tag)),
|
||||
KclValue::TagDeclarator(_) => Some(RuntimeType::Primitive(PrimitiveType::TagDecl)),
|
||||
KclValue::Uuid { .. } => Some(RuntimeType::Primitive(PrimitiveType::Tag)),
|
||||
KclValue::Function { .. } => Some(RuntimeType::Primitive(PrimitiveType::Function)),
|
||||
KclValue::Module { .. } | KclValue::KclNone { .. } | KclValue::Type { .. } => None,
|
||||
}
|
||||
|
@ -247,17 +247,6 @@ impl ObjectProperty {
|
||||
}
|
||||
}
|
||||
|
||||
impl MemberObject {
|
||||
fn get_hover_value_for_position(&self, pos: usize, code: &str, opts: &HoverOpts) -> Option<Hover> {
|
||||
match self {
|
||||
MemberObject::MemberExpression(member_expression) => {
|
||||
member_expression.get_hover_value_for_position(pos, code, opts)
|
||||
}
|
||||
MemberObject::Identifier(_identifier) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MemberExpression {
|
||||
fn get_hover_value_for_position(&self, pos: usize, code: &str, opts: &HoverOpts) -> Option<Hover> {
|
||||
let object_source_range: SourceRange = self.object.clone().into();
|
||||
|
@ -4,7 +4,7 @@ use crate::parsing::ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, AscribedExpression, BinaryExpression, BinaryPart, BodyItem,
|
||||
CallExpressionKw, DefaultParamVal, ElseIf, Expr, ExpressionStatement, FunctionExpression, FunctionType, Identifier,
|
||||
IfExpression, ImportItem, ImportSelector, ImportStatement, ItemVisibility, KclNone, LabelledExpression, Literal,
|
||||
LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, ObjectExpression, ObjectProperty, Parameter,
|
||||
LiteralIdentifier, LiteralValue, MemberExpression, Name, ObjectExpression, ObjectProperty, Parameter,
|
||||
PipeExpression, PipeSubstitution, PrimitiveType, Program, ReturnStatement, TagDeclarator, Type, TypeDeclaration,
|
||||
UnaryExpression, VariableDeclaration, VariableDeclarator, VariableKind,
|
||||
};
|
||||
@ -167,15 +167,6 @@ impl BinaryPart {
|
||||
}
|
||||
}
|
||||
|
||||
impl MemberObject {
|
||||
pub fn compute_digest(&mut self) -> Digest {
|
||||
match self {
|
||||
MemberObject::MemberExpression(me) => me.compute_digest(),
|
||||
MemberObject::Identifier(id) => id.compute_digest(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LiteralIdentifier {
|
||||
pub fn compute_digest(&mut self) -> Digest {
|
||||
match self {
|
||||
|
@ -2,7 +2,7 @@ pub(crate) mod digest;
|
||||
pub mod types;
|
||||
|
||||
use crate::{
|
||||
parsing::ast::types::{BinaryPart, BodyItem, Expr, LiteralIdentifier, MemberObject},
|
||||
parsing::ast::types::{BinaryPart, BodyItem, Expr, LiteralIdentifier},
|
||||
ModuleId,
|
||||
};
|
||||
|
||||
@ -57,15 +57,6 @@ impl BinaryPart {
|
||||
}
|
||||
}
|
||||
|
||||
impl MemberObject {
|
||||
pub fn module_id(&self) -> ModuleId {
|
||||
match self {
|
||||
MemberObject::MemberExpression(member_expression) => member_expression.module_id,
|
||||
MemberObject::Identifier(identifier) => identifier.module_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LiteralIdentifier {
|
||||
pub fn module_id(&self) -> ModuleId {
|
||||
match self {
|
||||
|
@ -2756,47 +2756,6 @@ impl ObjectProperty {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum MemberObject {
|
||||
MemberExpression(BoxNode<MemberExpression>),
|
||||
Identifier(BoxNode<Identifier>),
|
||||
}
|
||||
|
||||
impl MemberObject {
|
||||
pub fn start(&self) -> usize {
|
||||
match self {
|
||||
MemberObject::MemberExpression(member_expression) => member_expression.start,
|
||||
MemberObject::Identifier(identifier) => identifier.start,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end(&self) -> usize {
|
||||
match self {
|
||||
MemberObject::MemberExpression(member_expression) => member_expression.end,
|
||||
MemberObject::Identifier(identifier) => identifier.end,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn contains_range(&self, range: &SourceRange) -> bool {
|
||||
let sr = SourceRange::from(self);
|
||||
sr.contains_range(range)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MemberObject> for SourceRange {
|
||||
fn from(obj: MemberObject) -> Self {
|
||||
Self::new(obj.start(), obj.end(), obj.module_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&MemberObject> for SourceRange {
|
||||
fn from(obj: &MemberObject) -> Self {
|
||||
Self::new(obj.start(), obj.end(), obj.module_id())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
@ -2842,7 +2801,7 @@ impl From<&LiteralIdentifier> for SourceRange {
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
pub struct MemberExpression {
|
||||
pub object: MemberObject,
|
||||
pub object: Expr,
|
||||
pub property: LiteralIdentifier,
|
||||
pub computed: bool,
|
||||
|
||||
@ -2864,12 +2823,7 @@ impl Node<MemberExpression> {
|
||||
impl MemberExpression {
|
||||
/// Rename all identifiers that have the old name to the new given name.
|
||||
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
|
||||
match &mut self.object {
|
||||
MemberObject::MemberExpression(ref mut member_expression) => {
|
||||
member_expression.rename_identifiers(old_name, new_name)
|
||||
}
|
||||
MemberObject::Identifier(ref mut identifier) => identifier.rename(old_name, new_name),
|
||||
}
|
||||
self.object.rename_identifiers(old_name, new_name);
|
||||
|
||||
match &mut self.property {
|
||||
LiteralIdentifier::Identifier(ref mut identifier) => identifier.rename(old_name, new_name),
|
||||
|
@ -1,6 +1,6 @@
|
||||
use serde::Serialize;
|
||||
|
||||
use super::{BodyItem, Expr, MemberObject, Node, Program};
|
||||
use super::{BodyItem, Expr, Node, Program};
|
||||
use crate::SourceRange;
|
||||
|
||||
/// A traversal path through the AST to a node.
|
||||
@ -60,6 +60,20 @@ pub enum Step {
|
||||
}
|
||||
|
||||
impl NodePath {
|
||||
/// Placeholder for when the AST isn't available to create a real path. It
|
||||
/// will be filled in later.
|
||||
pub(crate) fn placeholder() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
#[cfg(feature = "artifact-graph")]
|
||||
pub(crate) fn fill_placeholder(&mut self, program: &Node<Program>, cached_body_items: usize, range: SourceRange) {
|
||||
if !self.is_empty() {
|
||||
return;
|
||||
}
|
||||
*self = Self::from_range(program, cached_body_items, range).unwrap_or_default();
|
||||
}
|
||||
|
||||
/// Given a program and a [`SourceRange`], return the path to the node that
|
||||
/// contains the range.
|
||||
pub(crate) fn from_range(program: &Node<Program>, cached_body_items: usize, range: SourceRange) -> Option<Self> {
|
||||
@ -248,7 +262,7 @@ impl NodePath {
|
||||
Expr::MemberExpression(node) => {
|
||||
if node.object.contains_range(&range) {
|
||||
path.push(Step::MemberExpressionObject);
|
||||
return Self::from_member_expr_object(&node.object, range, path);
|
||||
return NodePath::from_expr(&node.object, range, path);
|
||||
}
|
||||
if node.property.contains_range(&range) {
|
||||
path.push(Step::MemberExpressionProperty);
|
||||
@ -313,18 +327,6 @@ impl NodePath {
|
||||
Some(path)
|
||||
}
|
||||
|
||||
fn from_member_expr_object(mut expr: &MemberObject, range: SourceRange, mut path: NodePath) -> Option<NodePath> {
|
||||
while let MemberObject::MemberExpression(node) = expr {
|
||||
if !node.object.contains_range(&range) {
|
||||
break;
|
||||
}
|
||||
path.push(Step::MemberExpressionObject);
|
||||
expr = &node.object;
|
||||
}
|
||||
|
||||
Some(path)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.steps.is_empty()
|
||||
}
|
||||
@ -402,4 +404,19 @@ mod tests {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_path_from_range_import() {
|
||||
let code = r#"import "cube.step" as cube
|
||||
import "cylinder.kcl" as cylinder
|
||||
"#;
|
||||
let program = crate::Program::parse_no_errs(code).unwrap();
|
||||
// The entire cylinder import statement.
|
||||
assert_eq!(
|
||||
NodePath::from_range(&program.ast, 0, range(27, 60)).unwrap(),
|
||||
NodePath {
|
||||
steps: vec![Step::ProgramBodyItem { index: 1 }],
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ use crate::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
|
||||
BoxNode, CallExpressionKw, CommentStyle, DefaultParamVal, ElseIf, Expr, ExpressionStatement,
|
||||
FunctionExpression, FunctionType, Identifier, IfExpression, ImportItem, ImportSelector, ImportStatement,
|
||||
ItemVisibility, LabeledArg, Literal, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name,
|
||||
Node, NodeList, NonCodeMeta, NonCodeNode, NonCodeValue, ObjectExpression, ObjectProperty, Parameter,
|
||||
ItemVisibility, LabeledArg, Literal, LiteralIdentifier, LiteralValue, MemberExpression, Name, Node,
|
||||
NodeList, NonCodeMeta, NonCodeNode, NonCodeValue, ObjectExpression, ObjectProperty, Parameter,
|
||||
PipeExpression, PipeSubstitution, PrimitiveType, Program, ReturnStatement, Shebang, TagDeclarator, Type,
|
||||
TypeDeclaration, UnaryExpression, UnaryOperator, VariableDeclaration, VariableDeclarator, VariableKind,
|
||||
},
|
||||
@ -1326,10 +1326,7 @@ fn member_expression_subscript(i: &mut TokenSlice) -> ModalResult<(LiteralIdenti
|
||||
|
||||
/// Get a property of an object, or an index of an array, or a member of a collection.
|
||||
/// Can be arbitrarily nested, e.g. `people[i]['adam'].age`.
|
||||
fn member_expression(i: &mut TokenSlice) -> ModalResult<Node<MemberExpression>> {
|
||||
// This is an identifier, followed by a sequence of members (aka properties)
|
||||
// First, the identifier.
|
||||
let id = nameable_identifier.context(expected("the identifier of the object whose property you're trying to access, e.g. in 'shape.size.width', 'shape' is the identifier")).parse_next(i)?;
|
||||
fn build_member_expression(object: Expr, i: &mut TokenSlice) -> ModalResult<Node<MemberExpression>> {
|
||||
// Now a sequence of members.
|
||||
let member = alt((member_expression_dot, member_expression_subscript)).context(expected("a member/property, e.g. size.x and size['height'] and size[0] are all different ways to access a member/property of 'size'"));
|
||||
let mut members: Vec<_> = repeat(1.., member)
|
||||
@ -1340,11 +1337,11 @@ fn member_expression(i: &mut TokenSlice) -> ModalResult<Node<MemberExpression>>
|
||||
// It's safe to call remove(0), because the vec is created from repeat(1..),
|
||||
// which is guaranteed to have >=1 elements.
|
||||
let (property, end, computed) = members.remove(0);
|
||||
let start = id.start;
|
||||
let module_id = id.module_id;
|
||||
let start = object.start();
|
||||
let module_id = object.module_id();
|
||||
let initial_member_expression = Node::new(
|
||||
MemberExpression {
|
||||
object: MemberObject::Identifier(Box::new(id)),
|
||||
object,
|
||||
computed,
|
||||
property,
|
||||
digest: None,
|
||||
@ -1362,7 +1359,7 @@ fn member_expression(i: &mut TokenSlice) -> ModalResult<Node<MemberExpression>>
|
||||
.fold(initial_member_expression, |accumulated, (property, end, computed)| {
|
||||
Node::new(
|
||||
MemberExpression {
|
||||
object: MemberObject::MemberExpression(Box::new(accumulated)),
|
||||
object: Expr::MemberExpression(Box::new(accumulated)),
|
||||
computed,
|
||||
property,
|
||||
digest: None,
|
||||
@ -2085,8 +2082,7 @@ fn unnecessarily_bracketed(i: &mut TokenSlice) -> ModalResult<Expr> {
|
||||
}
|
||||
|
||||
fn expr_allowed_in_pipe_expr(i: &mut TokenSlice) -> ModalResult<Expr> {
|
||||
alt((
|
||||
member_expression.map(Box::new).map(Expr::MemberExpression),
|
||||
let parsed_expr = alt((
|
||||
bool_value.map(Box::new).map(Expr::Literal),
|
||||
tag.map(Box::new).map(Expr::TagDeclarator),
|
||||
literal.map(Expr::Literal),
|
||||
@ -2100,14 +2096,19 @@ fn expr_allowed_in_pipe_expr(i: &mut TokenSlice) -> ModalResult<Expr> {
|
||||
unnecessarily_bracketed,
|
||||
))
|
||||
.context(expected("a KCL expression (but not a pipe expression)"))
|
||||
.parse_next(i)
|
||||
.parse_next(i)?;
|
||||
|
||||
let maybe_member = build_member_expression(parsed_expr.clone(), i);
|
||||
if let Ok(mem) = maybe_member {
|
||||
return Ok(Expr::MemberExpression(Box::new(mem)));
|
||||
}
|
||||
Ok(parsed_expr)
|
||||
}
|
||||
|
||||
fn possible_operands(i: &mut TokenSlice) -> ModalResult<Expr> {
|
||||
let mut expr = alt((
|
||||
unary_expression.map(Box::new).map(Expr::UnaryExpression),
|
||||
bool_value.map(Box::new).map(Expr::Literal),
|
||||
member_expression.map(Box::new).map(Expr::MemberExpression),
|
||||
literal.map(Expr::Literal),
|
||||
fn_call_kw.map(Box::new).map(Expr::CallExpressionKw),
|
||||
name.map(Box::new).map(Expr::Name),
|
||||
@ -2118,6 +2119,10 @@ fn possible_operands(i: &mut TokenSlice) -> ModalResult<Expr> {
|
||||
"a KCL value which can be used as an argument/operand to an operator",
|
||||
))
|
||||
.parse_next(i)?;
|
||||
let maybe_member = build_member_expression(expr.clone(), i);
|
||||
if let Ok(mem) = maybe_member {
|
||||
expr = Expr::MemberExpression(Box::new(mem));
|
||||
}
|
||||
|
||||
let ty = opt((colon, opt(whitespace), type_)).parse_next(i)?;
|
||||
if let Some((_, _, ty)) = ty {
|
||||
@ -3258,7 +3263,7 @@ fn fn_call_kw(i: &mut TokenSlice) -> ModalResult<Node<CallExpressionKw>> {
|
||||
return Err(ErrMode::Cut(
|
||||
CompilationError::fatal(
|
||||
SourceRange::from(&tok),
|
||||
format!("There was an unexpected {}. Try removing it.", tok.value),
|
||||
format!("There was an unexpected `{}`. Try removing it.", tok.value),
|
||||
)
|
||||
.into(),
|
||||
));
|
||||
@ -4427,7 +4432,7 @@ z(-[["#,
|
||||
assert_err(
|
||||
r#"z
|
||||
(--#"#,
|
||||
"There was an unexpected -. Try removing it.",
|
||||
"There was an unexpected `-`. Try removing it.",
|
||||
[3, 4],
|
||||
);
|
||||
}
|
||||
@ -4997,6 +5002,17 @@ type foo = fn(fn, f: fn(number(_))): [fn([any]): string]
|
||||
assert_no_err(some_program_string);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_fn_call_then_field() {
|
||||
let some_program_string = "myFunction().field";
|
||||
let module_id = ModuleId::default();
|
||||
let tokens = crate::parsing::token::lex(some_program_string, module_id).unwrap(); // Updated import path
|
||||
let actual = expression.parse(tokens.as_slice()).unwrap();
|
||||
let Expr::MemberExpression(_expr) = actual else {
|
||||
panic!("expected member expression")
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_array_missing_closing_bracket() {
|
||||
let some_program_string = r#"
|
||||
@ -5185,7 +5201,7 @@ bar = 1
|
||||
.cause
|
||||
.as_ref()
|
||||
.expect("Found an error, but there was no cause. Add a cause.");
|
||||
assert_eq!(cause.message, "There was an unexpected }. Try removing it.",);
|
||||
assert_eq!(cause.message, "There was an unexpected `}`. Try removing it.",);
|
||||
assert_eq!(cause.source_range.start(), expected_src_start);
|
||||
}
|
||||
|
||||
|
@ -117,12 +117,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 45,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 40,
|
||||
"end": 43,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 40,
|
||||
"end": 43,
|
||||
"name": "obj",
|
||||
"start": 40,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 40,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 44,
|
||||
|
@ -117,12 +117,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 49,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 41,
|
||||
"end": 44,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 41,
|
||||
"end": 44,
|
||||
"name": "obj",
|
||||
"start": 41,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 41,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 45,
|
||||
|
@ -104,12 +104,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 44,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 36,
|
||||
"end": 39,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 36,
|
||||
"end": 39,
|
||||
"name": "obj",
|
||||
"start": 36,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 36,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 40,
|
||||
|
@ -120,12 +120,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 49,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 41,
|
||||
"end": 44,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 41,
|
||||
"end": 44,
|
||||
"name": "obj",
|
||||
"start": 41,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 41,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 45,
|
||||
|
@ -107,12 +107,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 45,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 37,
|
||||
"end": 40,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 37,
|
||||
"end": 40,
|
||||
"name": "obj",
|
||||
"start": 37,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 37,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 41,
|
||||
|
@ -107,12 +107,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 44,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 36,
|
||||
"end": 39,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 36,
|
||||
"end": 39,
|
||||
"name": "obj",
|
||||
"start": 36,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 36,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 40,
|
||||
|
@ -37,12 +37,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 18,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 13,
|
||||
"end": 16,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 13,
|
||||
"end": 16,
|
||||
"name": "obj",
|
||||
"start": 13,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 13,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 17,
|
||||
|
@ -24,12 +24,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 19,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 11,
|
||||
"end": 14,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 11,
|
||||
"end": 14,
|
||||
"name": "obj",
|
||||
"start": 11,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 11,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 15,
|
||||
|
@ -101,12 +101,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 44,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 36,
|
||||
"end": 39,
|
||||
"name": "obj",
|
||||
"name": {
|
||||
"commentStart": 36,
|
||||
"end": 39,
|
||||
"name": "obj",
|
||||
"start": 36,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 36,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 40,
|
||||
|
@ -25,12 +25,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 16,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 7,
|
||||
"end": 9,
|
||||
"name": "yo",
|
||||
"name": {
|
||||
"commentStart": 7,
|
||||
"end": 9,
|
||||
"name": "yo",
|
||||
"start": 7,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 7,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 10,
|
||||
|
@ -21,12 +21,20 @@ expression: actual
|
||||
"computed": true,
|
||||
"end": 11,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 8,
|
||||
"name": "b1",
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 8,
|
||||
"name": "b1",
|
||||
"start": 6,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 9,
|
||||
|
@ -33,12 +33,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 13,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 7,
|
||||
"end": 9,
|
||||
"name": "yo",
|
||||
"name": {
|
||||
"commentStart": 7,
|
||||
"end": 9,
|
||||
"name": "yo",
|
||||
"start": 7,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 7,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 10,
|
||||
|
@ -21,12 +21,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 11,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 8,
|
||||
"name": "b1",
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 8,
|
||||
"name": "b1",
|
||||
"start": 6,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 9,
|
||||
|
@ -21,12 +21,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 16,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 8,
|
||||
"name": "b1",
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 8,
|
||||
"name": "b1",
|
||||
"start": 6,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 9,
|
||||
|
@ -21,12 +21,20 @@ expression: actual
|
||||
"computed": false,
|
||||
"end": 13,
|
||||
"object": {
|
||||
"abs_path": false,
|
||||
"commentStart": 6,
|
||||
"end": 8,
|
||||
"name": "b1",
|
||||
"name": {
|
||||
"commentStart": 6,
|
||||
"end": 8,
|
||||
"name": "b1",
|
||||
"start": 6,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 6,
|
||||
"type": "Identifier",
|
||||
"type": "Identifier"
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"property": {
|
||||
"commentStart": 9,
|
||||
|
@ -94,6 +94,11 @@ impl SourceRange {
|
||||
ModuleId::from_usize(self.0[2])
|
||||
}
|
||||
|
||||
/// True if this source range is from the top-level module.
|
||||
pub fn is_top_level_module(&self) -> bool {
|
||||
self.module_id().is_top_level()
|
||||
}
|
||||
|
||||
/// Check if the range contains a position.
|
||||
pub fn contains(&self, pos: usize) -> bool {
|
||||
pos >= self.start() && pos <= self.end()
|
||||
|
@ -22,7 +22,7 @@ lazy_static::lazy_static! {
|
||||
|
||||
/// Construct a color from its red, blue and green components.
|
||||
pub async fn hex_string(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let rgb: [TyF64; 3] = args.get_unlabeled_kw_arg_typed(
|
||||
let rgb: [TyF64; 3] = args.get_unlabeled_kw_arg(
|
||||
"rgb",
|
||||
&RuntimeType::Array(Box::new(RuntimeType::count()), ArrayLen::Known(3)),
|
||||
exec_state,
|
||||
@ -50,15 +50,15 @@ async fn inner_hex_string(rgb: [TyF64; 3], _: &mut ExecState, args: Args) -> Res
|
||||
|
||||
/// Set the appearance of a solid. This only works on solids, not sketches or individual paths.
|
||||
pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids = args.get_unlabeled_kw_arg_typed(
|
||||
let solids = args.get_unlabeled_kw_arg(
|
||||
"solids",
|
||||
&RuntimeType::Union(vec![RuntimeType::solids(), RuntimeType::imported()]),
|
||||
exec_state,
|
||||
)?;
|
||||
|
||||
let color: String = args.get_kw_arg_typed("color", &RuntimeType::string(), exec_state)?;
|
||||
let metalness: Option<TyF64> = args.get_kw_arg_opt_typed("metalness", &RuntimeType::count(), exec_state)?;
|
||||
let roughness: Option<TyF64> = args.get_kw_arg_opt_typed("roughness", &RuntimeType::count(), exec_state)?;
|
||||
let color: String = args.get_kw_arg("color", &RuntimeType::string(), exec_state)?;
|
||||
let metalness: Option<TyF64> = args.get_kw_arg_opt("metalness", &RuntimeType::count(), exec_state)?;
|
||||
let roughness: Option<TyF64> = args.get_kw_arg_opt("roughness", &RuntimeType::count(), exec_state)?;
|
||||
|
||||
// Make sure the color if set is valid.
|
||||
if !HEX_REGEX.is_match(&color) {
|
||||
|
@ -109,32 +109,7 @@ impl JsonSchema for TyF64 {
|
||||
}
|
||||
|
||||
impl Args {
|
||||
/// Get a keyword argument. If not set, returns None.
|
||||
pub(crate) fn get_kw_arg_opt<'a, T>(&'a self, label: &str) -> Result<Option<T>, KclError>
|
||||
where
|
||||
T: FromKclValue<'a>,
|
||||
{
|
||||
let Some(arg) = self.kw_args.labeled.get(label) else {
|
||||
return Ok(None);
|
||||
};
|
||||
if let KclValue::KclNone { .. } = arg.value {
|
||||
// It is set, but it's an optional parameter that wasn't provided.
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
T::from_kcl_val(&arg.value).map(Some).ok_or_else(|| {
|
||||
KclError::new_type(KclErrorDetails::new(
|
||||
format!(
|
||||
"The arg {label} was given, but it was the wrong type. It should be type {} but it was {}",
|
||||
tynm::type_name::<T>(),
|
||||
arg.value.human_friendly_type(),
|
||||
),
|
||||
vec![self.source_range],
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_kw_arg_opt_typed<T>(
|
||||
pub(crate) fn get_kw_arg_opt<T>(
|
||||
&self,
|
||||
label: &str,
|
||||
ty: &RuntimeType,
|
||||
@ -152,28 +127,10 @@ impl Args {
|
||||
}
|
||||
}
|
||||
|
||||
self.get_kw_arg_typed(label, ty, exec_state).map(Some)
|
||||
self.get_kw_arg(label, ty, exec_state).map(Some)
|
||||
}
|
||||
|
||||
/// Get a keyword argument. If not set, returns Err.
|
||||
pub(crate) fn get_kw_arg<'a, T>(&'a self, label: &str) -> Result<T, KclError>
|
||||
where
|
||||
T: FromKclValue<'a>,
|
||||
{
|
||||
self.get_kw_arg_opt(label)?.ok_or_else(|| {
|
||||
KclError::new_semantic(KclErrorDetails::new(
|
||||
format!("This function requires a keyword argument '{label}'"),
|
||||
vec![self.source_range],
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_kw_arg_typed<T>(
|
||||
&self,
|
||||
label: &str,
|
||||
ty: &RuntimeType,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<T, KclError>
|
||||
pub(crate) fn get_kw_arg<T>(&self, label: &str, ty: &RuntimeType, exec_state: &mut ExecState) -> Result<T, KclError>
|
||||
where
|
||||
T: for<'a> FromKclValue<'a>,
|
||||
{
|
||||
@ -254,7 +211,7 @@ impl Args {
|
||||
label: &str,
|
||||
exec_state: &mut ExecState,
|
||||
) -> Result<(Vec<KclValue>, RuntimeType), KclError> {
|
||||
let value = self.get_unlabeled_kw_arg_typed(label, &RuntimeType::any_array(), exec_state)?;
|
||||
let value = self.get_unlabeled_kw_arg(label, &RuntimeType::any_array(), exec_state)?;
|
||||
Ok(match value {
|
||||
KclValue::HomArray { value, ty } => (value, ty),
|
||||
KclValue::Tuple { value, .. } => (value, RuntimeType::any()),
|
||||
@ -264,7 +221,7 @@ impl Args {
|
||||
|
||||
/// Get the unlabeled keyword argument. If not set, returns Err. If it
|
||||
/// can't be converted to the given type, returns Err.
|
||||
pub(crate) fn get_unlabeled_kw_arg_typed<T>(
|
||||
pub(crate) fn get_unlabeled_kw_arg<T>(
|
||||
&self,
|
||||
label: &str,
|
||||
ty: &RuntimeType,
|
||||
@ -1393,9 +1350,9 @@ impl<'a> FromKclValue<'a> for Box<Solid> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for &'a FunctionSource {
|
||||
impl<'a> FromKclValue<'a> for FunctionSource {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
arg.as_function()
|
||||
arg.as_function().cloned()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,8 @@ use crate::{
|
||||
|
||||
/// Apply a function to each element of an array.
|
||||
pub async fn map(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let array: Vec<KclValue> = args.get_unlabeled_kw_arg_typed("array", &RuntimeType::any_array(), exec_state)?;
|
||||
let f: &FunctionSource = args.get_kw_arg("f")?;
|
||||
let array: Vec<KclValue> = args.get_unlabeled_kw_arg("array", &RuntimeType::any_array(), exec_state)?;
|
||||
let f: FunctionSource = args.get_kw_arg("f", &RuntimeType::function(), exec_state)?;
|
||||
let new_array = inner_map(array, f, exec_state, &args).await?;
|
||||
Ok(KclValue::HomArray {
|
||||
value: new_array,
|
||||
@ -23,15 +23,15 @@ pub async fn map(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
|
||||
})
|
||||
}
|
||||
|
||||
async fn inner_map<'a>(
|
||||
async fn inner_map(
|
||||
array: Vec<KclValue>,
|
||||
f: &'a FunctionSource,
|
||||
f: FunctionSource,
|
||||
exec_state: &mut ExecState,
|
||||
args: &'a Args,
|
||||
args: &Args,
|
||||
) -> Result<Vec<KclValue>, KclError> {
|
||||
let mut new_array = Vec::with_capacity(array.len());
|
||||
for elem in array {
|
||||
let new_elem = call_map_closure(elem, f, args.source_range, exec_state, &args.ctx).await?;
|
||||
let new_elem = call_map_closure(elem, &f, args.source_range, exec_state, &args.ctx).await?;
|
||||
new_array.push(new_elem);
|
||||
}
|
||||
Ok(new_array)
|
||||
@ -68,22 +68,22 @@ async fn call_map_closure(
|
||||
|
||||
/// For each item in an array, update a value.
|
||||
pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let array: Vec<KclValue> = args.get_unlabeled_kw_arg_typed("array", &RuntimeType::any_array(), exec_state)?;
|
||||
let f: &FunctionSource = args.get_kw_arg("f")?;
|
||||
let initial: KclValue = args.get_kw_arg_typed("initial", &RuntimeType::any(), exec_state)?;
|
||||
let array: Vec<KclValue> = args.get_unlabeled_kw_arg("array", &RuntimeType::any_array(), exec_state)?;
|
||||
let f: FunctionSource = args.get_kw_arg("f", &RuntimeType::function(), exec_state)?;
|
||||
let initial: KclValue = args.get_kw_arg("initial", &RuntimeType::any(), exec_state)?;
|
||||
inner_reduce(array, initial, f, exec_state, &args).await
|
||||
}
|
||||
|
||||
async fn inner_reduce<'a>(
|
||||
async fn inner_reduce(
|
||||
array: Vec<KclValue>,
|
||||
initial: KclValue,
|
||||
f: &'a FunctionSource,
|
||||
f: FunctionSource,
|
||||
exec_state: &mut ExecState,
|
||||
args: &'a Args,
|
||||
args: &Args,
|
||||
) -> Result<KclValue, KclError> {
|
||||
let mut reduced = initial;
|
||||
for elem in array {
|
||||
reduced = call_reduce_closure(elem, reduced, f, args.source_range, exec_state, &args.ctx).await?;
|
||||
reduced = call_reduce_closure(elem, reduced, &f, args.source_range, exec_state, &args.ctx).await?;
|
||||
}
|
||||
|
||||
Ok(reduced)
|
||||
@ -128,7 +128,7 @@ async fn call_reduce_closure(
|
||||
|
||||
pub async fn push(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (mut array, ty) = args.get_unlabeled_kw_arg_array_and_type("array", exec_state)?;
|
||||
let item: KclValue = args.get_kw_arg_typed("item", &RuntimeType::any(), exec_state)?;
|
||||
let item: KclValue = args.get_kw_arg("item", &RuntimeType::any(), exec_state)?;
|
||||
|
||||
array.push(item);
|
||||
|
||||
|
@ -20,8 +20,8 @@ async fn _assert(value: bool, message: &str, args: &Args) -> Result<(), KclError
|
||||
}
|
||||
|
||||
pub async fn assert_is(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let actual = args.get_unlabeled_kw_arg_typed("actual", &RuntimeType::bool(), exec_state)?;
|
||||
let error = args.get_kw_arg_opt_typed("error", &RuntimeType::string(), exec_state)?;
|
||||
let actual = args.get_unlabeled_kw_arg("actual", &RuntimeType::bool(), exec_state)?;
|
||||
let error = args.get_kw_arg_opt("error", &RuntimeType::string(), exec_state)?;
|
||||
inner_assert_is(actual, error, &args).await?;
|
||||
Ok(KclValue::none())
|
||||
}
|
||||
@ -29,14 +29,14 @@ pub async fn assert_is(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
/// Check that the provided value is true, or raise a [KclError]
|
||||
/// with the provided description.
|
||||
pub async fn assert(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let actual = args.get_unlabeled_kw_arg_typed("actual", &RuntimeType::num_any(), exec_state)?;
|
||||
let gt = args.get_kw_arg_opt_typed("isGreaterThan", &RuntimeType::num_any(), exec_state)?;
|
||||
let lt = args.get_kw_arg_opt_typed("isLessThan", &RuntimeType::num_any(), exec_state)?;
|
||||
let gte = args.get_kw_arg_opt_typed("isGreaterThanOrEqual", &RuntimeType::num_any(), exec_state)?;
|
||||
let lte = args.get_kw_arg_opt_typed("isLessThanOrEqual", &RuntimeType::num_any(), exec_state)?;
|
||||
let eq = args.get_kw_arg_opt_typed("isEqualTo", &RuntimeType::num_any(), exec_state)?;
|
||||
let tolerance = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::num_any(), exec_state)?;
|
||||
let error = args.get_kw_arg_opt_typed("error", &RuntimeType::string(), exec_state)?;
|
||||
let actual = args.get_unlabeled_kw_arg("actual", &RuntimeType::num_any(), exec_state)?;
|
||||
let gt = args.get_kw_arg_opt("isGreaterThan", &RuntimeType::num_any(), exec_state)?;
|
||||
let lt = args.get_kw_arg_opt("isLessThan", &RuntimeType::num_any(), exec_state)?;
|
||||
let gte = args.get_kw_arg_opt("isGreaterThanOrEqual", &RuntimeType::num_any(), exec_state)?;
|
||||
let lte = args.get_kw_arg_opt("isLessThanOrEqual", &RuntimeType::num_any(), exec_state)?;
|
||||
let eq = args.get_kw_arg_opt("isEqualTo", &RuntimeType::num_any(), exec_state)?;
|
||||
let tolerance = args.get_kw_arg_opt("tolerance", &RuntimeType::num_any(), exec_state)?;
|
||||
let error = args.get_kw_arg_opt("error", &RuntimeType::string(), exec_state)?;
|
||||
inner_assert(actual, gt, lt, gte, lte, eq, tolerance, error, &args).await?;
|
||||
Ok(KclValue::none())
|
||||
}
|
||||
|
@ -7,10 +7,7 @@ use kittycad_modeling_cmds as kcmc;
|
||||
use super::args::TyF64;
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{
|
||||
types::{PrimitiveType, RuntimeType},
|
||||
ChamferSurface, EdgeCut, ExecState, ExtrudeSurface, GeoMeta, KclValue, Solid,
|
||||
},
|
||||
execution::{types::RuntimeType, ChamferSurface, EdgeCut, ExecState, ExtrudeSurface, GeoMeta, KclValue, Solid},
|
||||
parsing::ast::types::TagNode,
|
||||
std::{fillet::EdgeReference, Args},
|
||||
};
|
||||
@ -19,10 +16,10 @@ pub(crate) const DEFAULT_TOLERANCE: f64 = 0.0000001;
|
||||
|
||||
/// Create chamfers on tagged paths.
|
||||
pub async fn chamfer(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solid = args.get_unlabeled_kw_arg_typed("solid", &RuntimeType::Primitive(PrimitiveType::Solid), exec_state)?;
|
||||
let length: TyF64 = args.get_kw_arg_typed("length", &RuntimeType::length(), exec_state)?;
|
||||
let solid = args.get_unlabeled_kw_arg("solid", &RuntimeType::solid(), exec_state)?;
|
||||
let length: TyF64 = args.get_kw_arg("length", &RuntimeType::length(), exec_state)?;
|
||||
let tags = args.kw_arg_edge_array_and_source("tags")?;
|
||||
let tag = args.get_kw_arg_opt("tag")?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
super::fillet::validate_unique(&tags)?;
|
||||
let tags: Vec<EdgeReference> = tags.into_iter().map(|item| item.0).collect();
|
||||
|
@ -26,7 +26,7 @@ use crate::{
|
||||
///
|
||||
/// This works essentially like a copy-paste operation.
|
||||
pub async fn clone(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let geometry = args.get_unlabeled_kw_arg_typed(
|
||||
let geometry = args.get_unlabeled_kw_arg(
|
||||
"geometry",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Sketch),
|
||||
|
@ -19,8 +19,8 @@ use crate::{
|
||||
/// Union two or more solids into a single solid.
|
||||
pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids: Vec<Solid> =
|
||||
args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::Union(vec![RuntimeType::solids()]), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
args.get_unlabeled_kw_arg("solids", &RuntimeType::Union(vec![RuntimeType::solids()]), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
|
||||
if solids.len() < 2 {
|
||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||
@ -84,8 +84,8 @@ pub(crate) async fn inner_union(
|
||||
/// Intersect returns the shared volume between multiple solids, preserving only
|
||||
/// overlapping regions.
|
||||
pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids: Vec<Solid> = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let solids: Vec<Solid> = args.get_unlabeled_kw_arg("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
|
||||
if solids.len() < 2 {
|
||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||
@ -148,10 +148,10 @@ pub(crate) async fn inner_intersect(
|
||||
|
||||
/// Subtract removes tool solids from base solids, leaving the remaining material.
|
||||
pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids: Vec<Solid> = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let tools: Vec<Solid> = args.get_kw_arg_typed("tools", &RuntimeType::solids(), exec_state)?;
|
||||
let solids: Vec<Solid> = args.get_unlabeled_kw_arg("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let tools: Vec<Solid> = args.get_kw_arg("tools", &RuntimeType::solids(), exec_state)?;
|
||||
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
|
||||
let solids = inner_subtract(solids, tools, tolerance, exec_state, args).await?;
|
||||
Ok(solids.into())
|
||||
|
@ -16,7 +16,7 @@ use crate::{
|
||||
|
||||
/// Get the opposite edge to the edge given.
|
||||
pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let input_edge = args.get_unlabeled_kw_arg("edge", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
|
||||
let edge = inner_get_opposite_edge(input_edge, exec_state, args.clone()).await?;
|
||||
Ok(KclValue::Uuid {
|
||||
@ -63,7 +63,7 @@ async fn inner_get_opposite_edge(
|
||||
|
||||
/// Get the next adjacent edge to the edge given.
|
||||
pub async fn get_next_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let input_edge = args.get_unlabeled_kw_arg("edge", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
|
||||
let edge = inner_get_next_adjacent_edge(input_edge, exec_state, args.clone()).await?;
|
||||
Ok(KclValue::Uuid {
|
||||
@ -119,7 +119,7 @@ async fn inner_get_next_adjacent_edge(
|
||||
|
||||
/// Get the previous adjacent edge to the edge given.
|
||||
pub async fn get_previous_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let input_edge = args.get_unlabeled_kw_arg("edge", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
|
||||
let edge = inner_get_previous_adjacent_edge(input_edge, exec_state, args.clone()).await?;
|
||||
Ok(KclValue::Uuid {
|
||||
@ -174,7 +174,7 @@ async fn inner_get_previous_adjacent_edge(
|
||||
|
||||
/// Get the shared edge between two faces.
|
||||
pub async fn get_common_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let faces: Vec<TagIdentifier> = args.get_kw_arg_typed(
|
||||
let faces: Vec<TagIdentifier> = args.get_kw_arg(
|
||||
"faces",
|
||||
&RuntimeType::Array(Box::new(RuntimeType::tag_identifier()), ArrayLen::Known(2)),
|
||||
exec_state,
|
||||
|
@ -28,13 +28,13 @@ use crate::{
|
||||
|
||||
/// Extrudes by a given amount.
|
||||
pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let length: TyF64 = args.get_kw_arg_typed("length", &RuntimeType::length(), exec_state)?;
|
||||
let symmetric = args.get_kw_arg_opt_typed("symmetric", &RuntimeType::bool(), exec_state)?;
|
||||
let sketches = args.get_unlabeled_kw_arg("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let length: TyF64 = args.get_kw_arg("length", &RuntimeType::length(), exec_state)?;
|
||||
let symmetric = args.get_kw_arg_opt("symmetric", &RuntimeType::bool(), exec_state)?;
|
||||
let bidirectional_length: Option<TyF64> =
|
||||
args.get_kw_arg_opt_typed("bidirectionalLength", &RuntimeType::length(), exec_state)?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd")?;
|
||||
args.get_kw_arg_opt("bidirectionalLength", &RuntimeType::length(), exec_state)?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let result = inner_extrude(
|
||||
sketches,
|
||||
|
@ -60,11 +60,11 @@ pub(super) fn validate_unique<T: Eq + std::hash::Hash>(tags: &[(T, SourceRange)]
|
||||
|
||||
/// Create fillets on tagged paths.
|
||||
pub async fn fillet(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solid = args.get_unlabeled_kw_arg_typed("solid", &RuntimeType::solid(), exec_state)?;
|
||||
let radius: TyF64 = args.get_kw_arg_typed("radius", &RuntimeType::length(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let solid = args.get_unlabeled_kw_arg("solid", &RuntimeType::solid(), exec_state)?;
|
||||
let radius: TyF64 = args.get_kw_arg("radius", &RuntimeType::length(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let tags = args.kw_arg_edge_array_and_source("tags")?;
|
||||
let tag = args.get_kw_arg_opt("tag")?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
// Run the function.
|
||||
validate_unique(&tags)?;
|
||||
|
@ -16,11 +16,11 @@ use crate::{
|
||||
|
||||
/// 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::degrees(), exec_state)?;
|
||||
let revolutions: TyF64 = args.get_kw_arg_typed("revolutions", &RuntimeType::count(), exec_state)?;
|
||||
let ccw = args.get_kw_arg_opt_typed("ccw", &RuntimeType::bool(), exec_state)?;
|
||||
let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?;
|
||||
let axis: Option<Axis3dOrEdgeReference> = args.get_kw_arg_opt_typed(
|
||||
let angle_start: TyF64 = args.get_kw_arg("angleStart", &RuntimeType::degrees(), exec_state)?;
|
||||
let revolutions: TyF64 = args.get_kw_arg("revolutions", &RuntimeType::count(), exec_state)?;
|
||||
let ccw = args.get_kw_arg_opt("ccw", &RuntimeType::bool(), exec_state)?;
|
||||
let radius: Option<TyF64> = args.get_kw_arg_opt("radius", &RuntimeType::length(), exec_state)?;
|
||||
let axis: Option<Axis3dOrEdgeReference> = args.get_kw_arg_opt(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Edge),
|
||||
@ -28,8 +28,8 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
]),
|
||||
exec_state,
|
||||
)?;
|
||||
let length: Option<TyF64> = args.get_kw_arg_opt_typed("length", &RuntimeType::length(), exec_state)?;
|
||||
let cylinder = args.get_kw_arg_opt_typed("cylinder", &RuntimeType::solid(), exec_state)?;
|
||||
let length: Option<TyF64> = args.get_kw_arg_opt("length", &RuntimeType::length(), exec_state)?;
|
||||
let cylinder = args.get_kw_arg_opt("cylinder", &RuntimeType::solid(), exec_state)?;
|
||||
|
||||
// Make sure we have a radius if we don't have a cylinder.
|
||||
if radius.is_none() && cylinder.is_none() {
|
||||
|
@ -21,23 +21,22 @@ const DEFAULT_V_DEGREE: u32 = 2;
|
||||
|
||||
/// Create a 3D surface or solid by interpolating between two or more sketches.
|
||||
pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let sketches = args.get_unlabeled_kw_arg("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let v_degree: NonZeroU32 = args
|
||||
.get_kw_arg_opt_typed("vDegree", &RuntimeType::count(), exec_state)?
|
||||
.get_kw_arg_opt("vDegree", &RuntimeType::count(), exec_state)?
|
||||
.unwrap_or(NonZeroU32::new(DEFAULT_V_DEGREE).unwrap());
|
||||
// Attempt to approximate rational curves (such as arcs) using a bezier.
|
||||
// This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios
|
||||
// Over time, this field won't be necessary.
|
||||
let bez_approximate_rational = args
|
||||
.get_kw_arg_opt_typed("bezApproximateRational", &RuntimeType::bool(), exec_state)?
|
||||
.get_kw_arg_opt("bezApproximateRational", &RuntimeType::bool(), exec_state)?
|
||||
.unwrap_or(false);
|
||||
// This can be set to override the automatically determined topological base curve, which is usually the first section encountered.
|
||||
let base_curve_index: Option<u32> =
|
||||
args.get_kw_arg_opt_typed("baseCurveIndex", &RuntimeType::count(), exec_state)?;
|
||||
let base_curve_index: Option<u32> = args.get_kw_arg_opt("baseCurveIndex", &RuntimeType::count(), exec_state)?;
|
||||
// Tolerance for the loft operation.
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd")?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let value = inner_loft(
|
||||
sketches,
|
||||
|
@ -15,8 +15,8 @@ use crate::{
|
||||
/// Compute the remainder after dividing `num` by `div`.
|
||||
/// If `num` is negative, the result will be too.
|
||||
pub async fn rem(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let n: TyF64 = args.get_unlabeled_kw_arg_typed("number to divide", &RuntimeType::num_any(), exec_state)?;
|
||||
let d: TyF64 = args.get_kw_arg_typed("divisor", &RuntimeType::num_any(), exec_state)?;
|
||||
let n: TyF64 = args.get_unlabeled_kw_arg("number to divide", &RuntimeType::num_any(), exec_state)?;
|
||||
let d: TyF64 = args.get_kw_arg("divisor", &RuntimeType::num_any(), exec_state)?;
|
||||
|
||||
let (n, d, ty) = NumericType::combine_div(n, d);
|
||||
if ty == NumericType::Unknown {
|
||||
@ -32,28 +32,28 @@ pub async fn rem(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
|
||||
|
||||
/// 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::angle(), exec_state)?;
|
||||
let num: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::angle(), exec_state)?;
|
||||
let num = num.to_radians();
|
||||
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::angle(), exec_state)?;
|
||||
let num: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::angle(), exec_state)?;
|
||||
let num = num.to_radians();
|
||||
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::angle(), exec_state)?;
|
||||
let num: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::angle(), exec_state)?;
|
||||
let num = num.to_radians();
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::count(num.tan())))
|
||||
}
|
||||
|
||||
/// Compute the square root of a number.
|
||||
pub async fn sqrt(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
|
||||
if input.n < 0.0 {
|
||||
return Err(KclError::new_semantic(KclErrorDetails::new(
|
||||
@ -72,7 +72,7 @@ pub async fn sqrt(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
|
||||
/// Compute the absolute value of a number.
|
||||
pub async fn abs(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let result = input.n.abs();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
|
||||
@ -80,7 +80,7 @@ pub async fn abs(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
|
||||
|
||||
/// Round a number to the nearest integer.
|
||||
pub async fn round(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let result = input.n.round();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
|
||||
@ -88,7 +88,7 @@ pub async fn round(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
|
||||
/// Compute the largest integer less than or equal to a number.
|
||||
pub async fn floor(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let result = input.n.floor();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
|
||||
@ -96,7 +96,7 @@ pub async fn floor(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
|
||||
/// Compute the smallest integer greater than or equal to a number.
|
||||
pub async fn ceil(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let result = input.n.ceil();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
|
||||
@ -104,7 +104,7 @@ pub async fn ceil(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
|
||||
/// Compute the minimum of the given arguments.
|
||||
pub async fn min(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let nums: Vec<TyF64> = args.get_unlabeled_kw_arg_typed(
|
||||
let nums: Vec<TyF64> = args.get_unlabeled_kw_arg(
|
||||
"input",
|
||||
&RuntimeType::Array(Box::new(RuntimeType::num_any()), ArrayLen::Minimum(1)),
|
||||
exec_state,
|
||||
@ -129,7 +129,7 @@ pub async fn min(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
|
||||
|
||||
/// Compute the maximum of the given arguments.
|
||||
pub async fn max(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let nums: Vec<TyF64> = args.get_unlabeled_kw_arg_typed(
|
||||
let nums: Vec<TyF64> = args.get_unlabeled_kw_arg(
|
||||
"input",
|
||||
&RuntimeType::Array(Box::new(RuntimeType::num_any()), ArrayLen::Minimum(1)),
|
||||
exec_state,
|
||||
@ -154,8 +154,8 @@ pub async fn max(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
|
||||
|
||||
/// Compute the number to a power.
|
||||
pub async fn pow(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let exp: TyF64 = args.get_kw_arg_typed("exp", &RuntimeType::count(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let exp: TyF64 = args.get_kw_arg("exp", &RuntimeType::count(), exec_state)?;
|
||||
let result = input.n.powf(exp.n);
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
|
||||
@ -163,7 +163,7 @@ pub async fn pow(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
|
||||
|
||||
/// Compute the arccosine of a number (in radians).
|
||||
pub async fn acos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::count(), exec_state)?;
|
||||
let result = input.n.acos();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
|
||||
@ -171,7 +171,7 @@ pub async fn acos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
|
||||
/// Compute the arcsine of a number (in radians).
|
||||
pub async fn asin(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::count(), exec_state)?;
|
||||
let result = input.n.asin();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
|
||||
@ -179,7 +179,7 @@ pub async fn asin(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
|
||||
/// Compute the arctangent of a number (in radians).
|
||||
pub async fn atan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::count(), exec_state)?;
|
||||
let result = input.n.atan();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
|
||||
@ -187,8 +187,8 @@ pub async fn atan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
|
||||
/// Compute the four quadrant arctangent of Y and X (in radians).
|
||||
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 = args.get_kw_arg("y", &RuntimeType::length(), exec_state)?;
|
||||
let x = args.get_kw_arg("x", &RuntimeType::length(), exec_state)?;
|
||||
let (y, x, _) = NumericType::combine_eq_coerce(y, x);
|
||||
let result = y.atan2(x);
|
||||
|
||||
@ -201,8 +201,8 @@ pub async fn atan2(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// details; `log2()` can produce more accurate results for base 2,
|
||||
/// and `log10()` can produce more accurate results for base 10.
|
||||
pub async fn log(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let base: TyF64 = args.get_kw_arg_typed("base", &RuntimeType::count(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let base: TyF64 = args.get_kw_arg("base", &RuntimeType::count(), exec_state)?;
|
||||
let result = input.n.log(base.n);
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
|
||||
@ -210,7 +210,7 @@ pub async fn log(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
|
||||
|
||||
/// Compute the base 2 logarithm of the number.
|
||||
pub async fn log2(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let result = input.n.log2();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
|
||||
@ -218,7 +218,7 @@ pub async fn log2(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
|
||||
|
||||
/// Compute the base 10 logarithm of the number.
|
||||
pub async fn log10(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let result = input.n.log10();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
|
||||
@ -226,7 +226,7 @@ pub async fn log10(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
|
||||
/// Compute the natural logarithm of the number.
|
||||
pub async fn ln(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let input: TyF64 = args.get_unlabeled_kw_arg("input", &RuntimeType::num_any(), exec_state)?;
|
||||
let result = input.n.ln();
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
|
||||
@ -234,8 +234,8 @@ pub async fn ln(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclE
|
||||
|
||||
/// Compute the length of the given leg.
|
||||
pub async fn leg_length(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let hypotenuse: TyF64 = args.get_kw_arg_typed("hypotenuse", &RuntimeType::length(), exec_state)?;
|
||||
let leg: TyF64 = args.get_kw_arg_typed("leg", &RuntimeType::length(), exec_state)?;
|
||||
let hypotenuse: TyF64 = args.get_kw_arg("hypotenuse", &RuntimeType::length(), exec_state)?;
|
||||
let leg: TyF64 = args.get_kw_arg("leg", &RuntimeType::length(), exec_state)?;
|
||||
let (hypotenuse, leg, ty) = NumericType::combine_eq_coerce(hypotenuse, leg);
|
||||
let result = (hypotenuse.powi(2) - f64::min(hypotenuse.abs(), leg.abs()).powi(2)).sqrt();
|
||||
Ok(KclValue::from_number_with_type(result, ty, vec![args.into()]))
|
||||
@ -243,8 +243,8 @@ pub async fn leg_length(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
|
||||
/// Compute the angle of the given leg for x.
|
||||
pub async fn leg_angle_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let hypotenuse: TyF64 = args.get_kw_arg_typed("hypotenuse", &RuntimeType::length(), exec_state)?;
|
||||
let leg: TyF64 = args.get_kw_arg_typed("leg", &RuntimeType::length(), exec_state)?;
|
||||
let hypotenuse: TyF64 = args.get_kw_arg("hypotenuse", &RuntimeType::length(), exec_state)?;
|
||||
let leg: TyF64 = args.get_kw_arg("leg", &RuntimeType::length(), exec_state)?;
|
||||
let (hypotenuse, leg, _ty) = NumericType::combine_eq_coerce(hypotenuse, leg);
|
||||
let result = (leg.min(hypotenuse) / hypotenuse).acos().to_degrees();
|
||||
Ok(KclValue::from_number_with_type(
|
||||
@ -256,8 +256,8 @@ pub async fn leg_angle_x(exec_state: &mut ExecState, args: Args) -> Result<KclVa
|
||||
|
||||
/// Compute the angle of the given leg for y.
|
||||
pub async fn leg_angle_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let hypotenuse: TyF64 = args.get_kw_arg_typed("hypotenuse", &RuntimeType::length(), exec_state)?;
|
||||
let leg: TyF64 = args.get_kw_arg_typed("leg", &RuntimeType::length(), exec_state)?;
|
||||
let hypotenuse: TyF64 = args.get_kw_arg("hypotenuse", &RuntimeType::length(), exec_state)?;
|
||||
let leg: TyF64 = args.get_kw_arg("leg", &RuntimeType::length(), exec_state)?;
|
||||
let (hypotenuse, leg, _ty) = NumericType::combine_eq_coerce(hypotenuse, leg);
|
||||
let result = (leg.min(hypotenuse) / hypotenuse).asin().to_degrees();
|
||||
Ok(KclValue::from_number_with_type(
|
||||
|
@ -18,8 +18,8 @@ use crate::{
|
||||
|
||||
/// Mirror a sketch.
|
||||
pub async fn mirror_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let axis = args.get_kw_arg_typed(
|
||||
let sketches = args.get_unlabeled_kw_arg("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let axis = args.get_kw_arg(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Edge),
|
||||
|
@ -170,7 +170,7 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|
||||
),
|
||||
("transform", "mirror2d") => (
|
||||
|e, a| Box::pin(crate::std::mirror::mirror_2d(e, a)),
|
||||
StdFnProps::default("std::transform::mirror2d"),
|
||||
StdFnProps::default("std::transform::mirror2d").include_in_feature_tree(),
|
||||
),
|
||||
("transform", "translate") => (
|
||||
|e, a| Box::pin(crate::std::transform::translate(e, a)),
|
||||
@ -406,47 +406,47 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
|
||||
),
|
||||
("sketch", "involuteCircular") => (
|
||||
|e, a| Box::pin(crate::std::sketch::involute_circular(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::involuteCircular"),
|
||||
),
|
||||
("sketch", "line") => (
|
||||
|e, a| Box::pin(crate::std::sketch::line(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::line"),
|
||||
),
|
||||
("sketch", "xLine") => (
|
||||
|e, a| Box::pin(crate::std::sketch::x_line(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::xLine"),
|
||||
),
|
||||
("sketch", "yLine") => (
|
||||
|e, a| Box::pin(crate::std::sketch::y_line(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::yLine"),
|
||||
),
|
||||
("sketch", "angledLine") => (
|
||||
|e, a| Box::pin(crate::std::sketch::angled_line(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::angledLine"),
|
||||
),
|
||||
("sketch", "angledLineThatIntersects") => (
|
||||
|e, a| Box::pin(crate::std::sketch::angled_line_that_intersects(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::angledLineThatIntersects"),
|
||||
),
|
||||
("sketch", "close") => (
|
||||
|e, a| Box::pin(crate::std::sketch::close(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::close"),
|
||||
),
|
||||
("sketch", "arc") => (
|
||||
|e, a| Box::pin(crate::std::sketch::arc(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::arc"),
|
||||
),
|
||||
("sketch", "tangentialArc") => (
|
||||
|e, a| Box::pin(crate::std::sketch::tangential_arc(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::tangentialArc"),
|
||||
),
|
||||
("sketch", "bezierCurve") => (
|
||||
|e, a| Box::pin(crate::std::sketch::bezier_curve(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile"),
|
||||
StdFnProps::default("std::sketch::bezierCurve"),
|
||||
),
|
||||
("sketch", "subtract2d") => (
|
||||
|e, a| Box::pin(crate::std::sketch::subtract_2d(e, a)),
|
||||
StdFnProps::default("std::sketch::startProfile").include_in_feature_tree(),
|
||||
StdFnProps::default("std::sketch::subtract2d").include_in_feature_tree(),
|
||||
),
|
||||
("appearance", "hexString") => (
|
||||
|e, a| Box::pin(crate::std::appearance::hex_string(e, a)),
|
||||
|
@ -35,10 +35,10 @@ const MUST_HAVE_ONE_INSTANCE: &str = "There must be at least 1 instance of your
|
||||
|
||||
/// Repeat some 3D solid, changing each repetition slightly.
|
||||
pub async fn pattern_transform(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
|
||||
let transform: &FunctionSource = args.get_kw_arg("transform")?;
|
||||
let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
let solids = args.get_unlabeled_kw_arg("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg("instances", &RuntimeType::count(), exec_state)?;
|
||||
let transform: FunctionSource = args.get_kw_arg("transform", &RuntimeType::function(), exec_state)?;
|
||||
let use_original = args.get_kw_arg_opt("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
let solids = inner_pattern_transform(solids, instances, transform, use_original, exec_state, &args).await?;
|
||||
Ok(solids.into())
|
||||
@ -46,22 +46,22 @@ pub async fn pattern_transform(exec_state: &mut ExecState, args: Args) -> Result
|
||||
|
||||
/// Repeat some 2D sketch, changing each repetition slightly.
|
||||
pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
|
||||
let transform: &FunctionSource = args.get_kw_arg("transform")?;
|
||||
let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
let sketches = args.get_unlabeled_kw_arg("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg("instances", &RuntimeType::count(), exec_state)?;
|
||||
let transform: FunctionSource = args.get_kw_arg("transform", &RuntimeType::function(), exec_state)?;
|
||||
let use_original = args.get_kw_arg_opt("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
let sketches = inner_pattern_transform_2d(sketches, instances, transform, use_original, exec_state, &args).await?;
|
||||
Ok(sketches.into())
|
||||
}
|
||||
|
||||
async fn inner_pattern_transform<'a>(
|
||||
async fn inner_pattern_transform(
|
||||
solids: Vec<Solid>,
|
||||
instances: u32,
|
||||
transform: &'a FunctionSource,
|
||||
transform: FunctionSource,
|
||||
use_original: Option<bool>,
|
||||
exec_state: &mut ExecState,
|
||||
args: &'a Args,
|
||||
args: &Args,
|
||||
) -> Result<Vec<Solid>, KclError> {
|
||||
// Build the vec of transforms, one for each repetition.
|
||||
let mut transform_vec = Vec::with_capacity(usize::try_from(instances).unwrap());
|
||||
@ -72,7 +72,7 @@ async fn inner_pattern_transform<'a>(
|
||||
)));
|
||||
}
|
||||
for i in 1..instances {
|
||||
let t = make_transform::<Solid>(i, transform, args.source_range, exec_state, &args.ctx).await?;
|
||||
let t = make_transform::<Solid>(i, &transform, args.source_range, exec_state, &args.ctx).await?;
|
||||
transform_vec.push(t);
|
||||
}
|
||||
execute_pattern_transform(
|
||||
@ -85,13 +85,13 @@ async fn inner_pattern_transform<'a>(
|
||||
.await
|
||||
}
|
||||
|
||||
async fn inner_pattern_transform_2d<'a>(
|
||||
async fn inner_pattern_transform_2d(
|
||||
sketches: Vec<Sketch>,
|
||||
instances: u32,
|
||||
transform: &'a FunctionSource,
|
||||
transform: FunctionSource,
|
||||
use_original: Option<bool>,
|
||||
exec_state: &mut ExecState,
|
||||
args: &'a Args,
|
||||
args: &Args,
|
||||
) -> Result<Vec<Sketch>, KclError> {
|
||||
// Build the vec of transforms, one for each repetition.
|
||||
let mut transform_vec = Vec::with_capacity(usize::try_from(instances).unwrap());
|
||||
@ -102,7 +102,7 @@ async fn inner_pattern_transform_2d<'a>(
|
||||
)));
|
||||
}
|
||||
for i in 1..instances {
|
||||
let t = make_transform::<Sketch>(i, transform, args.source_range, exec_state, &args.ctx).await?;
|
||||
let t = make_transform::<Sketch>(i, &transform, args.source_range, exec_state, &args.ctx).await?;
|
||||
transform_vec.push(t);
|
||||
}
|
||||
execute_pattern_transform(
|
||||
@ -519,10 +519,10 @@ mod tests {
|
||||
|
||||
/// A linear pattern on a 2D sketch.
|
||||
pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
|
||||
let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?;
|
||||
let axis: Axis2dOrPoint2d = args.get_kw_arg_typed(
|
||||
let sketches = args.get_unlabeled_kw_arg("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg("instances", &RuntimeType::count(), exec_state)?;
|
||||
let distance: TyF64 = args.get_kw_arg("distance", &RuntimeType::length(), exec_state)?;
|
||||
let axis: Axis2dOrPoint2d = args.get_kw_arg(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Axis2d),
|
||||
@ -530,7 +530,7 @@ pub async fn pattern_linear_2d(exec_state: &mut ExecState, args: Args) -> Result
|
||||
]),
|
||||
exec_state,
|
||||
)?;
|
||||
let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
let use_original = args.get_kw_arg_opt("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
let axis = axis.to_point2d();
|
||||
if axis[0].n == 0.0 && axis[1].n == 0.0 {
|
||||
@ -579,10 +579,10 @@ async fn inner_pattern_linear_2d(
|
||||
|
||||
/// A linear pattern on a 3D model.
|
||||
pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
|
||||
let distance: TyF64 = args.get_kw_arg_typed("distance", &RuntimeType::length(), exec_state)?;
|
||||
let axis: Axis3dOrPoint3d = args.get_kw_arg_typed(
|
||||
let solids = args.get_unlabeled_kw_arg("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg("instances", &RuntimeType::count(), exec_state)?;
|
||||
let distance: TyF64 = args.get_kw_arg("distance", &RuntimeType::length(), exec_state)?;
|
||||
let axis: Axis3dOrPoint3d = args.get_kw_arg(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Axis3d),
|
||||
@ -590,7 +590,7 @@ pub async fn pattern_linear_3d(exec_state: &mut ExecState, args: Args) -> Result
|
||||
]),
|
||||
exec_state,
|
||||
)?;
|
||||
let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
let use_original = args.get_kw_arg_opt("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
let axis = axis.to_point3d();
|
||||
if axis[0].n == 0.0 && axis[1].n == 0.0 && axis[2].n == 0.0 {
|
||||
@ -747,12 +747,12 @@ impl CircularPattern {
|
||||
|
||||
/// A circular pattern on a 2D sketch.
|
||||
pub async fn pattern_circular_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
|
||||
let center: [TyF64; 2] = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?;
|
||||
let arc_degrees: Option<TyF64> = args.get_kw_arg_opt_typed("arcDegrees", &RuntimeType::degrees(), exec_state)?;
|
||||
let rotate_duplicates = args.get_kw_arg_opt_typed("rotateDuplicates", &RuntimeType::bool(), exec_state)?;
|
||||
let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
let sketches = args.get_unlabeled_kw_arg("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg("instances", &RuntimeType::count(), exec_state)?;
|
||||
let center: [TyF64; 2] = args.get_kw_arg("center", &RuntimeType::point2d(), exec_state)?;
|
||||
let arc_degrees: Option<TyF64> = args.get_kw_arg_opt("arcDegrees", &RuntimeType::degrees(), exec_state)?;
|
||||
let rotate_duplicates = args.get_kw_arg_opt("rotateDuplicates", &RuntimeType::bool(), exec_state)?;
|
||||
let use_original = args.get_kw_arg_opt("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
let sketches = inner_pattern_circular_2d(
|
||||
sketches,
|
||||
@ -817,14 +817,14 @@ async fn inner_pattern_circular_2d(
|
||||
|
||||
/// A circular pattern on a 3D model.
|
||||
pub async fn pattern_circular_3d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let solids = args.get_unlabeled_kw_arg("solids", &RuntimeType::solids(), exec_state)?;
|
||||
// The number of total instances. Must be greater than or equal to 1.
|
||||
// This includes the original entity. For example, if instances is 2,
|
||||
// there will be two copies -- the original, and one new copy.
|
||||
// If instances is 1, this has no effect.
|
||||
let instances: u32 = args.get_kw_arg_typed("instances", &RuntimeType::count(), exec_state)?;
|
||||
let instances: u32 = args.get_kw_arg("instances", &RuntimeType::count(), exec_state)?;
|
||||
// The axis around which to make the pattern. This is a 3D vector.
|
||||
let axis: Axis3dOrPoint3d = args.get_kw_arg_typed(
|
||||
let axis: Axis3dOrPoint3d = args.get_kw_arg(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Axis3d),
|
||||
@ -835,14 +835,14 @@ pub async fn pattern_circular_3d(exec_state: &mut ExecState, args: Args) -> Resu
|
||||
let axis = axis.to_point3d();
|
||||
|
||||
// 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)?;
|
||||
let center: [TyF64; 3] = args.get_kw_arg("center", &RuntimeType::point3d(), exec_state)?;
|
||||
// The arc angle (in degrees) to place the repetitions. Must be greater than 0.
|
||||
let arc_degrees: Option<TyF64> = args.get_kw_arg_opt_typed("arcDegrees", &RuntimeType::degrees(), exec_state)?;
|
||||
let arc_degrees: Option<TyF64> = args.get_kw_arg_opt("arcDegrees", &RuntimeType::degrees(), exec_state)?;
|
||||
// Whether or not to rotate the duplicates as they are copied.
|
||||
let rotate_duplicates = args.get_kw_arg_opt_typed("rotateDuplicates", &RuntimeType::bool(), exec_state)?;
|
||||
let rotate_duplicates = args.get_kw_arg_opt("rotateDuplicates", &RuntimeType::bool(), exec_state)?;
|
||||
// If the target being patterned is itself a pattern, then, should you use the original solid,
|
||||
// or the pattern?
|
||||
let use_original = args.get_kw_arg_opt_typed("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
let use_original = args.get_kw_arg_opt("useOriginal", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
let solids = inner_pattern_circular_3d(
|
||||
solids,
|
||||
|
@ -12,8 +12,8 @@ use crate::{
|
||||
|
||||
/// Offset a plane by a distance along its normal.
|
||||
pub async fn offset_plane(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let std_plane = args.get_unlabeled_kw_arg_typed("plane", &RuntimeType::plane(), exec_state)?;
|
||||
let offset: TyF64 = args.get_kw_arg_typed("offset", &RuntimeType::length(), exec_state)?;
|
||||
let std_plane = args.get_unlabeled_kw_arg("plane", &RuntimeType::plane(), exec_state)?;
|
||||
let offset: TyF64 = args.get_kw_arg("offset", &RuntimeType::length(), exec_state)?;
|
||||
let plane = inner_offset_plane(std_plane, offset, exec_state, &args).await?;
|
||||
Ok(KclValue::Plane { value: Box::new(plane) })
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ extern crate nalgebra_glm as glm;
|
||||
|
||||
/// Revolve a sketch or set of sketches around an axis.
|
||||
pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let axis = args.get_kw_arg_typed(
|
||||
let sketches = args.get_unlabeled_kw_arg("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let axis = args.get_kw_arg(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Edge),
|
||||
@ -33,13 +33,13 @@ 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::degrees(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd")?;
|
||||
let symmetric = args.get_kw_arg_opt_typed("symmetric", &RuntimeType::bool(), exec_state)?;
|
||||
let angle: Option<TyF64> = args.get_kw_arg_opt("angle", &RuntimeType::degrees(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let symmetric = args.get_kw_arg_opt("symmetric", &RuntimeType::bool(), exec_state)?;
|
||||
let bidirectional_angle: Option<TyF64> =
|
||||
args.get_kw_arg_opt_typed("bidirectionalAngle", &RuntimeType::angle(), exec_state)?;
|
||||
args.get_kw_arg_opt("bidirectionalAngle", &RuntimeType::angle(), exec_state)?;
|
||||
|
||||
let value = inner_revolve(
|
||||
sketches,
|
||||
|
@ -15,7 +15,7 @@ use crate::{
|
||||
|
||||
/// Returns the point at the end of the given segment.
|
||||
pub async fn segment_end(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let pt = inner_segment_end(&tag, exec_state, args.clone())?;
|
||||
|
||||
args.make_kcl_val_from_point([pt[0].n, pt[1].n], pt[0].ty.clone())
|
||||
@ -38,7 +38,7 @@ fn inner_segment_end(tag: &TagIdentifier, exec_state: &mut ExecState, args: Args
|
||||
|
||||
/// Returns the segment end of x.
|
||||
pub async fn segment_end_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let result = inner_segment_end_x(&tag, exec_state, args.clone())?;
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(result))
|
||||
@ -58,7 +58,7 @@ fn inner_segment_end_x(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
|
||||
|
||||
/// Returns the segment end of y.
|
||||
pub async fn segment_end_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let result = inner_segment_end_y(&tag, exec_state, args.clone())?;
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(result))
|
||||
@ -78,7 +78,7 @@ fn inner_segment_end_y(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
|
||||
|
||||
/// Returns the point at the start of the given segment.
|
||||
pub async fn segment_start(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let pt = inner_segment_start(&tag, exec_state, args.clone())?;
|
||||
|
||||
args.make_kcl_val_from_point([pt[0].n, pt[1].n], pt[0].ty.clone())
|
||||
@ -101,7 +101,7 @@ fn inner_segment_start(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
|
||||
|
||||
/// Returns the segment start of x.
|
||||
pub async fn segment_start_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let result = inner_segment_start_x(&tag, exec_state, args.clone())?;
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(result))
|
||||
@ -121,7 +121,7 @@ fn inner_segment_start_x(tag: &TagIdentifier, exec_state: &mut ExecState, args:
|
||||
|
||||
/// Returns the segment start of y.
|
||||
pub async fn segment_start_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let result = inner_segment_start_y(&tag, exec_state, args.clone())?;
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(result))
|
||||
@ -140,8 +140,7 @@ fn inner_segment_start_y(tag: &TagIdentifier, exec_state: &mut ExecState, args:
|
||||
}
|
||||
/// Returns the last segment of x.
|
||||
pub async fn last_segment_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let result = inner_last_segment_x(sketch, args.clone())?;
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(result))
|
||||
@ -164,8 +163,7 @@ fn inner_last_segment_x(sketch: Sketch, args: Args) -> Result<TyF64, KclError> {
|
||||
|
||||
/// Returns the last segment of y.
|
||||
pub async fn last_segment_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let result = inner_last_segment_y(sketch, args.clone())?;
|
||||
|
||||
Ok(args.make_user_val_from_f64_with_type(result))
|
||||
@ -188,7 +186,7 @@ fn inner_last_segment_y(sketch: Sketch, args: Args) -> Result<TyF64, KclError> {
|
||||
|
||||
/// Returns the length of the segment.
|
||||
pub async fn segment_length(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let result = inner_segment_length(&tag, exec_state, args.clone())?;
|
||||
Ok(args.make_user_val_from_f64_with_type(result))
|
||||
}
|
||||
@ -207,7 +205,7 @@ fn inner_segment_length(tag: &TagIdentifier, exec_state: &mut ExecState, args: A
|
||||
|
||||
/// Returns the angle of the segment.
|
||||
pub async fn segment_angle(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
|
||||
let result = inner_segment_angle(&tag, exec_state, args.clone())?;
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees())))
|
||||
@ -229,7 +227,7 @@ fn inner_segment_angle(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
|
||||
|
||||
/// Returns the angle coming out of the end of the segment in degrees.
|
||||
pub async fn tangent_to_end(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg_typed("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let tag: TagIdentifier = args.get_unlabeled_kw_arg("tag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
|
||||
let result = inner_tangent_to_end(&tag, exec_state, args.clone()).await?;
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::degrees())))
|
||||
|
@ -24,7 +24,6 @@ use crate::{
|
||||
},
|
||||
parsing::ast::types::TagNode,
|
||||
std::{
|
||||
sketch::NEW_TAG_KW,
|
||||
utils::{calculate_circle_center, distance},
|
||||
Args,
|
||||
},
|
||||
@ -43,11 +42,11 @@ pub enum SketchOrSurface {
|
||||
/// Sketch a circle.
|
||||
pub async fn circle(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch_or_surface =
|
||||
args.get_unlabeled_kw_arg_typed("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
|
||||
let center = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?;
|
||||
let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?;
|
||||
let diameter: Option<TyF64> = args.get_kw_arg_opt_typed("diameter", &RuntimeType::length(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
args.get_unlabeled_kw_arg("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
|
||||
let center = args.get_kw_arg("center", &RuntimeType::point2d(), exec_state)?;
|
||||
let radius: Option<TyF64> = args.get_kw_arg_opt("radius", &RuntimeType::length(), exec_state)?;
|
||||
let diameter: Option<TyF64> = args.get_kw_arg_opt("diameter", &RuntimeType::length(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let sketch = inner_circle(sketch_or_surface, center, radius, diameter, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
@ -130,11 +129,11 @@ async fn inner_circle(
|
||||
/// Sketch a 3-point circle.
|
||||
pub async fn circle_three_point(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch_or_surface =
|
||||
args.get_unlabeled_kw_arg_typed("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
|
||||
let p1 = args.get_kw_arg_typed("p1", &RuntimeType::point2d(), exec_state)?;
|
||||
let p2 = args.get_kw_arg_typed("p2", &RuntimeType::point2d(), exec_state)?;
|
||||
let p3 = args.get_kw_arg_typed("p3", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag")?;
|
||||
args.get_unlabeled_kw_arg("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
|
||||
let p1 = args.get_kw_arg("p1", &RuntimeType::point2d(), exec_state)?;
|
||||
let p2 = args.get_kw_arg("p2", &RuntimeType::point2d(), exec_state)?;
|
||||
let p3 = args.get_kw_arg("p3", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let sketch = inner_circle_three_point(sketch_or_surface, p1, p2, p3, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
@ -239,11 +238,11 @@ pub enum PolygonType {
|
||||
/// Create a regular polygon with the specified number of sides and radius.
|
||||
pub async fn polygon(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch_or_surface =
|
||||
args.get_unlabeled_kw_arg_typed("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
|
||||
let radius: TyF64 = args.get_kw_arg_typed("radius", &RuntimeType::length(), exec_state)?;
|
||||
let num_sides: TyF64 = args.get_kw_arg_typed("numSides", &RuntimeType::count(), exec_state)?;
|
||||
let center = args.get_kw_arg_typed("center", &RuntimeType::point2d(), exec_state)?;
|
||||
let inscribed = args.get_kw_arg_opt_typed("inscribed", &RuntimeType::bool(), exec_state)?;
|
||||
args.get_unlabeled_kw_arg("sketchOrSurface", &RuntimeType::sketch_or_surface(), exec_state)?;
|
||||
let radius: TyF64 = args.get_kw_arg("radius", &RuntimeType::length(), exec_state)?;
|
||||
let num_sides: TyF64 = args.get_kw_arg("numSides", &RuntimeType::count(), exec_state)?;
|
||||
let center = args.get_kw_arg("center", &RuntimeType::point2d(), exec_state)?;
|
||||
let inscribed = args.get_kw_arg_opt("inscribed", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
let sketch = inner_polygon(
|
||||
sketch_or_surface,
|
||||
|
@ -16,9 +16,9 @@ use crate::{
|
||||
|
||||
/// Create a shell.
|
||||
pub async fn shell(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let thickness: TyF64 = args.get_kw_arg_typed("thickness", &RuntimeType::length(), exec_state)?;
|
||||
let faces = args.get_kw_arg_typed(
|
||||
let solids = args.get_unlabeled_kw_arg("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let thickness: TyF64 = args.get_kw_arg("thickness", &RuntimeType::length(), exec_state)?;
|
||||
let faces = args.get_kw_arg(
|
||||
"faces",
|
||||
&RuntimeType::Array(Box::new(RuntimeType::tag()), ArrayLen::Minimum(1)),
|
||||
exec_state,
|
||||
@ -94,8 +94,8 @@ async fn inner_shell(
|
||||
|
||||
/// Make the inside of a 3D object hollow.
|
||||
pub async fn hollow(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solid = args.get_unlabeled_kw_arg_typed("solid", &RuntimeType::solid(), exec_state)?;
|
||||
let thickness: TyF64 = args.get_kw_arg_typed("thickness", &RuntimeType::length(), exec_state)?;
|
||||
let solid = args.get_unlabeled_kw_arg("solid", &RuntimeType::solid(), exec_state)?;
|
||||
let thickness: TyF64 = args.get_kw_arg("thickness", &RuntimeType::length(), exec_state)?;
|
||||
|
||||
let value = inner_hollow(solid, thickness, exec_state, args).await?;
|
||||
Ok(KclValue::Solid { value })
|
||||
|
@ -102,13 +102,13 @@ pub enum StartOrEnd {
|
||||
pub const NEW_TAG_KW: &str = "tag";
|
||||
|
||||
pub async fn involute_circular(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::sketch(), exec_state)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::sketch(), exec_state)?;
|
||||
|
||||
let start_radius: TyF64 = args.get_kw_arg_typed("startRadius", &RuntimeType::length(), exec_state)?;
|
||||
let end_radius: TyF64 = args.get_kw_arg_typed("endRadius", &RuntimeType::length(), exec_state)?;
|
||||
let angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::angle(), exec_state)?;
|
||||
let reverse = args.get_kw_arg_opt_typed("reverse", &RuntimeType::bool(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let start_radius: TyF64 = args.get_kw_arg("startRadius", &RuntimeType::length(), exec_state)?;
|
||||
let end_radius: TyF64 = args.get_kw_arg("endRadius", &RuntimeType::length(), exec_state)?;
|
||||
let angle: TyF64 = args.get_kw_arg("angle", &RuntimeType::angle(), exec_state)?;
|
||||
let reverse = args.get_kw_arg_opt("reverse", &RuntimeType::bool(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let new_sketch =
|
||||
inner_involute_circular(sketch, start_radius, end_radius, angle, reverse, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
@ -195,10 +195,10 @@ async fn inner_involute_circular(
|
||||
|
||||
/// Draw a line to a point.
|
||||
pub async fn line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::sketch(), exec_state)?;
|
||||
let end = args.get_kw_arg_opt_typed("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let end_absolute = args.get_kw_arg_opt_typed("endAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::sketch(), exec_state)?;
|
||||
let end = args.get_kw_arg_opt("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let end_absolute = args.get_kw_arg_opt("endAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let new_sketch = inner_line(sketch, end_absolute, end, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
@ -332,11 +332,10 @@ async fn straight_line(
|
||||
|
||||
/// Draw a line on the x-axis.
|
||||
pub async fn x_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let length: Option<TyF64> = args.get_kw_arg_opt_typed("length", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute: Option<TyF64> = args.get_kw_arg_opt_typed("endAbsolute", &RuntimeType::length(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let length: Option<TyF64> = args.get_kw_arg_opt("length", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute: Option<TyF64> = args.get_kw_arg_opt("endAbsolute", &RuntimeType::length(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let new_sketch = inner_x_line(sketch, length, end_absolute, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
@ -369,11 +368,10 @@ async fn inner_x_line(
|
||||
|
||||
/// Draw a line on the y-axis.
|
||||
pub async fn y_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let length: Option<TyF64> = args.get_kw_arg_opt_typed("length", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute: Option<TyF64> = args.get_kw_arg_opt_typed("endAbsolute", &RuntimeType::length(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let length: Option<TyF64> = args.get_kw_arg_opt("length", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute: Option<TyF64> = args.get_kw_arg_opt("endAbsolute", &RuntimeType::length(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let new_sketch = inner_y_line(sketch, length, end_absolute, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
@ -406,16 +404,14 @@ async fn inner_y_line(
|
||||
|
||||
/// Draw an angled line.
|
||||
pub async fn angled_line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch = args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::sketch(), exec_state)?;
|
||||
let angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::degrees(), exec_state)?;
|
||||
let length: Option<TyF64> = args.get_kw_arg_opt_typed("length", &RuntimeType::length(), exec_state)?;
|
||||
let length_x: Option<TyF64> = args.get_kw_arg_opt_typed("lengthX", &RuntimeType::length(), exec_state)?;
|
||||
let length_y: Option<TyF64> = args.get_kw_arg_opt_typed("lengthY", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute_x: Option<TyF64> =
|
||||
args.get_kw_arg_opt_typed("endAbsoluteX", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute_y: Option<TyF64> =
|
||||
args.get_kw_arg_opt_typed("endAbsoluteY", &RuntimeType::length(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::sketch(), exec_state)?;
|
||||
let angle: TyF64 = args.get_kw_arg("angle", &RuntimeType::degrees(), exec_state)?;
|
||||
let length: Option<TyF64> = args.get_kw_arg_opt("length", &RuntimeType::length(), exec_state)?;
|
||||
let length_x: Option<TyF64> = args.get_kw_arg_opt("lengthX", &RuntimeType::length(), exec_state)?;
|
||||
let length_y: Option<TyF64> = args.get_kw_arg_opt("lengthY", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute_x: Option<TyF64> = args.get_kw_arg_opt("endAbsoluteX", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute_y: Option<TyF64> = args.get_kw_arg_opt("endAbsoluteY", &RuntimeType::length(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let new_sketch = inner_angled_line(
|
||||
sketch,
|
||||
@ -686,13 +682,11 @@ async fn inner_angled_line_to_y(
|
||||
|
||||
/// Draw an angled line that intersects with a given line.
|
||||
pub async fn angled_line_that_intersects(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let angle: TyF64 = args.get_kw_arg_typed("angle", &RuntimeType::angle(), exec_state)?;
|
||||
let intersect_tag: TagIdentifier =
|
||||
args.get_kw_arg_typed("intersectTag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let offset = args.get_kw_arg_opt_typed("offset", &RuntimeType::length(), exec_state)?;
|
||||
let tag: Option<TagNode> = args.get_kw_arg_opt("tag")?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let angle: TyF64 = args.get_kw_arg("angle", &RuntimeType::angle(), exec_state)?;
|
||||
let intersect_tag: TagIdentifier = args.get_kw_arg("intersectTag", &RuntimeType::tag_identifier(), exec_state)?;
|
||||
let offset = args.get_kw_arg_opt("offset", &RuntimeType::length(), exec_state)?;
|
||||
let tag: Option<TagNode> = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let new_sketch =
|
||||
inner_angled_line_that_intersects(sketch, angle, intersect_tag, offset, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
@ -777,12 +771,12 @@ pub enum PlaneData {
|
||||
|
||||
/// Start a sketch on a specific plane or face.
|
||||
pub async fn start_sketch_on(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let data = args.get_unlabeled_kw_arg_typed(
|
||||
let data = args.get_unlabeled_kw_arg(
|
||||
"planeOrSolid",
|
||||
&RuntimeType::Union(vec![RuntimeType::solid(), RuntimeType::plane()]),
|
||||
exec_state,
|
||||
)?;
|
||||
let face = args.get_kw_arg_opt_typed("face", &RuntimeType::tag(), exec_state)?;
|
||||
let face = args.get_kw_arg_opt("face", &RuntimeType::tag(), exec_state)?;
|
||||
|
||||
match inner_start_sketch_on(data, face, exec_state, &args).await? {
|
||||
SketchSurface::Plane(value) => Ok(KclValue::Plane { value }),
|
||||
@ -901,13 +895,13 @@ async fn make_sketch_plane_from_orientation(
|
||||
|
||||
/// Start a new profile at a given point.
|
||||
pub async fn start_profile(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch_surface = args.get_unlabeled_kw_arg_typed(
|
||||
let sketch_surface = args.get_unlabeled_kw_arg(
|
||||
"startProfileOn",
|
||||
&RuntimeType::Union(vec![RuntimeType::plane(), RuntimeType::face()]),
|
||||
exec_state,
|
||||
)?;
|
||||
let start: [TyF64; 2] = args.get_kw_arg_typed("at", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let start: [TyF64; 2] = args.get_kw_arg("at", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let sketch = inner_start_profile(sketch_surface, start, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
@ -1031,7 +1025,7 @@ pub(crate) async fn inner_start_profile(
|
||||
|
||||
/// Returns the X component of the sketch profile start point.
|
||||
pub async fn profile_start_x(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("profile", &RuntimeType::sketch(), exec_state)?;
|
||||
let sketch: Sketch = args.get_unlabeled_kw_arg("profile", &RuntimeType::sketch(), exec_state)?;
|
||||
let ty = sketch.units.into();
|
||||
let x = inner_profile_start_x(sketch)?;
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(x, ty)))
|
||||
@ -1043,7 +1037,7 @@ pub(crate) fn inner_profile_start_x(profile: Sketch) -> Result<f64, KclError> {
|
||||
|
||||
/// Returns the Y component of the sketch profile start point.
|
||||
pub async fn profile_start_y(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("profile", &RuntimeType::sketch(), exec_state)?;
|
||||
let sketch: Sketch = args.get_unlabeled_kw_arg("profile", &RuntimeType::sketch(), exec_state)?;
|
||||
let ty = sketch.units.into();
|
||||
let x = inner_profile_start_y(sketch)?;
|
||||
Ok(args.make_user_val_from_f64_with_type(TyF64::new(x, ty)))
|
||||
@ -1055,7 +1049,7 @@ pub(crate) fn inner_profile_start_y(profile: Sketch) -> Result<f64, KclError> {
|
||||
|
||||
/// Returns the sketch profile start point.
|
||||
pub async fn profile_start(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch: Sketch = args.get_unlabeled_kw_arg_typed("profile", &RuntimeType::sketch(), exec_state)?;
|
||||
let sketch: Sketch = args.get_unlabeled_kw_arg("profile", &RuntimeType::sketch(), exec_state)?;
|
||||
let ty = sketch.units.into();
|
||||
let point = inner_profile_start(sketch)?;
|
||||
Ok(KclValue::from_point2d(point, ty, args.into()))
|
||||
@ -1067,9 +1061,8 @@ pub(crate) fn inner_profile_start(profile: Sketch) -> Result<[f64; 2], KclError>
|
||||
|
||||
/// Close the current sketch.
|
||||
pub async fn close(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let new_sketch = inner_close(sketch, tag, exec_state, args).await?;
|
||||
Ok(KclValue::Sketch {
|
||||
value: Box::new(new_sketch),
|
||||
@ -1115,18 +1108,16 @@ pub(crate) async fn inner_close(
|
||||
|
||||
/// Draw an arc.
|
||||
pub async fn arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
|
||||
let angle_start: Option<TyF64> = args.get_kw_arg_opt_typed("angleStart", &RuntimeType::degrees(), exec_state)?;
|
||||
let angle_end: Option<TyF64> = args.get_kw_arg_opt_typed("angleEnd", &RuntimeType::degrees(), exec_state)?;
|
||||
let radius: Option<TyF64> = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?;
|
||||
let diameter: Option<TyF64> = args.get_kw_arg_opt_typed("diameter", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute: Option<[TyF64; 2]> =
|
||||
args.get_kw_arg_opt_typed("endAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let angle_start: Option<TyF64> = args.get_kw_arg_opt("angleStart", &RuntimeType::degrees(), exec_state)?;
|
||||
let angle_end: Option<TyF64> = args.get_kw_arg_opt("angleEnd", &RuntimeType::degrees(), exec_state)?;
|
||||
let radius: Option<TyF64> = args.get_kw_arg_opt("radius", &RuntimeType::length(), exec_state)?;
|
||||
let diameter: Option<TyF64> = args.get_kw_arg_opt("diameter", &RuntimeType::length(), exec_state)?;
|
||||
let end_absolute: Option<[TyF64; 2]> = args.get_kw_arg_opt("endAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let interior_absolute: Option<[TyF64; 2]> =
|
||||
args.get_kw_arg_opt_typed("interiorAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
args.get_kw_arg_opt("interiorAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let new_sketch = inner_arc(
|
||||
sketch,
|
||||
angle_start,
|
||||
@ -1307,14 +1298,13 @@ pub async fn relative_arc(
|
||||
|
||||
/// Draw a tangential arc to a specific point.
|
||||
pub async fn tangential_arc(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let end = args.get_kw_arg_opt_typed("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let end_absolute = args.get_kw_arg_opt_typed("endAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let radius = args.get_kw_arg_opt_typed("radius", &RuntimeType::length(), exec_state)?;
|
||||
let diameter = args.get_kw_arg_opt_typed("diameter", &RuntimeType::length(), exec_state)?;
|
||||
let angle = args.get_kw_arg_opt_typed("angle", &RuntimeType::angle(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt(NEW_TAG_KW)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let end = args.get_kw_arg_opt("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let end_absolute = args.get_kw_arg_opt("endAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let radius = args.get_kw_arg_opt("radius", &RuntimeType::length(), exec_state)?;
|
||||
let diameter = args.get_kw_arg_opt("diameter", &RuntimeType::length(), exec_state)?;
|
||||
let angle = args.get_kw_arg_opt("angle", &RuntimeType::angle(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let new_sketch = inner_tangential_arc(
|
||||
sketch,
|
||||
@ -1563,15 +1553,14 @@ async fn inner_tangential_arc_to_point(
|
||||
|
||||
/// Draw a bezier curve.
|
||||
pub async fn bezier_curve(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let control1 = args.get_kw_arg_opt_typed("control1", &RuntimeType::point2d(), exec_state)?;
|
||||
let control2 = args.get_kw_arg_opt_typed("control2", &RuntimeType::point2d(), exec_state)?;
|
||||
let end = args.get_kw_arg_opt_typed("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let control1_absolute = args.get_kw_arg_opt_typed("control1Absolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let control2_absolute = args.get_kw_arg_opt_typed("control2Absolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let end_absolute = args.get_kw_arg_opt_typed("endAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag")?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let control1 = args.get_kw_arg_opt("control1", &RuntimeType::point2d(), exec_state)?;
|
||||
let control2 = args.get_kw_arg_opt("control2", &RuntimeType::point2d(), exec_state)?;
|
||||
let end = args.get_kw_arg_opt("end", &RuntimeType::point2d(), exec_state)?;
|
||||
let control1_absolute = args.get_kw_arg_opt("control1Absolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let control2_absolute = args.get_kw_arg_opt("control2Absolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let end_absolute = args.get_kw_arg_opt("endAbsolute", &RuntimeType::point2d(), exec_state)?;
|
||||
let tag = args.get_kw_arg_opt("tag", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let new_sketch = inner_bezier_curve(
|
||||
sketch,
|
||||
@ -1689,10 +1678,9 @@ async fn inner_bezier_curve(
|
||||
|
||||
/// Use a sketch to cut a hole in another sketch.
|
||||
pub async fn subtract_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch =
|
||||
args.get_unlabeled_kw_arg_typed("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
let sketch = args.get_unlabeled_kw_arg("sketch", &RuntimeType::Primitive(PrimitiveType::Sketch), exec_state)?;
|
||||
|
||||
let tool: Vec<Sketch> = args.get_kw_arg_typed(
|
||||
let tool: Vec<Sketch> = args.get_kw_arg(
|
||||
"tool",
|
||||
&RuntimeType::Array(
|
||||
Box::new(RuntimeType::Primitive(PrimitiveType::Sketch)),
|
||||
|
@ -29,17 +29,17 @@ 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_typed(
|
||||
let sketches = args.get_unlabeled_kw_arg("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let path: SweepPath = args.get_kw_arg(
|
||||
"path",
|
||||
&RuntimeType::Union(vec![RuntimeType::sketch(), RuntimeType::helix()]),
|
||||
exec_state,
|
||||
)?;
|
||||
let sectional = args.get_kw_arg_opt_typed("sectional", &RuntimeType::bool(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt_typed("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let relative_to: Option<String> = args.get_kw_arg_opt_typed("relativeTo", &RuntimeType::string(), exec_state)?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd")?;
|
||||
let sectional = args.get_kw_arg_opt("sectional", &RuntimeType::bool(), exec_state)?;
|
||||
let tolerance: Option<TyF64> = args.get_kw_arg_opt("tolerance", &RuntimeType::length(), exec_state)?;
|
||||
let relative_to: Option<String> = args.get_kw_arg_opt("relativeTo", &RuntimeType::string(), exec_state)?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart", &RuntimeType::tag_decl(), exec_state)?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd", &RuntimeType::tag_decl(), exec_state)?;
|
||||
|
||||
let value = inner_sweep(
|
||||
sketches,
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
|
||||
/// Scale a solid or a sketch.
|
||||
pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let objects = args.get_unlabeled_kw_arg_typed(
|
||||
let objects = args.get_unlabeled_kw_arg(
|
||||
"objects",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::sketches(),
|
||||
@ -30,10 +30,10 @@ pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
]),
|
||||
exec_state,
|
||||
)?;
|
||||
let scale_x: Option<TyF64> = args.get_kw_arg_opt_typed("x", &RuntimeType::count(), exec_state)?;
|
||||
let scale_y: Option<TyF64> = args.get_kw_arg_opt_typed("y", &RuntimeType::count(), exec_state)?;
|
||||
let scale_z: Option<TyF64> = args.get_kw_arg_opt_typed("z", &RuntimeType::count(), exec_state)?;
|
||||
let global = args.get_kw_arg_opt_typed("global", &RuntimeType::bool(), exec_state)?;
|
||||
let scale_x: Option<TyF64> = args.get_kw_arg_opt("x", &RuntimeType::count(), exec_state)?;
|
||||
let scale_y: Option<TyF64> = args.get_kw_arg_opt("y", &RuntimeType::count(), exec_state)?;
|
||||
let scale_z: Option<TyF64> = args.get_kw_arg_opt("z", &RuntimeType::count(), exec_state)?;
|
||||
let global = args.get_kw_arg_opt("global", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
// Ensure at least one scale value is provided.
|
||||
if scale_x.is_none() && scale_y.is_none() && scale_z.is_none() {
|
||||
@ -103,7 +103,7 @@ async fn inner_scale(
|
||||
|
||||
/// Move a solid or a sketch.
|
||||
pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let objects = args.get_unlabeled_kw_arg_typed(
|
||||
let objects = args.get_unlabeled_kw_arg(
|
||||
"objects",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::sketches(),
|
||||
@ -112,10 +112,10 @@ pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
]),
|
||||
exec_state,
|
||||
)?;
|
||||
let translate_x: Option<TyF64> = args.get_kw_arg_opt_typed("x", &RuntimeType::length(), exec_state)?;
|
||||
let translate_y: Option<TyF64> = args.get_kw_arg_opt_typed("y", &RuntimeType::length(), exec_state)?;
|
||||
let translate_z: Option<TyF64> = args.get_kw_arg_opt_typed("z", &RuntimeType::length(), exec_state)?;
|
||||
let global = args.get_kw_arg_opt_typed("global", &RuntimeType::bool(), exec_state)?;
|
||||
let translate_x: Option<TyF64> = args.get_kw_arg_opt("x", &RuntimeType::length(), exec_state)?;
|
||||
let translate_y: Option<TyF64> = args.get_kw_arg_opt("y", &RuntimeType::length(), exec_state)?;
|
||||
let translate_z: Option<TyF64> = args.get_kw_arg_opt("z", &RuntimeType::length(), exec_state)?;
|
||||
let global = args.get_kw_arg_opt("global", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
// Ensure at least one translation value is provided.
|
||||
if translate_x.is_none() && translate_y.is_none() && translate_z.is_none() {
|
||||
@ -176,7 +176,7 @@ async fn inner_translate(
|
||||
|
||||
/// Rotate a solid or a sketch.
|
||||
pub async fn rotate(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let objects = args.get_unlabeled_kw_arg_typed(
|
||||
let objects = args.get_unlabeled_kw_arg(
|
||||
"objects",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::sketches(),
|
||||
@ -185,10 +185,10 @@ 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::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<Axis3dOrPoint3d> = args.get_kw_arg_opt_typed(
|
||||
let roll: Option<TyF64> = args.get_kw_arg_opt("roll", &RuntimeType::degrees(), exec_state)?;
|
||||
let pitch: Option<TyF64> = args.get_kw_arg_opt("pitch", &RuntimeType::degrees(), exec_state)?;
|
||||
let yaw: Option<TyF64> = args.get_kw_arg_opt("yaw", &RuntimeType::degrees(), exec_state)?;
|
||||
let axis: Option<Axis3dOrPoint3d> = args.get_kw_arg_opt(
|
||||
"axis",
|
||||
&RuntimeType::Union(vec![
|
||||
RuntimeType::Primitive(PrimitiveType::Axis3d),
|
||||
@ -197,8 +197,8 @@ pub async fn rotate(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
exec_state,
|
||||
)?;
|
||||
let axis = axis.map(|a| a.to_point3d());
|
||||
let angle: Option<TyF64> = args.get_kw_arg_opt_typed("angle", &RuntimeType::degrees(), exec_state)?;
|
||||
let global = args.get_kw_arg_opt_typed("global", &RuntimeType::bool(), exec_state)?;
|
||||
let angle: Option<TyF64> = args.get_kw_arg_opt("angle", &RuntimeType::degrees(), exec_state)?;
|
||||
let global = args.get_kw_arg_opt("global", &RuntimeType::bool(), exec_state)?;
|
||||
|
||||
// Check if no rotation values are provided.
|
||||
if roll.is_none() && pitch.is_none() && yaw.is_none() && axis.is_none() && angle.is_none() {
|
||||
|
@ -1,16 +1,26 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use crate::parsing::{
|
||||
ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, AscribedExpression, BinaryExpression, BinaryOperator,
|
||||
BinaryPart, BodyItem, CallExpressionKw, CommentStyle, DefaultParamVal, Expr, FormatOptions, FunctionExpression,
|
||||
IfExpression, ImportSelector, ImportStatement, ItemVisibility, LabeledArg, Literal, LiteralIdentifier,
|
||||
LiteralValue, MemberExpression, MemberObject, Node, NonCodeNode, NonCodeValue, ObjectExpression, Parameter,
|
||||
PipeExpression, Program, TagDeclarator, TypeDeclaration, UnaryExpression, VariableDeclaration, VariableKind,
|
||||
use crate::{
|
||||
parsing::{
|
||||
ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, AscribedExpression, BinaryExpression, BinaryOperator,
|
||||
BinaryPart, BodyItem, CallExpressionKw, CommentStyle, DefaultParamVal, Expr, FormatOptions,
|
||||
FunctionExpression, IfExpression, ImportSelector, ImportStatement, ItemVisibility, LabeledArg, Literal,
|
||||
LiteralIdentifier, LiteralValue, MemberExpression, Node, NonCodeNode, NonCodeValue, ObjectExpression,
|
||||
Parameter, PipeExpression, Program, TagDeclarator, TypeDeclaration, UnaryExpression, VariableDeclaration,
|
||||
VariableKind,
|
||||
},
|
||||
deprecation, DeprecationKind, PIPE_OPERATOR,
|
||||
},
|
||||
deprecation, DeprecationKind, PIPE_OPERATOR,
|
||||
KclError, ModuleId,
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn fmt(input: &str) -> Result<String, KclError> {
|
||||
let program = crate::parsing::parse_str(input, ModuleId::default()).parse_errs_as_err()?;
|
||||
Ok(program.recast(&Default::default(), 0))
|
||||
}
|
||||
|
||||
impl Program {
|
||||
pub fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
||||
let indentation = options.get_indentation(indentation_level);
|
||||
@ -278,11 +288,11 @@ impl Expr {
|
||||
ctxt = ExprContext::Other;
|
||||
}
|
||||
match &self {
|
||||
Expr::BinaryExpression(bin_exp) => bin_exp.recast(options),
|
||||
Expr::BinaryExpression(bin_exp) => bin_exp.recast(options, indentation_level, ctxt),
|
||||
Expr::ArrayExpression(array_exp) => array_exp.recast(options, indentation_level, ctxt),
|
||||
Expr::ArrayRangeExpression(range_exp) => range_exp.recast(options, indentation_level, ctxt),
|
||||
Expr::ObjectExpression(ref obj_exp) => obj_exp.recast(options, indentation_level, ctxt),
|
||||
Expr::MemberExpression(mem_exp) => mem_exp.recast(),
|
||||
Expr::MemberExpression(mem_exp) => mem_exp.recast(options, indentation_level, ctxt),
|
||||
Expr::Literal(literal) => literal.recast(),
|
||||
Expr::FunctionExpression(func_exp) => {
|
||||
let mut result = if is_decl { String::new() } else { "fn".to_owned() };
|
||||
@ -299,7 +309,7 @@ impl Expr {
|
||||
}
|
||||
Expr::TagDeclarator(tag) => tag.recast(),
|
||||
Expr::PipeExpression(pipe_exp) => pipe_exp.recast(options, indentation_level),
|
||||
Expr::UnaryExpression(unary_exp) => unary_exp.recast(options),
|
||||
Expr::UnaryExpression(unary_exp) => unary_exp.recast(options, indentation_level, ctxt),
|
||||
Expr::IfExpression(e) => e.recast(options, indentation_level, ctxt),
|
||||
Expr::PipeSubstitution(_) => crate::parsing::PIPE_SUBSTITUTION_OPERATOR.to_string(),
|
||||
Expr::LabelledExpression(e) => {
|
||||
@ -332,7 +342,7 @@ impl AscribedExpression {
|
||||
}
|
||||
|
||||
impl BinaryPart {
|
||||
fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
||||
fn recast(&self, options: &FormatOptions, indentation_level: usize, ctxt: ExprContext) -> String {
|
||||
match &self {
|
||||
BinaryPart::Literal(literal) => literal.recast(),
|
||||
BinaryPart::Name(name) => {
|
||||
@ -342,12 +352,16 @@ impl BinaryPart {
|
||||
None => result,
|
||||
}
|
||||
}
|
||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.recast(options),
|
||||
BinaryPart::BinaryExpression(binary_expression) => {
|
||||
binary_expression.recast(options, indentation_level, ctxt)
|
||||
}
|
||||
BinaryPart::CallExpressionKw(call_expression) => {
|
||||
call_expression.recast(options, indentation_level, ExprContext::Other)
|
||||
}
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.recast(options),
|
||||
BinaryPart::MemberExpression(member_expression) => member_expression.recast(),
|
||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.recast(options, indentation_level, ctxt),
|
||||
BinaryPart::MemberExpression(member_expression) => {
|
||||
member_expression.recast(options, indentation_level, ctxt)
|
||||
}
|
||||
BinaryPart::IfExpression(e) => e.recast(options, indentation_level, ExprContext::Other),
|
||||
BinaryPart::AscribedExpression(e) => e.recast(options, indentation_level, ExprContext::Other),
|
||||
}
|
||||
@ -670,7 +684,7 @@ impl ObjectExpression {
|
||||
}
|
||||
|
||||
impl MemberExpression {
|
||||
fn recast(&self) -> String {
|
||||
fn recast(&self, options: &FormatOptions, indentation_level: usize, ctxt: ExprContext) -> String {
|
||||
let key_str = match &self.property {
|
||||
LiteralIdentifier::Identifier(identifier) => {
|
||||
if self.computed {
|
||||
@ -682,15 +696,12 @@ impl MemberExpression {
|
||||
LiteralIdentifier::Literal(lit) => format!("[{}]", &(*lit.raw)),
|
||||
};
|
||||
|
||||
match &self.object {
|
||||
MemberObject::MemberExpression(member_exp) => member_exp.recast() + key_str.as_str(),
|
||||
MemberObject::Identifier(identifier) => identifier.name.to_string() + key_str.as_str(),
|
||||
}
|
||||
self.object.recast(options, indentation_level, ctxt) + key_str.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl BinaryExpression {
|
||||
fn recast(&self, options: &FormatOptions) -> String {
|
||||
fn recast(&self, options: &FormatOptions, _indentation_level: usize, ctxt: ExprContext) -> String {
|
||||
let maybe_wrap_it = |a: String, doit: bool| -> String {
|
||||
if doit {
|
||||
format!("({})", a)
|
||||
@ -715,15 +726,15 @@ impl BinaryExpression {
|
||||
|
||||
format!(
|
||||
"{} {} {}",
|
||||
maybe_wrap_it(self.left.recast(options, 0), should_wrap_left),
|
||||
maybe_wrap_it(self.left.recast(options, 0, ctxt), should_wrap_left),
|
||||
self.operator,
|
||||
maybe_wrap_it(self.right.recast(options, 0), should_wrap_right)
|
||||
maybe_wrap_it(self.right.recast(options, 0, ctxt), should_wrap_right)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryExpression {
|
||||
fn recast(&self, options: &FormatOptions) -> String {
|
||||
fn recast(&self, options: &FormatOptions, _indentation_level: usize, ctxt: ExprContext) -> String {
|
||||
match self.argument {
|
||||
BinaryPart::Literal(_)
|
||||
| BinaryPart::Name(_)
|
||||
@ -731,10 +742,10 @@ impl UnaryExpression {
|
||||
| BinaryPart::IfExpression(_)
|
||||
| BinaryPart::AscribedExpression(_)
|
||||
| BinaryPart::CallExpressionKw(_) => {
|
||||
format!("{}{}", &self.operator, self.argument.recast(options, 0))
|
||||
format!("{}{}", &self.operator, self.argument.recast(options, 0, ctxt))
|
||||
}
|
||||
BinaryPart::BinaryExpression(_) | BinaryPart::UnaryExpression(_) => {
|
||||
format!("{}({})", &self.operator, self.argument.recast(options, 0))
|
||||
format!("{}({})", &self.operator, self.argument.recast(options, 0, ctxt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,15 +226,6 @@ impl<'tree> From<&'tree types::BinaryPart> for Node<'tree> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree> From<&'tree types::MemberObject> for Node<'tree> {
|
||||
fn from(node: &'tree types::MemberObject) -> Self {
|
||||
match node {
|
||||
types::MemberObject::MemberExpression(me) => me.as_ref().into(),
|
||||
types::MemberObject::Identifier(id) => id.as_ref().into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree> From<&'tree types::LiteralIdentifier> for Node<'tree> {
|
||||
fn from(node: &'tree types::LiteralIdentifier) -> Self {
|
||||
match node {
|
||||
|
Reference in New Issue
Block a user