Allow passing in custom Scope to call_fn.
This commit is contained in:
parent
ae9a975576
commit
3f247fd695
12
README.md
12
README.md
@ -232,18 +232,22 @@ let ast = engine.compile(true,
|
|||||||
}
|
}
|
||||||
")?;
|
")?;
|
||||||
|
|
||||||
|
// A custom scope can also contain any variables/constants available to the functions
|
||||||
|
let mut scope = Scope::new();
|
||||||
|
|
||||||
// Evaluate a function defined in the script, passing arguments into the script as a tuple
|
// Evaluate a function defined in the script, passing arguments into the script as a tuple
|
||||||
// if there are more than one. Beware, arguments must be of the correct types because
|
// if there are more than one. Beware, arguments must be of the correct types because
|
||||||
// Rhai does not have built-in type conversions. If arguments of the wrong types are passed,
|
// Rhai does not have built-in type conversions. If arguments of the wrong types are passed,
|
||||||
// the Engine will not find the function.
|
// the Engine will not find the function.
|
||||||
|
|
||||||
let result: i64 = engine.call_fn(&ast, "hello", ( String::from("abc"), 123_i64 ) )?;
|
let result: i64 = engine.call_fn(&mut scope, &ast, "hello", ( String::from("abc"), 123_i64 ) )?;
|
||||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ put arguments in a tuple
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
// put arguments in a tuple
|
||||||
|
|
||||||
let result: i64 = engine.call_fn1(&ast, "hello", 123_i64)?
|
let result: i64 = engine.call_fn1(&mut scope, &ast, "hello", 123_i64)?
|
||||||
// ^^^^^^^^ use 'call_fn1' for one argument
|
// ^^^^^^^^ use 'call_fn1' for one argument
|
||||||
|
|
||||||
let result: i64 = engine.call_fn0(&ast, "hello")?
|
let result: i64 = engine.call_fn0(&mut scope, &ast, "hello")?
|
||||||
// ^^^^^^^^ use 'call_fn0' for no arguments
|
// ^^^^^^^^ use 'call_fn0' for no arguments
|
||||||
```
|
```
|
||||||
|
|
||||||
|
55
src/api.rs
55
src/api.rs
@ -857,23 +857,31 @@ impl<'e> Engine<'e> {
|
|||||||
/// # #[cfg(not(feature = "no_stdlib"))]
|
/// # #[cfg(not(feature = "no_stdlib"))]
|
||||||
/// # #[cfg(not(feature = "no_function"))]
|
/// # #[cfg(not(feature = "no_function"))]
|
||||||
/// # {
|
/// # {
|
||||||
/// use rhai::Engine;
|
/// use rhai::{Engine, Scope};
|
||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// let ast = engine.compile("fn num() { 42 }")?;
|
/// let ast = engine.compile("fn num() { 42 + foo }")?;
|
||||||
|
///
|
||||||
|
/// let mut scope = Scope::new();
|
||||||
|
/// scope.push("foo", 42_i64);
|
||||||
///
|
///
|
||||||
/// // Call the script-defined function
|
/// // Call the script-defined function
|
||||||
/// let result: i64 = engine.call_fn0(&ast, "num")?;
|
/// let result: i64 = engine.call_fn0(&mut scope, &ast, "num")?;
|
||||||
///
|
///
|
||||||
/// assert_eq!(result, 42);
|
/// assert_eq!(result, 84);
|
||||||
/// # }
|
/// # }
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub fn call_fn0<T: Any + Clone>(&mut self, ast: &AST, name: &str) -> Result<T, EvalAltResult> {
|
pub fn call_fn0<T: Any + Clone>(
|
||||||
self.call_fn_internal(ast, name, vec![])
|
&mut self,
|
||||||
|
scope: &mut Scope,
|
||||||
|
ast: &AST,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<T, EvalAltResult> {
|
||||||
|
self.call_fn_internal(scope, ast, name, vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a script function defined in an `AST` with one argument.
|
/// Call a script function defined in an `AST` with one argument.
|
||||||
@ -885,16 +893,19 @@ impl<'e> Engine<'e> {
|
|||||||
/// # #[cfg(not(feature = "no_stdlib"))]
|
/// # #[cfg(not(feature = "no_stdlib"))]
|
||||||
/// # #[cfg(not(feature = "no_function"))]
|
/// # #[cfg(not(feature = "no_function"))]
|
||||||
/// # {
|
/// # {
|
||||||
/// use rhai::Engine;
|
/// use rhai::{Engine, Scope};
|
||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// let ast = engine.compile("fn inc(x) { x + 1 }")?;
|
/// let ast = engine.compile("fn inc(x) { x + foo }")?;
|
||||||
|
///
|
||||||
|
/// let mut scope = Scope::new();
|
||||||
|
/// scope.push("foo", 42_i64);
|
||||||
///
|
///
|
||||||
/// // Call the script-defined function
|
/// // Call the script-defined function
|
||||||
/// let result: i64 = engine.call_fn1(&ast, "inc", 123_i64)?;
|
/// let result: i64 = engine.call_fn1(&mut scope, &ast, "inc", 123_i64)?;
|
||||||
///
|
///
|
||||||
/// assert_eq!(result, 124);
|
/// assert_eq!(result, 165);
|
||||||
/// # }
|
/// # }
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
@ -902,11 +913,12 @@ impl<'e> Engine<'e> {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub fn call_fn1<A: Any + Clone, T: Any + Clone>(
|
pub fn call_fn1<A: Any + Clone, T: Any + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
scope: &mut Scope,
|
||||||
ast: &AST,
|
ast: &AST,
|
||||||
name: &str,
|
name: &str,
|
||||||
arg: A,
|
arg: A,
|
||||||
) -> Result<T, EvalAltResult> {
|
) -> Result<T, EvalAltResult> {
|
||||||
self.call_fn_internal(ast, name, vec![arg.into_dynamic()])
|
self.call_fn_internal(scope, ast, name, vec![arg.into_dynamic()])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a script function defined in an `AST` with multiple arguments.
|
/// Call a script function defined in an `AST` with multiple arguments.
|
||||||
@ -918,16 +930,19 @@ impl<'e> Engine<'e> {
|
|||||||
/// # #[cfg(not(feature = "no_stdlib"))]
|
/// # #[cfg(not(feature = "no_stdlib"))]
|
||||||
/// # #[cfg(not(feature = "no_function"))]
|
/// # #[cfg(not(feature = "no_function"))]
|
||||||
/// # {
|
/// # {
|
||||||
/// use rhai::Engine;
|
/// use rhai::{Engine, Scope};
|
||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// let ast = engine.compile("fn add(x, y) { len(x) + y }")?;
|
/// let ast = engine.compile("fn add(x, y) { len(x) + y + foo }")?;
|
||||||
|
///
|
||||||
|
/// let mut scope = Scope::new();
|
||||||
|
/// scope.push("foo", 42_i64);
|
||||||
///
|
///
|
||||||
/// // Call the script-defined function
|
/// // Call the script-defined function
|
||||||
/// let result: i64 = engine.call_fn(&ast, "add", (String::from("abc"), 123_i64))?;
|
/// let result: i64 = engine.call_fn(&mut scope, &ast, "add", (String::from("abc"), 123_i64))?;
|
||||||
///
|
///
|
||||||
/// assert_eq!(result, 126);
|
/// assert_eq!(result, 168);
|
||||||
/// # }
|
/// # }
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
@ -935,26 +950,28 @@ impl<'e> Engine<'e> {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub fn call_fn<A: FuncArgs, T: Any + Clone>(
|
pub fn call_fn<A: FuncArgs, T: Any + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
scope: &mut Scope,
|
||||||
ast: &AST,
|
ast: &AST,
|
||||||
name: &str,
|
name: &str,
|
||||||
args: A,
|
args: A,
|
||||||
) -> Result<T, EvalAltResult> {
|
) -> Result<T, EvalAltResult> {
|
||||||
self.call_fn_internal(ast, name, args.into_vec())
|
self.call_fn_internal(scope, ast, name, args.into_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
fn call_fn_internal<T: Any + Clone>(
|
fn call_fn_internal<T: Any + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
scope: &mut Scope,
|
||||||
ast: &AST,
|
ast: &AST,
|
||||||
name: &str,
|
name: &str,
|
||||||
mut values: Vec<Dynamic>,
|
mut arg_values: Vec<Dynamic>,
|
||||||
) -> Result<T, EvalAltResult> {
|
) -> Result<T, EvalAltResult> {
|
||||||
let mut arg_values: Vec<_> = values.iter_mut().map(Dynamic::as_mut).collect();
|
let mut args: Vec<_> = arg_values.iter_mut().map(Dynamic::as_mut).collect();
|
||||||
|
|
||||||
self.fn_lib = Some(ast.1.clone());
|
self.fn_lib = Some(ast.1.clone());
|
||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.call_fn_raw(name, &mut arg_values, None, Position::none(), 0)?
|
.call_fn_raw(Some(scope), name, &mut args, None, Position::none(), 0)?
|
||||||
.try_cast()
|
.try_cast()
|
||||||
.map_err(|a| {
|
.map_err(|a| {
|
||||||
EvalAltResult::ErrorMismatchOutputType(
|
EvalAltResult::ErrorMismatchOutputType(
|
||||||
|
123
src/engine.rs
123
src/engine.rs
@ -435,6 +435,7 @@ impl Engine<'_> {
|
|||||||
/// Universal method for calling functions either registered with the `Engine` or written in Rhai
|
/// Universal method for calling functions either registered with the `Engine` or written in Rhai
|
||||||
pub(crate) fn call_fn_raw(
|
pub(crate) fn call_fn_raw(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
scope: Option<&mut Scope>,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
def_val: Option<&Dynamic>,
|
def_val: Option<&Dynamic>,
|
||||||
@ -444,25 +445,56 @@ impl Engine<'_> {
|
|||||||
// First search in script-defined functions (can override built-in)
|
// First search in script-defined functions (can override built-in)
|
||||||
if let Some(ref fn_lib_arc) = self.fn_lib {
|
if let Some(ref fn_lib_arc) = self.fn_lib {
|
||||||
if let Some(fn_def) = fn_lib_arc.clone().get_function(fn_name, args.len()) {
|
if let Some(fn_def) = fn_lib_arc.clone().get_function(fn_name, args.len()) {
|
||||||
let mut scope = Scope::new();
|
match scope {
|
||||||
|
// Extern scope passed in which is not empty
|
||||||
|
Some(scope) if scope.len() > 0 => {
|
||||||
|
let scope_len = scope.len();
|
||||||
|
|
||||||
scope.extend(
|
scope.extend(
|
||||||
// Put arguments into scope as variables
|
// Put arguments into scope as variables - variable name is copied
|
||||||
fn_def
|
fn_def
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.zip(args.iter().map(|x| (*x).into_dynamic()))
|
.zip(args.iter().map(|x| (*x).into_dynamic()))
|
||||||
.map(|(name, value)| (name, ScopeEntryType::Normal, value)),
|
.map(|(name, value)| (name.clone(), ScopeEntryType::Normal, value)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Evaluate the function at one higher level of call depth
|
// Evaluate the function at one higher level of call depth
|
||||||
return self.eval_stmt(&mut scope, &fn_def.body, level + 1).or_else(
|
let result = self.eval_stmt(scope, &fn_def.body, level + 1).or_else(
|
||||||
|err| match err {
|
|err| match err {
|
||||||
// Convert return statement to return value
|
// Convert return statement to return value
|
||||||
EvalAltResult::Return(x, _) => Ok(x),
|
EvalAltResult::Return(x, _) => Ok(x),
|
||||||
err => Err(err.set_position(pos)),
|
err => Err(err.set_position(pos)),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
scope.rewind(scope_len);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// No new scope - create internal scope
|
||||||
|
_ => {
|
||||||
|
let mut scope = Scope::new();
|
||||||
|
|
||||||
|
scope.extend(
|
||||||
|
// Put arguments into scope as variables
|
||||||
|
fn_def
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.zip(args.iter().map(|x| (*x).into_dynamic()))
|
||||||
|
.map(|(name, value)| (name, ScopeEntryType::Normal, value)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Evaluate the function at one higher level of call depth
|
||||||
|
return self.eval_stmt(&mut scope, &fn_def.body, level + 1).or_else(
|
||||||
|
|err| match err {
|
||||||
|
// Convert return statement to return value
|
||||||
|
EvalAltResult::Return(x, _) => Ok(x),
|
||||||
|
err => Err(err.set_position(pos)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +595,7 @@ impl Engine<'_> {
|
|||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<Dynamic, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
match dot_rhs {
|
match dot_rhs {
|
||||||
// xxx.fn_name(args)
|
// xxx.fn_name(arg_expr_list)
|
||||||
Expr::FunctionCall(fn_name, arg_expr_list, def_val, pos) => {
|
Expr::FunctionCall(fn_name, arg_expr_list, def_val, pos) => {
|
||||||
let mut values = arg_expr_list
|
let mut values = arg_expr_list
|
||||||
.iter()
|
.iter()
|
||||||
@ -572,17 +604,19 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
let this_ptr = target.get_mut(scope);
|
let this_ptr = target.get_mut(scope);
|
||||||
|
|
||||||
let mut arg_values: Vec<_> = once(this_ptr)
|
let mut args: Vec<_> = once(this_ptr)
|
||||||
.chain(values.iter_mut().map(Dynamic::as_mut))
|
.chain(values.iter_mut().map(Dynamic::as_mut))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.call_fn_raw(fn_name, &mut arg_values, def_val.as_ref(), *pos, 0)
|
let def_val = def_val.as_ref();
|
||||||
|
|
||||||
|
self.call_fn_raw(None, fn_name, &mut args, def_val, *pos, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let this_ptr = target.get_mut(scope);
|
let mut args = [target.get_mut(scope)];
|
||||||
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(None, &make_getter(id), &mut args, None, *pos, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xxx.idx_lhs[idx_expr]
|
// xxx.idx_lhs[idx_expr]
|
||||||
@ -591,8 +625,8 @@ impl Engine<'_> {
|
|||||||
let value = match idx_lhs.as_ref() {
|
let value = match idx_lhs.as_ref() {
|
||||||
// xxx.id[idx_expr]
|
// xxx.id[idx_expr]
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let this_ptr = target.get_mut(scope);
|
let mut args = [target.get_mut(scope)];
|
||||||
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)?
|
self.call_fn_raw(None, &make_getter(id), &mut args, None, *pos, 0)?
|
||||||
}
|
}
|
||||||
// xxx.???[???][idx_expr]
|
// xxx.???[???][idx_expr]
|
||||||
Expr::Index(_, _, _) => {
|
Expr::Index(_, _, _) => {
|
||||||
@ -615,8 +649,8 @@ impl Engine<'_> {
|
|||||||
Expr::Dot(dot_lhs, rhs, _) => match dot_lhs.as_ref() {
|
Expr::Dot(dot_lhs, rhs, _) => match dot_lhs.as_ref() {
|
||||||
// xxx.id.rhs
|
// xxx.id.rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let this_ptr = target.get_mut(scope);
|
let mut args = [target.get_mut(scope)];
|
||||||
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(None, &make_getter(id), &mut args, None, *pos, 0)
|
||||||
.and_then(|mut val| {
|
.and_then(|mut val| {
|
||||||
self.get_dot_val_helper(scope, Target::from(val.as_mut()), rhs, level)
|
self.get_dot_val_helper(scope, Target::from(val.as_mut()), rhs, level)
|
||||||
})
|
})
|
||||||
@ -627,8 +661,8 @@ impl Engine<'_> {
|
|||||||
let val = match idx_lhs.as_ref() {
|
let val = match idx_lhs.as_ref() {
|
||||||
// xxx.id[idx_expr].rhs
|
// xxx.id[idx_expr].rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let this_ptr = target.get_mut(scope);
|
let mut args = [target.get_mut(scope)];
|
||||||
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)?
|
self.call_fn_raw(None, &make_getter(id), &mut args, None, *pos, 0)?
|
||||||
}
|
}
|
||||||
// xxx.???[???][idx_expr].rhs
|
// xxx.???[???][idx_expr].rhs
|
||||||
Expr::Index(_, _, _) => {
|
Expr::Index(_, _, _) => {
|
||||||
@ -977,7 +1011,7 @@ impl Engine<'_> {
|
|||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let mut args = [this_ptr, new_val.0.as_mut()];
|
let mut args = [this_ptr, new_val.0.as_mut()];
|
||||||
self.call_fn_raw(&make_setter(id), &mut args, None, *pos, 0)
|
self.call_fn_raw(None, &make_setter(id), &mut args, None, *pos, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xxx.lhs[idx_expr]
|
// xxx.lhs[idx_expr]
|
||||||
@ -986,7 +1020,7 @@ impl Engine<'_> {
|
|||||||
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
||||||
// xxx.id[idx_expr]
|
// xxx.id[idx_expr]
|
||||||
Expr::Property(id, pos) => self
|
Expr::Property(id, pos) => self
|
||||||
.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
.call_fn_raw(None, &make_getter(id), &mut [this_ptr], None, *pos, 0)
|
||||||
.and_then(|val| {
|
.and_then(|val| {
|
||||||
let (_, _, idx) =
|
let (_, _, idx) =
|
||||||
self.get_indexed_value(scope, &val, idx_expr, *op_pos, level)?;
|
self.get_indexed_value(scope, &val, idx_expr, *op_pos, level)?;
|
||||||
@ -995,7 +1029,7 @@ impl Engine<'_> {
|
|||||||
})
|
})
|
||||||
.and_then(|mut val| {
|
.and_then(|mut val| {
|
||||||
let mut args = [this_ptr, val.as_mut()];
|
let mut args = [this_ptr, val.as_mut()];
|
||||||
self.call_fn_raw(&make_setter(id), &mut args, None, *pos, 0)
|
self.call_fn_raw(None, &make_setter(id), &mut args, None, *pos, 0)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// All others - syntax error for setters chain
|
// All others - syntax error for setters chain
|
||||||
@ -1009,14 +1043,14 @@ impl Engine<'_> {
|
|||||||
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
||||||
// xxx.id.rhs
|
// xxx.id.rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(None, &make_getter(id), &mut [this_ptr], None, *pos, 0)
|
||||||
.and_then(|mut val| {
|
.and_then(|mut val| {
|
||||||
self.set_dot_val_helper(scope, val.as_mut(), rhs, new_val, level)
|
self.set_dot_val_helper(scope, val.as_mut(), rhs, new_val, level)
|
||||||
.map(|_| val) // Discard Ok return value
|
.map(|_| val) // Discard Ok return value
|
||||||
})
|
})
|
||||||
.and_then(|mut val| {
|
.and_then(|mut val| {
|
||||||
let mut args = [this_ptr, val.as_mut()];
|
let mut args = [this_ptr, val.as_mut()];
|
||||||
self.call_fn_raw(&make_setter(id), &mut args, None, *pos, 0)
|
self.call_fn_raw(None, &make_setter(id), &mut args, None, *pos, 0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1026,7 +1060,7 @@ impl Engine<'_> {
|
|||||||
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
||||||
// xxx.id[idx_expr].rhs
|
// xxx.id[idx_expr].rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(None, &make_getter(id), &mut [this_ptr], None, *pos, 0)
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
let (mut value, _, idx) =
|
let (mut value, _, idx) =
|
||||||
self.get_indexed_value(scope, &v, idx_expr, *op_pos, level)?;
|
self.get_indexed_value(scope, &v, idx_expr, *op_pos, level)?;
|
||||||
@ -1039,13 +1073,8 @@ impl Engine<'_> {
|
|||||||
Self::update_indexed_value(v, idx, value, val_pos)
|
Self::update_indexed_value(v, idx, value, val_pos)
|
||||||
})
|
})
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
self.call_fn_raw(
|
let mut args = [this_ptr, v.as_mut()];
|
||||||
&make_setter(id),
|
self.call_fn_raw(None, &make_setter(id), &mut args, None, *pos, 0)
|
||||||
&mut [this_ptr, v.as_mut()],
|
|
||||||
None,
|
|
||||||
*pos,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1315,7 +1344,8 @@ impl Engine<'_> {
|
|||||||
.into_dynamic();
|
.into_dynamic();
|
||||||
|
|
||||||
// Redirect call to `print`
|
// Redirect call to `print`
|
||||||
self.call_fn_raw(KEYWORD_PRINT, &mut [result.as_mut()], None, pos, level)
|
let mut args = [result.as_mut()];
|
||||||
|
self.call_fn_raw(None, KEYWORD_PRINT, &mut args, None, pos, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
// type_of
|
// type_of
|
||||||
@ -1349,7 +1379,7 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
// Compile the script text
|
// Compile the script text
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
let mut ast = {
|
let ast = {
|
||||||
let orig_optimization_level = self.optimization_level;
|
let orig_optimization_level = self.optimization_level;
|
||||||
|
|
||||||
self.set_optimization_level(OptimizationLevel::None);
|
self.set_optimization_level(OptimizationLevel::None);
|
||||||
@ -1360,7 +1390,7 @@ impl Engine<'_> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "no_optimize")]
|
#[cfg(feature = "no_optimize")]
|
||||||
let mut ast = self.compile(script).map_err(EvalAltResult::ErrorParsing)?;
|
let ast = self.compile(script).map_err(EvalAltResult::ErrorParsing)?;
|
||||||
|
|
||||||
// If new functions are defined, merge it into the current functions library
|
// If new functions are defined, merge it into the current functions library
|
||||||
let merged = AST(
|
let merged = AST(
|
||||||
@ -1404,7 +1434,9 @@ impl Engine<'_> {
|
|||||||
let mut arg_values: Vec<_> =
|
let mut arg_values: Vec<_> =
|
||||||
values.iter_mut().map(Dynamic::as_mut).collect();
|
values.iter_mut().map(Dynamic::as_mut).collect();
|
||||||
|
|
||||||
self.call_fn_raw(fn_name, &mut arg_values, def_val.as_ref(), *pos, level)
|
let def_val = def_val.as_ref();
|
||||||
|
|
||||||
|
self.call_fn_raw(None, fn_name, &mut arg_values, def_val, *pos, level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1527,6 +1559,7 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
if let Some(ref type_iterators) = self.type_iterators {
|
if let Some(ref type_iterators) = self.type_iterators {
|
||||||
if let Some(iter_fn) = type_iterators.get(&tid) {
|
if let Some(iter_fn) = type_iterators.get(&tid) {
|
||||||
|
// Add the loop variable - variable name is copied
|
||||||
scope.push(name.clone(), ());
|
scope.push(name.clone(), ());
|
||||||
|
|
||||||
let entry = ScopeSource {
|
let entry = ScopeSource {
|
||||||
|
@ -63,6 +63,7 @@ pub(crate) struct EntryRef<'a> {
|
|||||||
/// allowing for automatic _shadowing_.
|
/// allowing for automatic _shadowing_.
|
||||||
///
|
///
|
||||||
/// Currently, `Scope` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
|
/// Currently, `Scope` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct Scope<'a>(Vec<Entry<'a>>);
|
pub struct Scope<'a>(Vec<Entry<'a>>);
|
||||||
|
|
||||||
impl<'a> Scope<'a> {
|
impl<'a> Scope<'a> {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#![cfg(not(feature = "no_function"))]
|
#![cfg(not(feature = "no_function"))]
|
||||||
use rhai::{Engine, EvalAltResult, ParseErrorType, INT};
|
use rhai::{Engine, EvalAltResult, ParseErrorType, Scope, INT};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fn() -> Result<(), EvalAltResult> {
|
fn test_fn() -> Result<(), EvalAltResult> {
|
||||||
@ -21,6 +21,9 @@ fn test_fn() -> Result<(), EvalAltResult> {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_call_fn() -> Result<(), EvalAltResult> {
|
fn test_call_fn() -> Result<(), EvalAltResult> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
let mut scope = Scope::new();
|
||||||
|
|
||||||
|
scope.push("foo", 42 as INT);
|
||||||
|
|
||||||
let ast = engine.compile(
|
let ast = engine.compile(
|
||||||
r"
|
r"
|
||||||
@ -28,22 +31,22 @@ fn test_call_fn() -> Result<(), EvalAltResult> {
|
|||||||
x + y
|
x + y
|
||||||
}
|
}
|
||||||
fn hello(x) {
|
fn hello(x) {
|
||||||
x * 2
|
x * foo
|
||||||
}
|
}
|
||||||
fn hello() {
|
fn hello() {
|
||||||
42
|
42 + foo
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let r: i64 = engine.call_fn(&ast, "hello", (42 as INT, 123 as INT))?;
|
let r: i64 = engine.call_fn(&mut scope, &ast, "hello", (42 as INT, 123 as INT))?;
|
||||||
assert_eq!(r, 165);
|
assert_eq!(r, 165);
|
||||||
|
|
||||||
let r: i64 = engine.call_fn1(&ast, "hello", 123 as INT)?;
|
let r: i64 = engine.call_fn1(&mut scope, &ast, "hello", 123 as INT)?;
|
||||||
assert_eq!(r, 246);
|
assert_eq!(r, 5166);
|
||||||
|
|
||||||
let r: i64 = engine.call_fn0(&ast, "hello")?;
|
let r: i64 = engine.call_fn0(&mut scope, &ast, "hello")?;
|
||||||
assert_eq!(r, 42);
|
assert_eq!(r, 84);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user