Fix shared variable assignment.

This commit is contained in:
Stephen Chung 2022-06-26 18:09:15 +08:00
parent d9875ff81c
commit 0031678cd4
5 changed files with 28 additions and 19 deletions

View File

@ -56,12 +56,7 @@ impl Engine {
.shared_lib() .shared_lib()
.iter_fn() .iter_fn()
.filter(|f| f.func.is_script()) .filter(|f| f.func.is_script())
.map(|f| { .map(|f| f.func.get_script_fn_def().unwrap().clone())
f.func
.get_script_fn_def()
.expect("script-defined function")
.clone()
})
.collect(); .collect();
crate::optimizer::optimize_into_ast( crate::optimizer::optimize_into_ast(

View File

@ -146,7 +146,7 @@ impl Engine {
let target_is_shared = false; let target_is_shared = false;
if target_is_shared { if target_is_shared {
lock_guard = target.write_lock::<Dynamic>().expect("`Dynamic`"); lock_guard = target.write_lock::<Dynamic>().unwrap();
lhs_ptr_inner = &mut *lock_guard; lhs_ptr_inner = &mut *lock_guard;
} else { } else {
lhs_ptr_inner = &mut *target; lhs_ptr_inner = &mut *target;
@ -181,7 +181,20 @@ impl Engine {
} }
} else { } else {
// Normal assignment // Normal assignment
*target.as_mut() = new_val;
#[cfg(not(feature = "no_closure"))]
if target.is_shared() {
// Handle case where target is a `Dynamic` shared value
// (returned by a variable resolver, for example)
*target.write_lock::<Dynamic>().unwrap() = new_val;
} else {
*target.as_mut() = new_val;
}
#[cfg(feature = "no_closure")]
{
*target.as_mut() = new_val;
}
} }
target.propagate_changed_value(op_info.pos) target.propagate_changed_value(op_info.pos)
@ -251,8 +264,8 @@ impl Engine {
let var_name = lhs.get_variable_name(false).expect("`Expr::Variable`"); let var_name = lhs.get_variable_name(false).expect("`Expr::Variable`");
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
// Temp results from expressions are flattened so should never be shared. // Also handle case where target is a `Dynamic` shared value
// A shared value may be provided by a variable resolver, however. // (returned by a variable resolver, for example)
let is_temp_result = !lhs_ptr.is_ref() && !lhs_ptr.is_shared(); let is_temp_result = !lhs_ptr.is_ref() && !lhs_ptr.is_shared();
#[cfg(feature = "no_closure")] #[cfg(feature = "no_closure")]
let is_temp_result = !lhs_ptr.is_ref(); let is_temp_result = !lhs_ptr.is_ref();

View File

@ -578,7 +578,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
// Then check ranges // Then check ranges
if value.is::<INT>() && !ranges.is_empty() { if value.is::<INT>() && !ranges.is_empty() {
let value = value.as_int().expect("`INT`"); let value = value.as_int().unwrap();
// Only one range or all ranges without conditions // Only one range or all ranges without conditions
if ranges.len() == 1 if ranges.len() == 1

View File

@ -1520,7 +1520,7 @@ fn get_next_token_inner(
} }
#[cfg(any(not(feature = "no_float"), feature = "decimal"))] #[cfg(any(not(feature = "no_float"), feature = "decimal"))]
'.' => { '.' => {
stream.get_next().expect("`.`"); stream.get_next().unwrap();
// Check if followed by digits or something that cannot start a property name // Check if followed by digits or something that cannot start a property name
match stream.peek_next().unwrap_or('\0') { match stream.peek_next().unwrap_or('\0') {
@ -1567,7 +1567,7 @@ fn get_next_token_inner(
'+' | '-' => { '+' | '-' => {
result.push(next_char); result.push(next_char);
pos.advance(); pos.advance();
result.push(stream.get_next().expect("`+` or `-`")); result.push(stream.get_next().unwrap());
pos.advance(); pos.advance();
} }
// Not a floating-point number // Not a floating-point number

View File

@ -196,13 +196,14 @@ fn test_var_resolver() -> Result<(), Box<EvalAltResult>> {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
{ {
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "HELLO")?, 1); assert_eq!(engine.eval::<INT>("HELLO")?, 1);
*base.write_lock::<INT>().unwrap() = 42; *base.write_lock::<INT>().unwrap() = 42;
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "HELLO")?, 42); assert_eq!(engine.eval::<INT>("HELLO")?, 42);
assert_eq!( engine.run("HELLO = 123")?;
engine.eval_with_scope::<INT>(&mut scope, "HELLO = HELLO * 2; HELLO")?, assert_eq!(base.as_int().unwrap(), 123);
84 assert_eq!(engine.eval::<INT>("HELLO = HELLO + 1; HELLO")?, 124);
); assert_eq!(engine.eval::<INT>("HELLO = HELLO * 2; HELLO")?, 248);
assert_eq!(base.as_int().unwrap(), 248);
} }
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "chameleon")?, 1); assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "chameleon")?, 1);