Add new &Module parameter to native functions.
This commit is contained in:
parent
495d202af4
commit
ea86888638
@ -56,19 +56,20 @@ let result: () = engine.call_fn(&mut scope, &ast, "hidden", ())?;
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
`Engine::call_fn_dynamic`
|
Low-Level API - `Engine::call_fn_dynamic`
|
||||||
------------------------
|
----------------------------------------
|
||||||
|
|
||||||
For more control, construct all arguments as `Dynamic` values and use `Engine::call_fn_dynamic`, passing it
|
For more control, construct all arguments as `Dynamic` values and use `Engine::call_fn_dynamic`, passing it
|
||||||
anything that implements `IntoIterator<Item = Dynamic>` (such as a simple `Vec<Dynamic>`):
|
anything that implements `AsMut<Dynamic>` (such as a simple array or a `Vec<Dynamic>`):
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let result: Dynamic = engine.call_fn_dynamic(
|
let result = engine.call_fn_dynamic(
|
||||||
&mut scope, // scope to use
|
&mut scope, // scope to use
|
||||||
&ast, // AST to use
|
ast.into(), // get 'Module' from 'AST'
|
||||||
"hello", // function entry-point
|
"hello", // function entry-point
|
||||||
None, // 'this' pointer, if any
|
None, // 'this' pointer, if any
|
||||||
[ String::from("abc").into(), 123_i64.into() ])?; // arguments
|
[ String::from("abc").into(), 123_i64.into() ] // arguments
|
||||||
|
)?;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -82,8 +83,13 @@ let ast = engine.compile("fn action(x) { this += x; }")?;
|
|||||||
|
|
||||||
let mut value: Dynamic = 1_i64.into();
|
let mut value: Dynamic = 1_i64.into();
|
||||||
|
|
||||||
let result = engine.call_fn_dynamic(&mut scope, &ast, "action", Some(&mut value), [ 41_i64.into() ])?;
|
let result = engine.call_fn_dynamic(
|
||||||
// ^^^^^^^^^^^^^^^^ binding the 'this' pointer
|
&mut scope,
|
||||||
|
ast.into(),
|
||||||
|
"action",
|
||||||
|
Some(&mut value), // binding the 'this' pointer
|
||||||
|
[ 41_i64.into() ]
|
||||||
|
)?;
|
||||||
|
|
||||||
assert_eq!(value.as_int().unwrap(), 42);
|
assert_eq!(value.as_int().unwrap(), 42);
|
||||||
```
|
```
|
||||||
|
78
src/api.rs
78
src/api.rs
@ -6,6 +6,7 @@ use crate::error::ParseError;
|
|||||||
use crate::fn_call::FuncArgs;
|
use crate::fn_call::FuncArgs;
|
||||||
use crate::fn_native::{IteratorFn, SendSync};
|
use crate::fn_native::{IteratorFn, SendSync};
|
||||||
use crate::fn_register::RegisterFn;
|
use crate::fn_register::RegisterFn;
|
||||||
|
use crate::module::Module;
|
||||||
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
use crate::optimize::{optimize_into_ast, OptimizationLevel};
|
||||||
use crate::parser::AST;
|
use crate::parser::AST;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
@ -53,10 +54,10 @@ impl Engine {
|
|||||||
name: &str,
|
name: &str,
|
||||||
args: &[TypeId],
|
args: &[TypeId],
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))] func: impl Fn(&Engine, &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>>
|
#[cfg(not(feature = "sync"))] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
+ 'static,
|
+ 'static,
|
||||||
|
|
||||||
#[cfg(feature = "sync")] func: impl Fn(&Engine, &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>>
|
#[cfg(feature = "sync")] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
@ -459,7 +460,7 @@ impl Engine {
|
|||||||
self.register_indexer_set(setter);
|
self.register_indexer_set(setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a string into an [`AST`], which can be used later for evaluation.
|
/// Compile a string into an `AST`, which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -482,7 +483,7 @@ impl Engine {
|
|||||||
self.compile_with_scope(&Scope::new(), script)
|
self.compile_with_scope(&Scope::new(), script)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a string into an [`AST`] using own scope, which can be used later for evaluation.
|
/// Compile a string into an `AST` using own scope, which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
/// The scope is useful for passing constants into the script for optimization
|
/// The scope is useful for passing constants into the script for optimization
|
||||||
/// when using `OptimizationLevel::Full`.
|
/// when using `OptimizationLevel::Full`.
|
||||||
@ -525,7 +526,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// When passed a list of strings, first join the strings into one large script,
|
/// When passed a list of strings, first join the strings into one large script,
|
||||||
/// and then compile them into an [`AST`] using own scope, which can be used later for evaluation.
|
/// and then compile them into an `AST` using own scope, which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
/// The scope is useful for passing constants into the script for optimization
|
/// The scope is useful for passing constants into the script for optimization
|
||||||
/// when using `OptimizationLevel::Full`.
|
/// when using `OptimizationLevel::Full`.
|
||||||
@ -578,7 +579,7 @@ impl Engine {
|
|||||||
self.compile_with_scope_and_optimization_level(scope, scripts, self.optimization_level)
|
self.compile_with_scope_and_optimization_level(scope, scripts, self.optimization_level)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Join a list of strings and compile into an [`AST`] using own scope at a specific optimization level.
|
/// Join a list of strings and compile into an `AST` using own scope at a specific optimization level.
|
||||||
pub(crate) fn compile_with_scope_and_optimization_level(
|
pub(crate) fn compile_with_scope_and_optimization_level(
|
||||||
&self,
|
&self,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
@ -614,7 +615,7 @@ impl Engine {
|
|||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a script file into an [`AST`], which can be used later for evaluation.
|
/// Compile a script file into an `AST`, which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -640,7 +641,7 @@ impl Engine {
|
|||||||
self.compile_file_with_scope(&Scope::new(), path)
|
self.compile_file_with_scope(&Scope::new(), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a script file into an [`AST`] using own scope, which can be used later for evaluation.
|
/// Compile a script file into an `AST` using own scope, which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
/// The scope is useful for passing constants into the script for optimization
|
/// The scope is useful for passing constants into the script for optimization
|
||||||
/// when using `OptimizationLevel::Full`.
|
/// when using `OptimizationLevel::Full`.
|
||||||
@ -722,7 +723,7 @@ impl Engine {
|
|||||||
self.eval_ast_with_scope(&mut scope, &ast)
|
self.eval_ast_with_scope(&mut scope, &ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a string containing an expression into an [`AST`],
|
/// Compile a string containing an expression into an `AST`,
|
||||||
/// which can be used later for evaluation.
|
/// which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -746,7 +747,7 @@ impl Engine {
|
|||||||
self.compile_expression_with_scope(&Scope::new(), script)
|
self.compile_expression_with_scope(&Scope::new(), script)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a string containing an expression into an [`AST`] using own scope,
|
/// Compile a string containing an expression into an `AST` using own scope,
|
||||||
/// which can be used later for evaluation.
|
/// which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
/// The scope is useful for passing constants into the script for optimization
|
/// The scope is useful for passing constants into the script for optimization
|
||||||
@ -954,7 +955,7 @@ impl Engine {
|
|||||||
self.eval_ast_with_scope(scope, &ast)
|
self.eval_ast_with_scope(scope, &ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate an [`AST`].
|
/// Evaluate an `AST`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -976,7 +977,7 @@ impl Engine {
|
|||||||
self.eval_ast_with_scope(&mut Scope::new(), ast)
|
self.eval_ast_with_scope(&mut Scope::new(), ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate an [`AST`] with own scope.
|
/// Evaluate an `AST` with own scope.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -1024,7 +1025,7 @@ impl Engine {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate an [`AST`] with own scope.
|
/// Evaluate an `AST` with own scope.
|
||||||
pub(crate) fn eval_ast_with_scope_raw<'a>(
|
pub(crate) fn eval_ast_with_scope_raw<'a>(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
@ -1090,7 +1091,7 @@ impl Engine {
|
|||||||
self.consume_ast_with_scope(&mut Scope::new(), ast)
|
self.consume_ast_with_scope(&mut Scope::new(), ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate an [`AST`] with own scope, but throw away the result and only return error (if any).
|
/// Evaluate an `AST` with own scope, but throw away the result and only return error (if any).
|
||||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||||
pub fn consume_ast_with_scope(
|
pub fn consume_ast_with_scope(
|
||||||
&self,
|
&self,
|
||||||
@ -1114,7 +1115,7 @@ impl Engine {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a script function defined in an [`AST`] with multiple arguments.
|
/// Call a script function defined in an `AST` with multiple arguments.
|
||||||
/// Arguments are passed as a tuple.
|
/// Arguments are passed as a tuple.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -1159,7 +1160,8 @@ impl Engine {
|
|||||||
args: A,
|
args: A,
|
||||||
) -> Result<T, Box<EvalAltResult>> {
|
) -> Result<T, Box<EvalAltResult>> {
|
||||||
let mut arg_values = args.into_vec();
|
let mut arg_values = args.into_vec();
|
||||||
let result = self.call_fn_dynamic_raw(scope, ast, name, &mut None, arg_values.as_mut())?;
|
let result =
|
||||||
|
self.call_fn_dynamic_raw(scope, ast.lib(), name, &mut None, arg_values.as_mut())?;
|
||||||
|
|
||||||
let typ = self.map_type_name(result.type_name());
|
let typ = self.map_type_name(result.type_name());
|
||||||
|
|
||||||
@ -1172,7 +1174,7 @@ impl Engine {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a script function defined in an [`AST`] with multiple `Dynamic` arguments
|
/// Call a script function defined in an `AST` with multiple `Dynamic` arguments
|
||||||
/// and optionally a value for binding to the 'this' pointer.
|
/// and optionally a value for binding to the 'this' pointer.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// ## WARNING
|
||||||
@ -1203,19 +1205,19 @@ impl Engine {
|
|||||||
/// scope.push("foo", 42_i64);
|
/// scope.push("foo", 42_i64);
|
||||||
///
|
///
|
||||||
/// // Call the script-defined function
|
/// // Call the script-defined function
|
||||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "add", None, [ String::from("abc").into(), 123_i64.into() ])?;
|
/// let result = engine.call_fn_dynamic(&mut scope, ast.into(), "add", None, [ String::from("abc").into(), 123_i64.into() ])?;
|
||||||
/// // ^^^^ no 'this' pointer
|
/// // ^^^^ no 'this' pointer
|
||||||
/// assert_eq!(result.cast::<i64>(), 168);
|
/// assert_eq!(result.cast::<i64>(), 168);
|
||||||
///
|
///
|
||||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "add1", None, [ String::from("abc").into() ])?;
|
/// let result = engine.call_fn_dynamic(&mut scope, ast.into(), "add1", None, [ String::from("abc").into() ])?;
|
||||||
/// assert_eq!(result.cast::<i64>(), 46);
|
/// assert_eq!(result.cast::<i64>(), 46);
|
||||||
///
|
///
|
||||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "bar", None, [])?;
|
/// let result = engine.call_fn_dynamic(&mut scope, ast.into(), "bar", None, [])?;
|
||||||
/// assert_eq!(result.cast::<i64>(), 21);
|
/// assert_eq!(result.cast::<i64>(), 21);
|
||||||
///
|
///
|
||||||
/// let mut value: Dynamic = 1_i64.into();
|
/// let mut value: Dynamic = 1_i64.into();
|
||||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "action", Some(&mut value), [ 41_i64.into() ])?;
|
/// let result = engine.call_fn_dynamic(&mut scope, ast.into(), "action", Some(&mut value), [ 41_i64.into() ])?;
|
||||||
/// // ^^^^^^^^^^^^^^^^ binding the 'this' pointer
|
/// // ^^^^^^^^^^^^^^^^ binding the 'this' pointer
|
||||||
/// assert_eq!(value.as_int().unwrap(), 42);
|
/// assert_eq!(value.as_int().unwrap(), 42);
|
||||||
/// # }
|
/// # }
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
@ -1225,15 +1227,15 @@ impl Engine {
|
|||||||
pub fn call_fn_dynamic(
|
pub fn call_fn_dynamic(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
ast: &AST,
|
lib: &Module,
|
||||||
name: &str,
|
name: &str,
|
||||||
mut this_ptr: Option<&mut Dynamic>,
|
mut this_ptr: Option<&mut Dynamic>,
|
||||||
mut arg_values: impl AsMut<[Dynamic]>,
|
mut arg_values: impl AsMut<[Dynamic]>,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
self.call_fn_dynamic_raw(scope, ast, name, &mut this_ptr, arg_values.as_mut())
|
self.call_fn_dynamic_raw(scope, lib, name, &mut this_ptr, arg_values.as_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a script function defined in an [`AST`] with multiple `Dynamic` arguments.
|
/// Call a script function defined in an `AST` with multiple `Dynamic` arguments.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// ## WARNING
|
||||||
///
|
///
|
||||||
@ -1245,14 +1247,14 @@ impl Engine {
|
|||||||
pub(crate) fn call_fn_dynamic_raw(
|
pub(crate) fn call_fn_dynamic_raw(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
ast: &AST,
|
lib: &Module,
|
||||||
name: &str,
|
name: &str,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
arg_values: &mut [Dynamic],
|
arg_values: &mut [Dynamic],
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
||||||
let fn_def = get_script_function_by_signature(ast.lib(), name, args.len(), true)
|
let fn_def =
|
||||||
.ok_or_else(|| {
|
get_script_function_by_signature(lib, name, args.len(), true).ok_or_else(|| {
|
||||||
Box::new(EvalAltResult::ErrorFunctionNotFound(
|
Box::new(EvalAltResult::ErrorFunctionNotFound(
|
||||||
name.into(),
|
name.into(),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
@ -1264,27 +1266,19 @@ impl Engine {
|
|||||||
let args = args.as_mut();
|
let args = args.as_mut();
|
||||||
|
|
||||||
self.call_script_fn(
|
self.call_script_fn(
|
||||||
scope,
|
scope, &mut mods, &mut state, lib, this_ptr, name, fn_def, args, 0,
|
||||||
&mut mods,
|
|
||||||
&mut state,
|
|
||||||
ast.lib(),
|
|
||||||
this_ptr,
|
|
||||||
name,
|
|
||||||
fn_def,
|
|
||||||
args,
|
|
||||||
0,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optimize the [`AST`] with constants defined in an external Scope.
|
/// Optimize the `AST` with constants defined in an external Scope.
|
||||||
/// An optimized copy of the [`AST`] is returned while the original [`AST`] is consumed.
|
/// An optimized copy of the `AST` is returned while the original `AST` is consumed.
|
||||||
///
|
///
|
||||||
/// Although optimization is performed by default during compilation, sometimes it is necessary to
|
/// Although optimization is performed by default during compilation, sometimes it is necessary to
|
||||||
/// _re_-optimize an AST. For example, when working with constants that are passed in via an
|
/// _re_-optimize an AST. For example, when working with constants that are passed in via an
|
||||||
/// external scope, it will be more efficient to optimize the [`AST`] once again to take advantage
|
/// external scope, it will be more efficient to optimize the `AST` once again to take advantage
|
||||||
/// of the new constants.
|
/// of the new constants.
|
||||||
///
|
///
|
||||||
/// With this method, it is no longer necessary to recompile a large script. The script [`AST`] can be
|
/// With this method, it is no longer necessary to recompile a large script. The script `AST` can be
|
||||||
/// compiled just once. Before evaluation, constants are passed into the `Engine` via an external scope
|
/// compiled just once. Before evaluation, constants are passed into the `Engine` via an external scope
|
||||||
/// (i.e. with `scope.push_constant(...)`). Then, the `AST is cloned and the copy re-optimized before running.
|
/// (i.e. with `scope.push_constant(...)`). Then, the `AST is cloned and the copy re-optimized before running.
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
|
@ -661,7 +661,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run external function
|
// Run external function
|
||||||
let result = func.get_native_fn()(self, args)?;
|
let result = func.get_native_fn()(self, lib, args)?;
|
||||||
|
|
||||||
// Restore the original reference
|
// Restore the original reference
|
||||||
restore_first_arg(old_this_ptr, args);
|
restore_first_arg(old_this_ptr, args);
|
||||||
@ -1616,7 +1616,7 @@ impl Engine {
|
|||||||
.or_else(|| self.packages.get_fn(hash_fn))
|
.or_else(|| self.packages.get_fn(hash_fn))
|
||||||
{
|
{
|
||||||
// Overriding exact implementation
|
// Overriding exact implementation
|
||||||
func(self, &mut [lhs_ptr, &mut rhs_val])?;
|
func(self, lib, &mut [lhs_ptr, &mut rhs_val])?;
|
||||||
} else if run_builtin_op_assignment(op, lhs_ptr, &rhs_val)?.is_none() {
|
} else if run_builtin_op_assignment(op, lhs_ptr, &rhs_val)?.is_none() {
|
||||||
// Not built in, map to `var = var op rhs`
|
// Not built in, map to `var = var op rhs`
|
||||||
let op = &op[..op.len() - 1]; // extract operator without =
|
let op = &op[..op.len() - 1]; // extract operator without =
|
||||||
@ -1885,9 +1885,8 @@ impl Engine {
|
|||||||
)
|
)
|
||||||
.map_err(|err| err.new_position(*pos))
|
.map_err(|err| err.new_position(*pos))
|
||||||
}
|
}
|
||||||
Ok(f) => {
|
Ok(f) => f.get_native_fn()(self, lib, args.as_mut())
|
||||||
f.get_native_fn()(self, args.as_mut()).map_err(|err| err.new_position(*pos))
|
.map_err(|err| err.new_position(*pos)),
|
||||||
}
|
|
||||||
Err(err) => match *err {
|
Err(err) => match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(_, _) if def_val.is_some() => {
|
EvalAltResult::ErrorFunctionNotFound(_, _) if def_val.is_some() => {
|
||||||
Ok(def_val.clone().unwrap())
|
Ok(def_val.clone().unwrap())
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
|
use crate::module::Module;
|
||||||
use crate::parser::ScriptFnDef;
|
use crate::parser::ScriptFnDef;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::utils::ImmutableString;
|
use crate::utils::ImmutableString;
|
||||||
@ -79,11 +80,11 @@ impl<S: Into<ImmutableString>> From<S> for FnPtr {
|
|||||||
|
|
||||||
/// A general function trail object.
|
/// A general function trail object.
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
pub type FnAny = dyn Fn(&Engine, &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
|
pub type FnAny = dyn Fn(&Engine, &Module, &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
|
||||||
/// A general function trail object.
|
/// A general function trail object.
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub type FnAny =
|
pub type FnAny =
|
||||||
dyn Fn(&Engine, &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync;
|
dyn Fn(&Engine, &Module, &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync;
|
||||||
|
|
||||||
/// A standard function that gets an iterator from a type.
|
/// A standard function that gets an iterator from a type.
|
||||||
pub type IteratorFn = fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
|
pub type IteratorFn = fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync};
|
use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync};
|
||||||
|
use crate::module::Module;
|
||||||
use crate::parser::FnAccess;
|
use crate::parser::FnAccess;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::utils::ImmutableString;
|
use crate::utils::ImmutableString;
|
||||||
@ -119,7 +120,7 @@ macro_rules! make_func {
|
|||||||
// ^ function parameter generic type name (A, B, C etc.)
|
// ^ function parameter generic type name (A, B, C etc.)
|
||||||
// ^ dereferencing function
|
// ^ dereferencing function
|
||||||
|
|
||||||
Box::new(move |_: &Engine, args: &mut FnCallArgs| {
|
Box::new(move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
// The arguments are assumed to be of the correct number and types!
|
// The arguments are assumed to be of the correct number and types!
|
||||||
|
|
||||||
#[allow(unused_variables, unused_mut)]
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
@ -373,9 +373,11 @@ impl Module {
|
|||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
args: &[TypeId],
|
args: &[TypeId],
|
||||||
func: impl Fn(&Engine, &mut [&mut Dynamic]) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |engine: &Engine, args: &mut FnCallArgs| func(engine, args).map(Dynamic::from);
|
let f = move |engine: &Engine, lib: &Module, args: &mut FnCallArgs| {
|
||||||
|
func(engine, lib, args).map(Dynamic::from)
|
||||||
|
};
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
Public,
|
Public,
|
||||||
@ -402,7 +404,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn() -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn() -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, _: &mut FnCallArgs| func().map(Dynamic::from);
|
let f = move |_: &Engine, _: &Module, _: &mut FnCallArgs| func().map(Dynamic::from);
|
||||||
let args = [];
|
let args = [];
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
@ -430,7 +432,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn(A) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(A) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
func(mem::take(args[0]).cast::<A>()).map(Dynamic::from)
|
func(mem::take(args[0]).cast::<A>()).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let args = [TypeId::of::<A>()];
|
let args = [TypeId::of::<A>()];
|
||||||
@ -460,7 +462,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn(&mut A) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(&mut A) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
|
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let args = [TypeId::of::<A>()];
|
let args = [TypeId::of::<A>()];
|
||||||
@ -514,7 +516,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn(A, B) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(A, B) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
let a = mem::take(args[0]).cast::<A>();
|
let a = mem::take(args[0]).cast::<A>();
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
|
|
||||||
@ -550,7 +552,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn(&mut A, B) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(&mut A, B) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let a = args[0].downcast_mut::<A>().unwrap();
|
let a = args[0].downcast_mut::<A>().unwrap();
|
||||||
|
|
||||||
@ -641,7 +643,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn(A, B, C) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(A, B, C) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
let a = mem::take(args[0]).cast::<A>();
|
let a = mem::take(args[0]).cast::<A>();
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let c = mem::take(args[2]).cast::<C>();
|
let c = mem::take(args[2]).cast::<C>();
|
||||||
@ -683,7 +685,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn(&mut A, B, C) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(&mut A, B, C) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let c = mem::take(args[2]).cast::<C>();
|
let c = mem::take(args[2]).cast::<C>();
|
||||||
let a = args[0].downcast_mut::<A>().unwrap();
|
let a = args[0].downcast_mut::<A>().unwrap();
|
||||||
@ -720,7 +722,7 @@ impl Module {
|
|||||||
&mut self,
|
&mut self,
|
||||||
func: impl Fn(&mut A, B, A) -> FuncReturn<()> + SendSync + 'static,
|
func: impl Fn(&mut A, B, A) -> FuncReturn<()> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let c = mem::take(args[2]).cast::<A>();
|
let c = mem::take(args[2]).cast::<A>();
|
||||||
let a = args[0].downcast_mut::<A>().unwrap();
|
let a = args[0].downcast_mut::<A>().unwrap();
|
||||||
@ -762,7 +764,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn(A, B, C, D) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(A, B, C, D) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
let a = mem::take(args[0]).cast::<A>();
|
let a = mem::take(args[0]).cast::<A>();
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let c = mem::take(args[2]).cast::<C>();
|
let c = mem::take(args[2]).cast::<C>();
|
||||||
@ -811,7 +813,7 @@ impl Module {
|
|||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
func: impl Fn(&mut A, B, C, D) -> FuncReturn<T> + SendSync + 'static,
|
func: impl Fn(&mut A, B, C, D) -> FuncReturn<T> + SendSync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &Engine, args: &mut FnCallArgs| {
|
let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| {
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let c = mem::take(args[2]).cast::<C>();
|
let c = mem::take(args[2]).cast::<C>();
|
||||||
let d = mem::take(args[3]).cast::<D>();
|
let d = mem::take(args[3]).cast::<D>();
|
||||||
@ -942,7 +944,7 @@ impl Module {
|
|||||||
.map(|f| f.get_shared_fn_def())
|
.map(|f| f.get_shared_fn_def())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `Module` by evaluating an [`AST`].
|
/// Create a new `Module` by evaluating an `AST`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
use crate::engine::{Array, Engine};
|
use crate::engine::{Array, Engine};
|
||||||
use crate::module::FuncReturn;
|
use crate::module::{FuncReturn, Module};
|
||||||
use crate::parser::{ImmutableString, INT};
|
use crate::parser::{ImmutableString, INT};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
@ -25,7 +25,11 @@ fn ins<T: Variant + Clone>(list: &mut Array, position: INT, item: T) -> FuncRetu
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn pad<T: Variant + Clone>(engine: &Engine, args: &mut [&mut Dynamic]) -> FuncReturn<()> {
|
fn pad<T: Variant + Clone>(
|
||||||
|
engine: &Engine,
|
||||||
|
_: &Module,
|
||||||
|
args: &mut [&mut Dynamic],
|
||||||
|
) -> FuncReturn<()> {
|
||||||
let len = *args[1].downcast_ref::<INT>().unwrap();
|
let len = *args[1].downcast_ref::<INT>().unwrap();
|
||||||
|
|
||||||
// Check if array will be over max size limit
|
// Check if array will be over max size limit
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
use crate::module::FuncReturn;
|
use crate::module::{FuncReturn, Module};
|
||||||
use crate::parser::{ImmutableString, INT};
|
use crate::parser::{ImmutableString, INT};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
@ -226,7 +226,7 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
|||||||
lib.set_fn_var_args(
|
lib.set_fn_var_args(
|
||||||
"pad",
|
"pad",
|
||||||
&[TypeId::of::<ImmutableString>(), TypeId::of::<INT>(), TypeId::of::<char>()],
|
&[TypeId::of::<ImmutableString>(), TypeId::of::<INT>(), TypeId::of::<char>()],
|
||||||
|engine: &Engine, args: &mut [&mut Dynamic]| {
|
|engine: &Engine, _: &Module, args: &mut [&mut Dynamic]| {
|
||||||
let len = *args[1].downcast_ref::< INT>().unwrap();
|
let len = *args[1].downcast_ref::< INT>().unwrap();
|
||||||
|
|
||||||
// Check if string will be over max size limit
|
// Check if string will be over max size limit
|
||||||
|
@ -298,6 +298,12 @@ impl Add<Self> for &AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a AST> for &'a Module {
|
||||||
|
fn from(ast: &'a AST) -> Self {
|
||||||
|
ast.lib()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A type representing the access mode of a scripted function.
|
/// A type representing the access mode of a scripted function.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum FnAccess {
|
pub enum FnAccess {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![cfg(not(feature = "no_function"))]
|
#![cfg(not(feature = "no_function"))]
|
||||||
use rhai::{
|
use rhai::{
|
||||||
Dynamic, Engine, EvalAltResult, Func, ImmutableString, ParseError, ParseErrorType, Scope, INT,
|
Dynamic, Engine, EvalAltResult, Func, ImmutableString, Module, ParseError, ParseErrorType,
|
||||||
|
Scope, INT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -117,17 +118,6 @@ fn test_anonymous_fn() -> Result<(), Box<EvalAltResult>> {
|
|||||||
fn test_fn_ptr() -> Result<(), Box<EvalAltResult>> {
|
fn test_fn_ptr() -> Result<(), Box<EvalAltResult>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
let ast = engine.compile(
|
|
||||||
r#"
|
|
||||||
fn foo(x) { this += x; }
|
|
||||||
|
|
||||||
let x = 41;
|
|
||||||
x.bar("foo", 1);
|
|
||||||
x
|
|
||||||
"#,
|
|
||||||
)?;
|
|
||||||
let ast_clone = ast.clone();
|
|
||||||
|
|
||||||
engine.register_raw_fn(
|
engine.register_raw_fn(
|
||||||
"bar",
|
"bar",
|
||||||
&[
|
&[
|
||||||
@ -135,24 +125,29 @@ fn test_fn_ptr() -> Result<(), Box<EvalAltResult>> {
|
|||||||
std::any::TypeId::of::<ImmutableString>(),
|
std::any::TypeId::of::<ImmutableString>(),
|
||||||
std::any::TypeId::of::<INT>(),
|
std::any::TypeId::of::<INT>(),
|
||||||
],
|
],
|
||||||
move |engine: &Engine, args: &mut [&mut Dynamic]| {
|
move |engine: &Engine, lib: &Module, args: &mut [&mut Dynamic]| {
|
||||||
let callback = args[1].clone().cast::<ImmutableString>();
|
let callback = args[1].clone().cast::<ImmutableString>();
|
||||||
let value = args[2].clone();
|
let value = args[2].clone();
|
||||||
let this_ptr = args.get_mut(0).unwrap();
|
let this_ptr = args.get_mut(0).unwrap();
|
||||||
|
|
||||||
engine.call_fn_dynamic(
|
engine.call_fn_dynamic(&mut Scope::new(), lib, &callback, Some(this_ptr), [value])?;
|
||||||
&mut Scope::new(),
|
|
||||||
&ast_clone,
|
|
||||||
&callback,
|
|
||||||
Some(this_ptr),
|
|
||||||
[value],
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(().into())
|
Ok(().into())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(engine.eval_ast::<INT>(&ast)?, 42);
|
assert_eq!(
|
||||||
|
engine.eval::<INT>(
|
||||||
|
r#"
|
||||||
|
fn foo(x) { this += x; }
|
||||||
|
|
||||||
|
let x = 41;
|
||||||
|
x.bar("foo", 1);
|
||||||
|
x
|
||||||
|
"#
|
||||||
|
)?,
|
||||||
|
42
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user