Add set_value to Scope.
This commit is contained in:
parent
44d6a5e466
commit
c4498d147d
20
README.md
20
README.md
@ -733,12 +733,14 @@ fn main() -> Result<(), EvalAltResult>
|
|||||||
// First create the state
|
// First create the state
|
||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
|
|
||||||
// Then push some initialized variables into the state
|
// Then push (i.e. add) some initialized variables into the state.
|
||||||
// NOTE: Remember the system number types in Rhai are i64 (i32 if 'only_i32') ond f64.
|
// Remember the system number types in Rhai are i64 (i32 if 'only_i32') ond f64.
|
||||||
// Better stick to them or it gets hard working with the script.
|
// Better stick to them or it gets hard working with the script.
|
||||||
scope.push("y", 42_i64);
|
scope.push("y", 42_i64);
|
||||||
scope.push("z", 999_i64);
|
scope.push("z", 999_i64);
|
||||||
scope.push("s", "hello, world!".to_string()); // remember to use 'String', not '&str'
|
|
||||||
|
// 'set_value' adds a variable when one doesn't exist
|
||||||
|
scope.set_value("s", "hello, world!".to_string()); // remember to use 'String', not '&str'
|
||||||
|
|
||||||
// First invocation
|
// First invocation
|
||||||
engine.eval_with_scope::<()>(&mut scope, r"
|
engine.eval_with_scope::<()>(&mut scope, r"
|
||||||
@ -749,10 +751,14 @@ fn main() -> Result<(), EvalAltResult>
|
|||||||
// Second invocation using the same state
|
// Second invocation using the same state
|
||||||
let result = engine.eval_with_scope::<i64>(&mut scope, "x")?;
|
let result = engine.eval_with_scope::<i64>(&mut scope, "x")?;
|
||||||
|
|
||||||
println!("result: {}", result); // prints 979
|
println!("result: {}", result); // prints 979
|
||||||
|
|
||||||
// Variable y is changed in the script
|
// Variable y is changed in the script - read it with 'get_value'
|
||||||
assert_eq!(scope.get_value::<i64>("y").expect("variable x should exist"), 1);
|
assert_eq!(scope.get_value::<i64>("y").expect("variable y should exist"), 1);
|
||||||
|
|
||||||
|
// We can modify scope variables directly with 'set_value'
|
||||||
|
scope.set_value("y", 42_i64);
|
||||||
|
assert_eq!(scope.get_value::<i64>("y").expect("variable y should exist"), 42);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
32
src/scope.rs
32
src/scope.rs
@ -179,16 +179,44 @@ impl<'a> Scope<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the value of an entry in the Scope, starting from the last.
|
/// Get the value of an entry in the Scope, starting from the last.
|
||||||
pub fn get_value<T: Any + Clone>(&self, key: &str) -> Option<T> {
|
pub fn get_value<T: Any + Clone>(&self, name: &str) -> Option<T> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev() // Always search a Scope in reverse order
|
.rev() // Always search a Scope in reverse order
|
||||||
.find(|(_, Entry { name, .. })| name == key)
|
.find(|(_, Entry { name: key, .. })| name == key)
|
||||||
.and_then(|(_, Entry { value, .. })| value.downcast_ref::<T>())
|
.and_then(|(_, Entry { value, .. })| value.downcast_ref::<T>())
|
||||||
.map(T::clone)
|
.map(T::clone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the value of the named variable.
|
||||||
|
/// Search starts from the last, and only the last variable matching the specified name is updated.
|
||||||
|
/// If no variable matching the specified name is found, a new variable is added.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics when trying to update the value of a constant.
|
||||||
|
pub fn set_value<T: Any + Clone>(&mut self, name: &'a str, value: T) {
|
||||||
|
match self.get(name) {
|
||||||
|
Some((
|
||||||
|
EntryRef {
|
||||||
|
typ: EntryType::Constant,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
_,
|
||||||
|
)) => panic!("variable {} is constant", name),
|
||||||
|
Some((
|
||||||
|
EntryRef {
|
||||||
|
index,
|
||||||
|
typ: EntryType::Normal,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
_,
|
||||||
|
)) => self.0.get_mut(index).unwrap().value = value.into_dynamic(),
|
||||||
|
None => self.push(name, value.into_dynamic()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to an entry in the Scope.
|
/// Get a mutable reference to an entry in the Scope.
|
||||||
pub(crate) fn get_mut(&mut self, key: EntryRef) -> &mut Dynamic {
|
pub(crate) fn get_mut(&mut self, key: EntryRef) -> &mut Dynamic {
|
||||||
let entry = self.0.get_mut(key.index).expect("invalid index in Scope");
|
let entry = self.0.get_mut(key.index).expect("invalid index in Scope");
|
||||||
|
@ -9,8 +9,12 @@ fn test_var_scope() -> Result<(), EvalAltResult> {
|
|||||||
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "x")?, 9);
|
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "x")?, 9);
|
||||||
engine.eval_with_scope::<()>(&mut scope, "x = x + 1; x = x + 2;")?;
|
engine.eval_with_scope::<()>(&mut scope, "x = x + 1; x = x + 2;")?;
|
||||||
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "x")?, 12);
|
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "x")?, 12);
|
||||||
|
|
||||||
|
scope.set_value("x", 42 as INT);
|
||||||
|
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "x")?, 42);
|
||||||
|
|
||||||
engine.eval_with_scope::<()>(&mut scope, "{let x = 3}")?;
|
engine.eval_with_scope::<()>(&mut scope, "{let x = 3}")?;
|
||||||
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "x")?, 12);
|
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "x")?, 42);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user