Fix lazy fillet (#3176)

* WIP: Fix lazy fillet

* cleanup

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
This commit is contained in:
Jonathan Tran
2024-07-29 23:22:52 -04:00
committed by GitHub
parent 789fb83a5d
commit 1c44b01d16
9 changed files with 253 additions and 57 deletions

View File

@ -23,8 +23,8 @@ use crate::{
docs::StdLibFn, docs::StdLibFn,
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
executor::{ executor::{
BodyType, ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange, StatementKind, BodyType, DynamicState, ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange,
TagEngineInfo, TagIdentifier, UserVal, StatementKind, TagEngineInfo, TagIdentifier, UserVal,
}, },
parser::PIPE_OPERATOR, parser::PIPE_OPERATOR,
std::{kcl_stdlib::KclStdLibFn, FunctionKind}, std::{kcl_stdlib::KclStdLibFn, FunctionKind},
@ -918,6 +918,7 @@ impl BinaryPart {
pub async fn get_result( pub async fn get_result(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
@ -928,10 +929,16 @@ impl BinaryPart {
Ok(value.clone()) Ok(value.clone())
} }
BinaryPart::BinaryExpression(binary_expression) => { BinaryPart::BinaryExpression(binary_expression) => {
binary_expression.get_result(memory, pipe_info, ctx).await binary_expression
.get_result(memory, dynamic_state, pipe_info, ctx)
.await
}
BinaryPart::CallExpression(call_expression) => {
call_expression.execute(memory, dynamic_state, pipe_info, ctx).await
}
BinaryPart::UnaryExpression(unary_expression) => {
unary_expression.get_result(memory, dynamic_state, pipe_info, ctx).await
} }
BinaryPart::CallExpression(call_expression) => call_expression.execute(memory, pipe_info, ctx).await,
BinaryPart::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, ctx).await,
BinaryPart::MemberExpression(member_expression) => member_expression.get_result(memory), BinaryPart::MemberExpression(member_expression) => member_expression.get_result(memory),
} }
} }
@ -1311,6 +1318,7 @@ impl CallExpression {
pub async fn execute( pub async fn execute(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
@ -1323,7 +1331,14 @@ impl CallExpression {
source_range: SourceRange([arg.start(), arg.end()]), source_range: SourceRange([arg.start(), arg.end()]),
}; };
let result = ctx let result = ctx
.arg_into_mem_item(arg, memory, pipe_info, &metadata, StatementKind::Expression) .arg_into_mem_item(
arg,
memory,
dynamic_state,
pipe_info,
&metadata,
StatementKind::Expression,
)
.await?; .await?;
fn_args.push(result); fn_args.push(result);
} }
@ -1331,7 +1346,8 @@ impl CallExpression {
match ctx.stdlib.get_either(&self.callee.name) { match ctx.stdlib.get_either(&self.callee.name) {
FunctionKind::Core(func) => { FunctionKind::Core(func) => {
// Attempt to call the function. // Attempt to call the function.
let args = crate::std::Args::new(fn_args, self.into(), ctx.clone(), memory.clone()); let args =
crate::std::Args::new(fn_args, self.into(), ctx.clone(), memory.clone(), dynamic_state.clone());
let mut result = func.std_lib_fn()(args).await?; let mut result = func.std_lib_fn()(args).await?;
// If the return result is a sketch group or extrude group, we want to update the // If the return result is a sketch group or extrude group, we want to update the
@ -1433,9 +1449,14 @@ impl CallExpression {
} }
} }
let mut fn_dynamic_state = dynamic_state.clone();
// Call the stdlib function // Call the stdlib function
let p = func.function().clone().body; let p = func.function().clone().body;
let results = match ctx.inner_execute(&p, &mut fn_memory, BodyType::Block).await { let results = match ctx
.inner_execute(&p, &mut fn_memory, &mut fn_dynamic_state, BodyType::Block)
.await
{
Ok(results) => results, Ok(results) => results,
Err(err) => { Err(err) => {
// We need to override the source ranges so we don't get the embedded kcl // We need to override the source ranges so we don't get the embedded kcl
@ -1456,7 +1477,11 @@ impl CallExpression {
} }
FunctionKind::UserDefined => { FunctionKind::UserDefined => {
let func = memory.get(&fn_name, self.into())?; let func = memory.get(&fn_name, self.into())?;
let result = func.call_fn(fn_args, ctx.clone()).await.map_err(|e| { let fn_dynamic_state = dynamic_state.merge(memory);
let result = func
.call_fn(fn_args, &fn_dynamic_state, ctx.clone())
.await
.map_err(|e| {
// Add the call expression to the source ranges. // Add the call expression to the source ranges.
e.add_source_ranges(vec![self.into()]) e.add_source_ranges(vec![self.into()])
})?; })?;
@ -2295,6 +2320,7 @@ impl ArrayExpression {
pub async fn execute( pub async fn execute(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
@ -2310,13 +2336,29 @@ impl ArrayExpression {
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => { Value::BinaryExpression(binary_expression) => {
binary_expression.get_result(memory, pipe_info, ctx).await? binary_expression
.get_result(memory, dynamic_state, pipe_info, ctx)
.await?
}
Value::CallExpression(call_expression) => {
call_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
}
Value::UnaryExpression(unary_expression) => {
unary_expression
.get_result(memory, dynamic_state, pipe_info, ctx)
.await?
}
Value::ObjectExpression(object_expression) => {
object_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
}
Value::ArrayExpression(array_expression) => {
array_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
}
Value::PipeExpression(pipe_expression) => {
pipe_expression
.get_result(memory, dynamic_state, pipe_info, ctx)
.await?
} }
Value::CallExpression(call_expression) => call_expression.execute(memory, pipe_info, ctx).await?,
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, ctx).await?,
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, ctx).await?,
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, ctx).await?,
Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, ctx).await?,
Value::PipeSubstitution(pipe_substitution) => { Value::PipeSubstitution(pipe_substitution) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
@ -2465,6 +2507,7 @@ impl ObjectExpression {
pub async fn execute( pub async fn execute(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
@ -2479,13 +2522,29 @@ impl ObjectExpression {
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => { Value::BinaryExpression(binary_expression) => {
binary_expression.get_result(memory, pipe_info, ctx).await? binary_expression
.get_result(memory, dynamic_state, pipe_info, ctx)
.await?
}
Value::CallExpression(call_expression) => {
call_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
}
Value::UnaryExpression(unary_expression) => {
unary_expression
.get_result(memory, dynamic_state, pipe_info, ctx)
.await?
}
Value::ObjectExpression(object_expression) => {
object_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
}
Value::ArrayExpression(array_expression) => {
array_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
}
Value::PipeExpression(pipe_expression) => {
pipe_expression
.get_result(memory, dynamic_state, pipe_info, ctx)
.await?
} }
Value::CallExpression(call_expression) => call_expression.execute(memory, pipe_info, ctx).await?,
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, ctx).await?,
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, ctx).await?,
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, ctx).await?,
Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, ctx).await?,
Value::MemberExpression(member_expression) => member_expression.get_result(memory)?, Value::MemberExpression(member_expression) => member_expression.get_result(memory)?,
Value::PipeSubstitution(pipe_substitution) => { Value::PipeSubstitution(pipe_substitution) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
@ -2947,11 +3006,20 @@ impl BinaryExpression {
pub async fn get_result( pub async fn get_result(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
let left_json_value = self.left.get_result(memory, pipe_info, ctx).await?.get_json_value()?; let left_json_value = self
let right_json_value = self.right.get_result(memory, pipe_info, ctx).await?.get_json_value()?; .left
.get_result(memory, dynamic_state, pipe_info, ctx)
.await?
.get_json_value()?;
let right_json_value = self
.right
.get_result(memory, dynamic_state, pipe_info, ctx)
.await?
.get_json_value()?;
// First check if we are doing string concatenation. // First check if we are doing string concatenation.
if self.operator == BinaryOperator::Add { if self.operator == BinaryOperator::Add {
@ -3156,13 +3224,14 @@ impl UnaryExpression {
pub async fn get_result( pub async fn get_result(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
let num = parse_json_number_as_f64( let num = parse_json_number_as_f64(
&self &self
.argument .argument
.get_result(memory, pipe_info, ctx) .get_result(memory, dynamic_state, pipe_info, ctx)
.await? .await?
.get_json_value()?, .get_json_value()?,
self.into(), self.into(),
@ -3333,10 +3402,11 @@ impl PipeExpression {
pub async fn get_result( pub async fn get_result(
&self, &self,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
ctx: &ExecutorContext, ctx: &ExecutorContext,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
execute_pipe_body(memory, &self.body, pipe_info, self.into(), ctx).await execute_pipe_body(memory, dynamic_state, &self.body, pipe_info, self.into(), ctx).await
} }
/// Rename all identifiers that have the old name to the new given name. /// Rename all identifiers that have the old name to the new given name.
@ -3350,6 +3420,7 @@ impl PipeExpression {
#[async_recursion::async_recursion] #[async_recursion::async_recursion]
async fn execute_pipe_body( async fn execute_pipe_body(
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
body: &[Value], body: &[Value],
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
source_range: SourceRange, source_range: SourceRange,
@ -3370,7 +3441,14 @@ async fn execute_pipe_body(
source_range: SourceRange([first.start(), first.end()]), source_range: SourceRange([first.start(), first.end()]),
}; };
let output = ctx let output = ctx
.arg_into_mem_item(first, memory, pipe_info, &meta, StatementKind::Expression) .arg_into_mem_item(
first,
memory,
dynamic_state,
pipe_info,
&meta,
StatementKind::Expression,
)
.await?; .await?;
// Now that we've evaluated the first child expression in the pipeline, following child expressions // Now that we've evaluated the first child expression in the pipeline, following child expressions
// should use the previous child expression for %. // should use the previous child expression for %.
@ -3381,9 +3459,15 @@ async fn execute_pipe_body(
for expression in body { for expression in body {
let output = match expression { let output = match expression {
Value::BinaryExpression(binary_expression) => { Value::BinaryExpression(binary_expression) => {
binary_expression.get_result(memory, &new_pipe_info, ctx).await? binary_expression
.get_result(memory, dynamic_state, &new_pipe_info, ctx)
.await?
}
Value::CallExpression(call_expression) => {
call_expression
.execute(memory, dynamic_state, &new_pipe_info, ctx)
.await?
} }
Value::CallExpression(call_expression) => call_expression.execute(memory, &new_pipe_info, ctx).await?,
Value::Identifier(identifier) => memory.get(&identifier.name, identifier.into())?.clone(), Value::Identifier(identifier) => memory.get(&identifier.name, identifier.into())?.clone(),
_ => { _ => {
// Return an error this should not happen. // Return an error this should not happen.

View File

@ -195,6 +195,50 @@ impl Environment {
} }
} }
/// Dynamic state that depends on the dynamic flow of the program, like the call
/// stack. If the language had exceptions, for example, you could store the
/// stack of exception handlers here.
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, ts_rs::TS, JsonSchema)]
pub struct DynamicState {
pub extrude_group_ids: Vec<ExtrudeGroupLazyIds>,
}
impl DynamicState {
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn merge(&self, memory: &ProgramMemory) -> Self {
let mut merged = self.clone();
merged.append(memory);
merged
}
pub fn append(&mut self, memory: &ProgramMemory) {
for env in &memory.environments {
for item in env.bindings.values() {
if let MemoryItem::ExtrudeGroup(eg) = item {
self.extrude_group_ids.push(ExtrudeGroupLazyIds::from(eg.as_ref()));
}
}
}
}
pub fn fillet_or_chamfer_ids_on_sketch_group(&self, sketch_group_id: uuid::Uuid) -> Vec<uuid::Uuid> {
self.extrude_group_ids
.iter()
.flat_map(|eg| {
if eg.sketch_group_id == sketch_group_id {
eg.fillet_or_chamfers.clone()
} else {
Vec::new()
}
})
.collect::<Vec<_>>()
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "camelCase", untagged)] #[serde(rename_all = "camelCase", untagged)]
@ -623,6 +667,7 @@ pub type MemoryFunction =
memory: ProgramMemory, memory: ProgramMemory,
expression: Box<FunctionExpression>, expression: Box<FunctionExpression>,
metadata: Vec<Metadata>, metadata: Vec<Metadata>,
dynamic_state: DynamicState,
ctx: ExecutorContext, ctx: ExecutorContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>; ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>;
@ -632,6 +677,7 @@ fn force_memory_function<
ProgramMemory, ProgramMemory,
Box<FunctionExpression>, Box<FunctionExpression>,
Vec<Metadata>, Vec<Metadata>,
DynamicState,
ExecutorContext, ExecutorContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>, ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>,
>( >(
@ -800,6 +846,7 @@ impl MemoryItem {
pub async fn call_fn( pub async fn call_fn(
&self, &self,
args: Vec<MemoryItem>, args: Vec<MemoryItem>,
dynamic_state: &DynamicState,
ctx: ExecutorContext, ctx: ExecutorContext,
) -> Result<Option<ProgramReturn>, KclError> { ) -> Result<Option<ProgramReturn>, KclError> {
let MemoryItem::Function { let MemoryItem::Function {
@ -825,6 +872,7 @@ impl MemoryItem {
closure_memory.as_ref().clone(), closure_memory.as_ref().clone(),
expression.clone(), expression.clone(),
meta.clone(), meta.clone(),
dynamic_state.clone(),
ctx, ctx,
) )
.await .await
@ -997,6 +1045,27 @@ impl ExtrudeGroup {
} }
} }
/// An extrude group ID and its fillet and chamfer IDs. This is needed for lazy
/// fillet evaluation.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
pub struct ExtrudeGroupLazyIds {
pub extrude_group_id: uuid::Uuid,
pub sketch_group_id: uuid::Uuid,
/// Chamfers or fillets on this extrude group.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub fillet_or_chamfers: Vec<uuid::Uuid>,
}
impl From<&ExtrudeGroup> for ExtrudeGroupLazyIds {
fn from(eg: &ExtrudeGroup) -> Self {
Self {
extrude_group_id: eg.id,
sketch_group_id: eg.sketch_group.id,
fillet_or_chamfers: eg.fillet_or_chamfers.iter().map(|foc| foc.id()).collect(),
}
}
}
/// A fillet or a chamfer. /// A fillet or a chamfer.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
@ -1621,7 +1690,13 @@ impl ExecutorContext {
} else { } else {
Default::default() Default::default()
}; };
self.inner_execute(program, &mut memory, crate::executor::BodyType::Root) let mut dynamic_state = DynamicState::default();
self.inner_execute(
program,
&mut memory,
&mut dynamic_state,
crate::executor::BodyType::Root,
)
.await .await
} }
@ -1631,6 +1706,7 @@ impl ExecutorContext {
&self, &self,
program: &crate::ast::types::Program, program: &crate::ast::types::Program,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &mut DynamicState,
body_type: BodyType, body_type: BodyType,
) -> Result<ProgramMemory, KclError> { ) -> Result<ProgramMemory, KclError> {
let pipe_info = PipeInfo::default(); let pipe_info = PipeInfo::default();
@ -1640,9 +1716,9 @@ impl ExecutorContext {
match statement { match statement {
BodyItem::ExpressionStatement(expression_statement) => { BodyItem::ExpressionStatement(expression_statement) => {
if let Value::PipeExpression(pipe_expr) = &expression_statement.expression { if let Value::PipeExpression(pipe_expr) = &expression_statement.expression {
pipe_expr.get_result(memory, &pipe_info, self).await?; pipe_expr.get_result(memory, dynamic_state, &pipe_info, self).await?;
} else if let Value::CallExpression(call_expr) = &expression_statement.expression { } else if let Value::CallExpression(call_expr) = &expression_statement.expression {
call_expr.execute(memory, &pipe_info, self).await?; call_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
} }
} }
BodyItem::VariableDeclaration(variable_declaration) => { BodyItem::VariableDeclaration(variable_declaration) => {
@ -1655,6 +1731,7 @@ impl ExecutorContext {
.arg_into_mem_item( .arg_into_mem_item(
&declaration.init, &declaration.init,
memory, memory,
dynamic_state,
&pipe_info, &pipe_info,
&metadata, &metadata,
StatementKind::Declaration { name: &var_name }, StatementKind::Declaration { name: &var_name },
@ -1665,11 +1742,11 @@ impl ExecutorContext {
} }
BodyItem::ReturnStatement(return_statement) => match &return_statement.argument { BodyItem::ReturnStatement(return_statement) => match &return_statement.argument {
Value::BinaryExpression(bin_expr) => { Value::BinaryExpression(bin_expr) => {
let result = bin_expr.get_result(memory, &pipe_info, self).await?; let result = bin_expr.get_result(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::UnaryExpression(unary_expr) => { Value::UnaryExpression(unary_expr) => {
let result = unary_expr.get_result(memory, &pipe_info, self).await?; let result = unary_expr.get_result(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::Identifier(identifier) => { Value::Identifier(identifier) => {
@ -1683,15 +1760,15 @@ impl ExecutorContext {
memory.return_ = Some(ProgramReturn::Value(tag.into())); memory.return_ = Some(ProgramReturn::Value(tag.into()));
} }
Value::ArrayExpression(array_expr) => { Value::ArrayExpression(array_expr) => {
let result = array_expr.execute(memory, &pipe_info, self).await?; let result = array_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::ObjectExpression(obj_expr) => { Value::ObjectExpression(obj_expr) => {
let result = obj_expr.execute(memory, &pipe_info, self).await?; let result = obj_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::CallExpression(call_expr) => { Value::CallExpression(call_expr) => {
let result = call_expr.execute(memory, &pipe_info, self).await?; let result = call_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::MemberExpression(member_expr) => { Value::MemberExpression(member_expr) => {
@ -1699,7 +1776,7 @@ impl ExecutorContext {
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::PipeExpression(pipe_expr) => { Value::PipeExpression(pipe_expr) => {
let result = pipe_expr.get_result(memory, &pipe_info, self).await?; let result = pipe_expr.get_result(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::PipeSubstitution(_) => {} Value::PipeSubstitution(_) => {}
@ -1730,6 +1807,7 @@ impl ExecutorContext {
&self, &self,
init: &Value, init: &Value,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
metadata: &Metadata, metadata: &Metadata,
statement_kind: StatementKind<'a>, statement_kind: StatementKind<'a>,
@ -1742,13 +1820,18 @@ impl ExecutorContext {
let value = memory.get(&identifier.name, identifier.into())?; let value = memory.get(&identifier.name, identifier.into())?;
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => binary_expression.get_result(memory, pipe_info, self).await?, Value::BinaryExpression(binary_expression) => {
binary_expression
.get_result(memory, dynamic_state, pipe_info, self)
.await?
}
Value::FunctionExpression(function_expression) => { Value::FunctionExpression(function_expression) => {
let mem_func = force_memory_function( let mem_func = force_memory_function(
|args: Vec<MemoryItem>, |args: Vec<MemoryItem>,
memory: ProgramMemory, memory: ProgramMemory,
function_expression: Box<FunctionExpression>, function_expression: Box<FunctionExpression>,
_metadata: Vec<Metadata>, _metadata: Vec<Metadata>,
mut dynamic_state: DynamicState,
ctx: ExecutorContext| { ctx: ExecutorContext| {
Box::pin(async move { Box::pin(async move {
// Create a new environment to execute the function // Create a new environment to execute the function
@ -1762,7 +1845,12 @@ impl ExecutorContext {
let mut fn_memory = assign_args_to_params(&function_expression, args, body_memory)?; let mut fn_memory = assign_args_to_params(&function_expression, args, body_memory)?;
let result = ctx let result = ctx
.inner_execute(&function_expression.body, &mut fn_memory, BodyType::Block) .inner_execute(
&function_expression.body,
&mut fn_memory,
&mut dynamic_state,
BodyType::Block,
)
.await?; .await?;
Ok(result.return_) Ok(result.return_)
@ -1779,8 +1867,14 @@ impl ExecutorContext {
memory: Box::new(memory.clone()), memory: Box::new(memory.clone()),
} }
} }
Value::CallExpression(call_expression) => call_expression.execute(memory, pipe_info, self).await?, Value::CallExpression(call_expression) => {
Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, self).await?, call_expression.execute(memory, dynamic_state, pipe_info, self).await?
}
Value::PipeExpression(pipe_expression) => {
pipe_expression
.get_result(memory, dynamic_state, pipe_info, self)
.await?
}
Value::PipeSubstitution(pipe_substitution) => match statement_kind { Value::PipeSubstitution(pipe_substitution) => match statement_kind {
StatementKind::Declaration { name } => { StatementKind::Declaration { name } => {
let message = format!( let message = format!(
@ -1802,10 +1896,20 @@ impl ExecutorContext {
} }
}, },
}, },
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, self).await?, Value::ArrayExpression(array_expression) => {
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, self).await?, array_expression.execute(memory, dynamic_state, pipe_info, self).await?
}
Value::ObjectExpression(object_expression) => {
object_expression
.execute(memory, dynamic_state, pipe_info, self)
.await?
}
Value::MemberExpression(member_expression) => member_expression.get_result(memory)?, Value::MemberExpression(member_expression) => member_expression.get_result(memory)?,
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, self).await?, Value::UnaryExpression(unary_expression) => {
unary_expression
.get_result(memory, dynamic_state, pipe_info, self)
.await?
}
}; };
Ok(item) Ok(item)
} }

View File

@ -3,13 +3,14 @@ use schemars::JsonSchema;
use crate::{ use crate::{
ast::types::FunctionExpression, ast::types::FunctionExpression,
errors::KclError, errors::KclError,
executor::{ExecutorContext, MemoryFunction, MemoryItem, Metadata, ProgramMemory, ProgramReturn}, executor::{DynamicState, ExecutorContext, MemoryFunction, MemoryItem, Metadata, ProgramMemory, ProgramReturn},
}; };
/// A function being used as a parameter into a stdlib function. /// A function being used as a parameter into a stdlib function.
pub struct FunctionParam<'a> { pub struct FunctionParam<'a> {
pub inner: &'a MemoryFunction, pub inner: &'a MemoryFunction,
pub memory: ProgramMemory, pub memory: ProgramMemory,
pub dynamic_state: DynamicState,
pub fn_expr: Box<FunctionExpression>, pub fn_expr: Box<FunctionExpression>,
pub meta: Vec<Metadata>, pub meta: Vec<Metadata>,
pub ctx: ExecutorContext, pub ctx: ExecutorContext,
@ -22,6 +23,7 @@ impl<'a> FunctionParam<'a> {
self.memory.clone(), self.memory.clone(),
self.fn_expr.clone(), self.fn_expr.clone(),
self.meta.clone(), self.meta.clone(),
self.dynamic_state.clone(),
self.ctx.clone(), self.ctx.clone(),
) )
.await .await

View File

@ -8,8 +8,8 @@ use crate::{
ast::types::{parse_json_number_as_f64, TagDeclarator}, ast::types::{parse_json_number_as_f64, TagDeclarator},
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
executor::{ executor::{
ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata, ProgramMemory, DynamicState, ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata,
SketchGroup, SketchGroupSet, SketchSurface, SourceRange, TagIdentifier, ProgramMemory, SketchGroup, SketchGroupSet, SketchSurface, SourceRange, TagIdentifier,
}, },
}; };
@ -19,6 +19,7 @@ pub struct Args {
pub source_range: SourceRange, pub source_range: SourceRange,
pub ctx: ExecutorContext, pub ctx: ExecutorContext,
pub current_program_memory: ProgramMemory, pub current_program_memory: ProgramMemory,
pub dynamic_state: DynamicState,
} }
impl Args { impl Args {
@ -27,12 +28,14 @@ impl Args {
source_range: SourceRange, source_range: SourceRange,
ctx: ExecutorContext, ctx: ExecutorContext,
current_program_memory: ProgramMemory, current_program_memory: ProgramMemory,
dynamic_state: DynamicState,
) -> Self { ) -> Self {
Self { Self {
args, args,
source_range, source_range,
ctx, ctx,
current_program_memory, current_program_memory,
dynamic_state,
} }
} }
@ -130,6 +133,10 @@ impl Args {
.iter() .iter()
.flat_map(|eg| eg.get_all_fillet_or_chamfer_ids()), .flat_map(|eg| eg.get_all_fillet_or_chamfer_ids()),
); );
ids.extend(
self.dynamic_state
.fillet_or_chamfer_ids_on_sketch_group(sketch_group_id),
);
traversed_sketch_groups.push(sketch_group_id); traversed_sketch_groups.push(sketch_group_id);
} }

View File

@ -88,6 +88,7 @@ pub async fn pattern_transform(args: Args) -> Result<MemoryItem, KclError> {
meta: vec![args.source_range.into()], meta: vec![args.source_range.into()],
ctx: args.ctx.clone(), ctx: args.ctx.clone(),
memory: *transform.memory, memory: *transform.memory,
dynamic_state: args.dynamic_state.clone(),
}, },
extr, extr,
&args, &args,

View File

@ -24,7 +24,7 @@ const plumbus1 =
|> extrude(plumbusLen, %) |> extrude(plumbusLen, %)
|> fillet({ |> fillet({
radius: 5, radius: 5,
tags: [c1.tags.arc_tag, getOppositeEdge(c1.tags.arc_tag)] tags: [c1.tags.arc_tag]
}, %) }, %)
const c2 = circl(200, a) const c2 = circl(200, a)
const plumbus0 = const plumbus0 =
@ -32,7 +32,7 @@ const plumbus0 =
|> extrude(plumbusLen, %) |> extrude(plumbusLen, %)
|> fillet({ |> fillet({
radius: 5, radius: 5,
tags: [c2.tags.arc_tag, getOppositeEdge(c2.tags.arc_tag)] tags: [c2.tags.arc_tag]
}, %) }, %)

View File

@ -97,7 +97,6 @@ async fn serial_test_pipe_as_arg() {
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
#[ignore] // We need to figure out why this broke even using scoped tags isn't working.
async fn serial_test_pentagon_fillet_sugar() { async fn serial_test_pentagon_fillet_sugar() {
let code = include_str!("inputs/pentagon_fillet_sugar.kcl"); let code = include_str!("inputs/pentagon_fillet_sugar.kcl");
let result = execute_and_snapshot(code, UnitLength::Cm).await.unwrap(); let result = execute_and_snapshot(code, UnitLength::Cm).await.unwrap();
@ -1701,7 +1700,6 @@ const part002 = startSketchOn(part001, 'end')
} }
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
#[ignore] // We need to figure out why this broke even using scoped tags isn't working.
async fn serial_test_plumbus_fillets() { async fn serial_test_plumbus_fillets() {
let code = r#"fn make_circle = (ext, face, pos, radius) => { let code = r#"fn make_circle = (ext, face, pos, radius) => {
const sg = startSketchOn(ext, face) const sg = startSketchOn(ext, face)
@ -1748,7 +1746,7 @@ const plumbus0 = circle0
|> extrude(10, %) |> extrude(10, %)
|> fillet({ |> fillet({
radius: 0.5, radius: 0.5,
tags: [circle0.tags.arc1, getOppositeEdge(circle0.tags.arc1)] tags: [circle0.tags.arc1]
}, %) }, %)
const circle1 = make_circle(p, p.sketchGroup.tags.b, [0, 0], 2.5) const circle1 = make_circle(p, p.sketchGroup.tags.b, [0, 0], 2.5)
@ -1756,7 +1754,7 @@ const plumbus1 = circle1
|> extrude(10, %) |> extrude(10, %)
|> fillet({ |> fillet({
radius: 0.5, radius: 0.5,
tags: [circle1.tags.arc1, getOppositeEdge(circle1.tags.arc1)] tags: [circle1.tags.arc1]
}, %) }, %)
"#; "#;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 131 KiB