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:
@ -23,8 +23,8 @@ use crate::{
|
||||
docs::StdLibFn,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{
|
||||
BodyType, ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange, StatementKind,
|
||||
TagEngineInfo, TagIdentifier, UserVal,
|
||||
BodyType, DynamicState, ExecutorContext, MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange,
|
||||
StatementKind, TagEngineInfo, TagIdentifier, UserVal,
|
||||
},
|
||||
parser::PIPE_OPERATOR,
|
||||
std::{kcl_stdlib::KclStdLibFn, FunctionKind},
|
||||
@ -918,6 +918,7 @@ impl BinaryPart {
|
||||
pub async fn get_result(
|
||||
&self,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
pipe_info: &PipeInfo,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<MemoryItem, KclError> {
|
||||
@ -928,10 +929,16 @@ impl BinaryPart {
|
||||
Ok(value.clone())
|
||||
}
|
||||
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),
|
||||
}
|
||||
}
|
||||
@ -1311,6 +1318,7 @@ impl CallExpression {
|
||||
pub async fn execute(
|
||||
&self,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
pipe_info: &PipeInfo,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<MemoryItem, KclError> {
|
||||
@ -1323,7 +1331,14 @@ impl CallExpression {
|
||||
source_range: SourceRange([arg.start(), arg.end()]),
|
||||
};
|
||||
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?;
|
||||
fn_args.push(result);
|
||||
}
|
||||
@ -1331,7 +1346,8 @@ impl CallExpression {
|
||||
match ctx.stdlib.get_either(&self.callee.name) {
|
||||
FunctionKind::Core(func) => {
|
||||
// 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?;
|
||||
|
||||
// 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
|
||||
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,
|
||||
Err(err) => {
|
||||
// We need to override the source ranges so we don't get the embedded kcl
|
||||
@ -1456,7 +1477,11 @@ impl CallExpression {
|
||||
}
|
||||
FunctionKind::UserDefined => {
|
||||
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.
|
||||
e.add_source_ranges(vec![self.into()])
|
||||
})?;
|
||||
@ -2295,6 +2320,7 @@ impl ArrayExpression {
|
||||
pub async fn execute(
|
||||
&self,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
pipe_info: &PipeInfo,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<MemoryItem, KclError> {
|
||||
@ -2310,13 +2336,29 @@ impl ArrayExpression {
|
||||
value.clone()
|
||||
}
|
||||
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) => {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
|
||||
@ -2465,6 +2507,7 @@ impl ObjectExpression {
|
||||
pub async fn execute(
|
||||
&self,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
pipe_info: &PipeInfo,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<MemoryItem, KclError> {
|
||||
@ -2479,13 +2522,29 @@ impl ObjectExpression {
|
||||
value.clone()
|
||||
}
|
||||
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::PipeSubstitution(pipe_substitution) => {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
@ -2947,11 +3006,20 @@ impl BinaryExpression {
|
||||
pub async fn get_result(
|
||||
&self,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
pipe_info: &PipeInfo,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<MemoryItem, KclError> {
|
||||
let left_json_value = self.left.get_result(memory, pipe_info, ctx).await?.get_json_value()?;
|
||||
let right_json_value = self.right.get_result(memory, pipe_info, ctx).await?.get_json_value()?;
|
||||
let left_json_value = self
|
||||
.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.
|
||||
if self.operator == BinaryOperator::Add {
|
||||
@ -3156,13 +3224,14 @@ impl UnaryExpression {
|
||||
pub async fn get_result(
|
||||
&self,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
pipe_info: &PipeInfo,
|
||||
ctx: &ExecutorContext,
|
||||
) -> Result<MemoryItem, KclError> {
|
||||
let num = parse_json_number_as_f64(
|
||||
&self
|
||||
.argument
|
||||
.get_result(memory, pipe_info, ctx)
|
||||
.get_result(memory, dynamic_state, pipe_info, ctx)
|
||||
.await?
|
||||
.get_json_value()?,
|
||||
self.into(),
|
||||
@ -3333,10 +3402,11 @@ impl PipeExpression {
|
||||
pub async fn get_result(
|
||||
&self,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
pipe_info: &PipeInfo,
|
||||
ctx: &ExecutorContext,
|
||||
) -> 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.
|
||||
@ -3350,6 +3420,7 @@ impl PipeExpression {
|
||||
#[async_recursion::async_recursion]
|
||||
async fn execute_pipe_body(
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
body: &[Value],
|
||||
pipe_info: &PipeInfo,
|
||||
source_range: SourceRange,
|
||||
@ -3370,7 +3441,14 @@ async fn execute_pipe_body(
|
||||
source_range: SourceRange([first.start(), first.end()]),
|
||||
};
|
||||
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?;
|
||||
// Now that we've evaluated the first child expression in the pipeline, following child expressions
|
||||
// should use the previous child expression for %.
|
||||
@ -3381,9 +3459,15 @@ async fn execute_pipe_body(
|
||||
for expression in body {
|
||||
let output = match 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(),
|
||||
_ => {
|
||||
// Return an error this should not happen.
|
||||
|
@ -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)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase", untagged)]
|
||||
@ -623,6 +667,7 @@ pub type MemoryFunction =
|
||||
memory: ProgramMemory,
|
||||
expression: Box<FunctionExpression>,
|
||||
metadata: Vec<Metadata>,
|
||||
dynamic_state: DynamicState,
|
||||
ctx: ExecutorContext,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>;
|
||||
|
||||
@ -632,6 +677,7 @@ fn force_memory_function<
|
||||
ProgramMemory,
|
||||
Box<FunctionExpression>,
|
||||
Vec<Metadata>,
|
||||
DynamicState,
|
||||
ExecutorContext,
|
||||
) -> 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(
|
||||
&self,
|
||||
args: Vec<MemoryItem>,
|
||||
dynamic_state: &DynamicState,
|
||||
ctx: ExecutorContext,
|
||||
) -> Result<Option<ProgramReturn>, KclError> {
|
||||
let MemoryItem::Function {
|
||||
@ -825,6 +872,7 @@ impl MemoryItem {
|
||||
closure_memory.as_ref().clone(),
|
||||
expression.clone(),
|
||||
meta.clone(),
|
||||
dynamic_state.clone(),
|
||||
ctx,
|
||||
)
|
||||
.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.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
@ -1621,7 +1690,13 @@ impl ExecutorContext {
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
@ -1631,6 +1706,7 @@ impl ExecutorContext {
|
||||
&self,
|
||||
program: &crate::ast::types::Program,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &mut DynamicState,
|
||||
body_type: BodyType,
|
||||
) -> Result<ProgramMemory, KclError> {
|
||||
let pipe_info = PipeInfo::default();
|
||||
@ -1640,9 +1716,9 @@ impl ExecutorContext {
|
||||
match statement {
|
||||
BodyItem::ExpressionStatement(expression_statement) => {
|
||||
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 {
|
||||
call_expr.execute(memory, &pipe_info, self).await?;
|
||||
call_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
|
||||
}
|
||||
}
|
||||
BodyItem::VariableDeclaration(variable_declaration) => {
|
||||
@ -1655,6 +1731,7 @@ impl ExecutorContext {
|
||||
.arg_into_mem_item(
|
||||
&declaration.init,
|
||||
memory,
|
||||
dynamic_state,
|
||||
&pipe_info,
|
||||
&metadata,
|
||||
StatementKind::Declaration { name: &var_name },
|
||||
@ -1665,11 +1742,11 @@ impl ExecutorContext {
|
||||
}
|
||||
BodyItem::ReturnStatement(return_statement) => match &return_statement.argument {
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
Value::Identifier(identifier) => {
|
||||
@ -1683,15 +1760,15 @@ impl ExecutorContext {
|
||||
memory.return_ = Some(ProgramReturn::Value(tag.into()));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
Value::MemberExpression(member_expr) => {
|
||||
@ -1699,7 +1776,7 @@ impl ExecutorContext {
|
||||
memory.return_ = Some(ProgramReturn::Value(result));
|
||||
}
|
||||
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));
|
||||
}
|
||||
Value::PipeSubstitution(_) => {}
|
||||
@ -1730,6 +1807,7 @@ impl ExecutorContext {
|
||||
&self,
|
||||
init: &Value,
|
||||
memory: &mut ProgramMemory,
|
||||
dynamic_state: &DynamicState,
|
||||
pipe_info: &PipeInfo,
|
||||
metadata: &Metadata,
|
||||
statement_kind: StatementKind<'a>,
|
||||
@ -1742,13 +1820,18 @@ impl ExecutorContext {
|
||||
let value = memory.get(&identifier.name, identifier.into())?;
|
||||
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) => {
|
||||
let mem_func = force_memory_function(
|
||||
|args: Vec<MemoryItem>,
|
||||
memory: ProgramMemory,
|
||||
function_expression: Box<FunctionExpression>,
|
||||
_metadata: Vec<Metadata>,
|
||||
mut dynamic_state: DynamicState,
|
||||
ctx: ExecutorContext| {
|
||||
Box::pin(async move {
|
||||
// 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 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?;
|
||||
|
||||
Ok(result.return_)
|
||||
@ -1779,8 +1867,14 @@ impl ExecutorContext {
|
||||
memory: Box::new(memory.clone()),
|
||||
}
|
||||
}
|
||||
Value::CallExpression(call_expression) => call_expression.execute(memory, pipe_info, self).await?,
|
||||
Value::PipeExpression(pipe_expression) => pipe_expression.get_result(memory, pipe_info, self).await?,
|
||||
Value::CallExpression(call_expression) => {
|
||||
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 {
|
||||
StatementKind::Declaration { name } => {
|
||||
let message = format!(
|
||||
@ -1802,10 +1896,20 @@ impl ExecutorContext {
|
||||
}
|
||||
},
|
||||
},
|
||||
Value::ArrayExpression(array_expression) => array_expression.execute(memory, pipe_info, self).await?,
|
||||
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, self).await?,
|
||||
Value::ArrayExpression(array_expression) => {
|
||||
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::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)
|
||||
}
|
||||
|
@ -3,13 +3,14 @@ use schemars::JsonSchema;
|
||||
use crate::{
|
||||
ast::types::FunctionExpression,
|
||||
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.
|
||||
pub struct FunctionParam<'a> {
|
||||
pub inner: &'a MemoryFunction,
|
||||
pub memory: ProgramMemory,
|
||||
pub dynamic_state: DynamicState,
|
||||
pub fn_expr: Box<FunctionExpression>,
|
||||
pub meta: Vec<Metadata>,
|
||||
pub ctx: ExecutorContext,
|
||||
@ -22,6 +23,7 @@ impl<'a> FunctionParam<'a> {
|
||||
self.memory.clone(),
|
||||
self.fn_expr.clone(),
|
||||
self.meta.clone(),
|
||||
self.dynamic_state.clone(),
|
||||
self.ctx.clone(),
|
||||
)
|
||||
.await
|
||||
|
@ -8,8 +8,8 @@ use crate::{
|
||||
ast::types::{parse_json_number_as_f64, TagDeclarator},
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{
|
||||
ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata, ProgramMemory,
|
||||
SketchGroup, SketchGroupSet, SketchSurface, SourceRange, TagIdentifier,
|
||||
DynamicState, ExecutorContext, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, MemoryItem, Metadata,
|
||||
ProgramMemory, SketchGroup, SketchGroupSet, SketchSurface, SourceRange, TagIdentifier,
|
||||
},
|
||||
};
|
||||
|
||||
@ -19,6 +19,7 @@ pub struct Args {
|
||||
pub source_range: SourceRange,
|
||||
pub ctx: ExecutorContext,
|
||||
pub current_program_memory: ProgramMemory,
|
||||
pub dynamic_state: DynamicState,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
@ -27,12 +28,14 @@ impl Args {
|
||||
source_range: SourceRange,
|
||||
ctx: ExecutorContext,
|
||||
current_program_memory: ProgramMemory,
|
||||
dynamic_state: DynamicState,
|
||||
) -> Self {
|
||||
Self {
|
||||
args,
|
||||
source_range,
|
||||
ctx,
|
||||
current_program_memory,
|
||||
dynamic_state,
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,6 +133,10 @@ impl Args {
|
||||
.iter()
|
||||
.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);
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ pub async fn pattern_transform(args: Args) -> Result<MemoryItem, KclError> {
|
||||
meta: vec![args.source_range.into()],
|
||||
ctx: args.ctx.clone(),
|
||||
memory: *transform.memory,
|
||||
dynamic_state: args.dynamic_state.clone(),
|
||||
},
|
||||
extr,
|
||||
&args,
|
||||
|
@ -24,7 +24,7 @@ const plumbus1 =
|
||||
|> extrude(plumbusLen, %)
|
||||
|> fillet({
|
||||
radius: 5,
|
||||
tags: [c1.tags.arc_tag, getOppositeEdge(c1.tags.arc_tag)]
|
||||
tags: [c1.tags.arc_tag]
|
||||
}, %)
|
||||
const c2 = circl(200, a)
|
||||
const plumbus0 =
|
||||
@ -32,7 +32,7 @@ const plumbus0 =
|
||||
|> extrude(plumbusLen, %)
|
||||
|> fillet({
|
||||
radius: 5,
|
||||
tags: [c2.tags.arc_tag, getOppositeEdge(c2.tags.arc_tag)]
|
||||
tags: [c2.tags.arc_tag]
|
||||
}, %)
|
||||
|
||||
|
||||
|
@ -97,7 +97,6 @@ async fn serial_test_pipe_as_arg() {
|
||||
}
|
||||
|
||||
#[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() {
|
||||
let code = include_str!("inputs/pentagon_fillet_sugar.kcl");
|
||||
let result = execute_and_snapshot(code, UnitLength::Cm).await.unwrap();
|
||||
@ -1701,7 +1700,6 @@ const part002 = startSketchOn(part001, 'end')
|
||||
}
|
||||
|
||||
#[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() {
|
||||
let code = r#"fn make_circle = (ext, face, pos, radius) => {
|
||||
const sg = startSketchOn(ext, face)
|
||||
@ -1748,7 +1746,7 @@ const plumbus0 = circle0
|
||||
|> extrude(10, %)
|
||||
|> fillet({
|
||||
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)
|
||||
@ -1756,7 +1754,7 @@ const plumbus1 = circle1
|
||||
|> extrude(10, %)
|
||||
|> fillet({
|
||||
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 |
Reference in New Issue
Block a user