Use proper envs for Rust functions (#7623)
This commit is contained in:
@ -401,7 +401,7 @@ impl FunctionDefinition<'_> {
|
||||
impl FunctionBody<'_> {
|
||||
fn prep_mem(&self, exec_state: &mut ExecState) {
|
||||
match self {
|
||||
FunctionBody::Rust(_) => exec_state.mut_stack().push_new_env_for_rust_call(),
|
||||
FunctionBody::Rust(_) => exec_state.mut_stack().push_new_root_env(true),
|
||||
FunctionBody::Kcl(_, memory) => exec_state.mut_stack().push_new_env_for_call(*memory),
|
||||
}
|
||||
}
|
||||
|
@ -541,22 +541,6 @@ impl Stack {
|
||||
self.push_new_env_for_call(snapshot);
|
||||
}
|
||||
|
||||
/// Push a new stack frame on to the call stack for callees which should not read or write
|
||||
/// from memory.
|
||||
///
|
||||
/// This is suitable for calling standard library functions or other functions written in Rust
|
||||
/// which will use 'Rust memory' rather than KCL's memory and cannot reach into the wider
|
||||
/// environment.
|
||||
///
|
||||
/// Trying to read or write from this environment will panic with an index out of bounds.
|
||||
pub fn push_new_env_for_rust_call(&mut self) {
|
||||
self.call_stack.push(self.current_env);
|
||||
// Rust functions shouldn't try to set or access anything in their environment, so don't
|
||||
// waste time and space on a new env. Using usize::MAX means we'll get an overflow if we
|
||||
// try to access anything rather than a silent error.
|
||||
self.current_env = EnvironmentRef(usize::MAX, 0);
|
||||
}
|
||||
|
||||
/// Push a new stack frame on to the call stack with no connection to a parent environment.
|
||||
///
|
||||
/// Suitable for executing a separate module.
|
||||
@ -683,7 +667,7 @@ impl Stack {
|
||||
env.contains_key(var)
|
||||
}
|
||||
|
||||
/// Get a key from the first KCL (i.e., non-Rust) stack frame on the call stack.
|
||||
/// Get a key from the first stack frame on the call stack.
|
||||
pub fn get_from_call_stack(&self, key: &str, source_range: SourceRange) -> Result<(usize, &KclValue), KclError> {
|
||||
if !self.current_env.skip_env() {
|
||||
return Ok((self.current_env.1, self.get(key, source_range)?));
|
||||
@ -695,7 +679,7 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
unreachable!("It can't be Rust frames all the way down");
|
||||
unreachable!("No frames on the stack?");
|
||||
}
|
||||
|
||||
/// Iterate over all keys in the current environment which satisfy the provided predicate.
|
||||
@ -1217,24 +1201,6 @@ mod test {
|
||||
assert_get_from(mem, "c", 5, callee);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rust_env() {
|
||||
let mem = &mut Stack::new_for_tests();
|
||||
mem.add("a".to_owned(), val(1), sr()).unwrap();
|
||||
mem.add("b".to_owned(), val(3), sr()).unwrap();
|
||||
let sn = mem.snapshot();
|
||||
|
||||
mem.push_new_env_for_rust_call();
|
||||
mem.push_new_env_for_call(sn);
|
||||
assert_get(mem, "b", 3);
|
||||
mem.add("b".to_owned(), val(4), sr()).unwrap();
|
||||
assert_get(mem, "b", 4);
|
||||
|
||||
mem.pop_env();
|
||||
mem.pop_env();
|
||||
assert_get(mem, "b", 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deep_call_env() {
|
||||
let mem = &mut Stack::new_for_tests();
|
||||
|
@ -1920,6 +1920,22 @@ shape = layer() |> patternTransform(instances = 10, transform = transform)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn pass_std_to_std() {
|
||||
let ast = r#"sketch001 = startSketchOn(XY)
|
||||
profile001 = circle(sketch001, center = [0, 0], radius = 2)
|
||||
extrude001 = extrude(profile001, length = 5)
|
||||
extrudes = patternLinear3d(
|
||||
extrude001,
|
||||
instances = 3,
|
||||
distance = 5,
|
||||
axis = [1, 1, 0],
|
||||
)
|
||||
clone001 = map(extrudes, f = clone)
|
||||
"#;
|
||||
parse_execute(ast).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_zero_param_fn() {
|
||||
let ast = r#"sigmaAllow = 35000 // psi
|
||||
|
Reference in New Issue
Block a user