Create NativeCallable trait.
This commit is contained in:
parent
314ec5e4d2
commit
4a8710a4a9
@ -3,11 +3,12 @@
|
|||||||
use crate::any::{Dynamic, Union};
|
use crate::any::{Dynamic, Union};
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::error::ParseErrorType;
|
use crate::error::ParseErrorType;
|
||||||
|
use crate::fn_native::{FnCallArgs, NativeFunction, SharedNativeFunction};
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{
|
use crate::packages::{
|
||||||
CorePackage, Package, PackageLibrary, PackageStore, PackagesCollection, StandardPackage,
|
CorePackage, Package, PackageLibrary, PackageStore, PackagesCollection, StandardPackage,
|
||||||
};
|
};
|
||||||
use crate::parser::{Expr, FnAccess, FnDef, ReturnType, Stmt, AST};
|
use crate::parser::{Expr, FnAccess, FnDef, ReturnType, SharedFnDef, Stmt, AST};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
@ -46,19 +47,6 @@ pub type Array = Vec<Dynamic>;
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub type Map = HashMap<String, Dynamic>;
|
pub type Map = HashMap<String, Dynamic>;
|
||||||
|
|
||||||
pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub type FnAny =
|
|
||||||
dyn Fn(&mut FnCallArgs, Position) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync;
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub type FnAny = dyn Fn(&mut FnCallArgs, Position) -> Result<Dynamic, Box<EvalAltResult>>;
|
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync;
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub const MAX_CALL_STACK_DEPTH: usize = 28;
|
pub const MAX_CALL_STACK_DEPTH: usize = 28;
|
||||||
|
|
||||||
@ -168,20 +156,6 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An external native Rust function.
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub type NativeFunction = Rc<Box<FnAny>>;
|
|
||||||
/// An external native Rust function.
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub type NativeFunction = Arc<Box<FnAny>>;
|
|
||||||
|
|
||||||
/// A sharable script-defined function.
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub type ScriptedFunction = Arc<FnDef>;
|
|
||||||
/// A sharable script-defined function.
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub type ScriptedFunction = Rc<FnDef>;
|
|
||||||
|
|
||||||
/// A type that holds a library (`HashMap`) of script-defined functions.
|
/// A type that holds a library (`HashMap`) of script-defined functions.
|
||||||
///
|
///
|
||||||
/// Since script-defined functions have `Dynamic` parameters, functions with the same name
|
/// Since script-defined functions have `Dynamic` parameters, functions with the same name
|
||||||
@ -190,7 +164,7 @@ pub type ScriptedFunction = Rc<FnDef>;
|
|||||||
/// The key of the `HashMap` is a `u64` hash calculated by the function `calc_fn_hash`
|
/// The key of the `HashMap` is a `u64` hash calculated by the function `calc_fn_hash`
|
||||||
/// with dummy parameter types `EMPTY_TYPE_ID()` repeated the correct number of times.
|
/// with dummy parameter types `EMPTY_TYPE_ID()` repeated the correct number of times.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct FunctionsLib(HashMap<u64, ScriptedFunction>);
|
pub struct FunctionsLib(HashMap<u64, SharedFnDef>);
|
||||||
|
|
||||||
impl FunctionsLib {
|
impl FunctionsLib {
|
||||||
/// Create a new `FunctionsLib` from a collection of `FnDef`.
|
/// Create a new `FunctionsLib` from a collection of `FnDef`.
|
||||||
@ -261,8 +235,8 @@ impl FunctionsLib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<(u64, ScriptedFunction)>> for FunctionsLib {
|
impl From<Vec<(u64, SharedFnDef)>> for FunctionsLib {
|
||||||
fn from(values: Vec<(u64, ScriptedFunction)>) -> Self {
|
fn from(values: Vec<(u64, SharedFnDef)>) -> Self {
|
||||||
FunctionsLib(values.into_iter().collect())
|
FunctionsLib(values.into_iter().collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,7 +570,7 @@ impl Engine {
|
|||||||
.or_else(|| self.packages.get_function(hash_fn_spec))
|
.or_else(|| self.packages.get_function(hash_fn_spec))
|
||||||
{
|
{
|
||||||
// Run external function
|
// Run external function
|
||||||
let result = func(args, pos)?;
|
let result = func.call(args, pos)?;
|
||||||
|
|
||||||
// See if the function match print/debug (which requires special processing)
|
// See if the function match print/debug (which requires special processing)
|
||||||
return Ok(match fn_name {
|
return Ok(match fn_name {
|
||||||
@ -1476,7 +1450,7 @@ impl Engine {
|
|||||||
let hash = *hash_fn_def ^ hash_fn_args;
|
let hash = *hash_fn_def ^ hash_fn_args;
|
||||||
|
|
||||||
match module.get_qualified_fn(name, hash, *pos) {
|
match module.get_qualified_fn(name, hash, *pos) {
|
||||||
Ok(func) => func(args.as_mut(), *pos),
|
Ok(func) => func.call(args.as_mut(), *pos),
|
||||||
Err(_) if def_val.is_some() => Ok(def_val.clone().unwrap()),
|
Err(_) if def_val.is_some() => Ok(def_val.clone().unwrap()),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
|
52
src/fn_native.rs
Normal file
52
src/fn_native.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
use crate::any::Dynamic;
|
||||||
|
use crate::result::EvalAltResult;
|
||||||
|
use crate::token::Position;
|
||||||
|
|
||||||
|
use crate::stdlib::{boxed::Box, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
|
pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
||||||
|
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
pub type FnAny =
|
||||||
|
dyn Fn(&mut FnCallArgs, Position) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync;
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
pub type FnAny = dyn Fn(&mut FnCallArgs, Position) -> Result<Dynamic, Box<EvalAltResult>>;
|
||||||
|
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync;
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
|
||||||
|
|
||||||
|
/// A trait implemented by all native Rust functions that are callable by Rhai.
|
||||||
|
pub trait NativeCallable {
|
||||||
|
/// Call a native Rust function.
|
||||||
|
fn call(&self, args: &mut FnCallArgs, pos: Position) -> Result<Dynamic, Box<EvalAltResult>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type encapsulating a native Rust function callable by Rhai.
|
||||||
|
pub struct NativeFunction(Box<FnAny>);
|
||||||
|
|
||||||
|
impl NativeCallable for NativeFunction {
|
||||||
|
fn call(&self, args: &mut FnCallArgs, pos: Position) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
(self.0)(args, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Box<FnAny>> for NativeFunction {
|
||||||
|
fn from(func: Box<FnAny>) -> Self {
|
||||||
|
Self::new(func)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl NativeFunction {
|
||||||
|
/// Create a new `NativeFunction`.
|
||||||
|
pub fn new(func: Box<FnAny>) -> Self {
|
||||||
|
Self(func)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An external native Rust function.
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
pub type SharedNativeFunction = Rc<Box<dyn NativeCallable>>;
|
||||||
|
/// An external native Rust function.
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
pub type SharedNativeFunction = Arc<Box<dyn NativeCallable>>;
|
@ -3,7 +3,8 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::{Engine, FnCallArgs};
|
use crate::engine::Engine;
|
||||||
|
use crate::fn_native::{FnCallArgs, NativeFunction};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
use crate::utils::calc_fn_spec;
|
use crate::utils::calc_fn_spec;
|
||||||
@ -117,14 +118,14 @@ pub struct Mut<T>(T);
|
|||||||
//pub struct Ref<T>(T);
|
//pub struct Ref<T>(T);
|
||||||
|
|
||||||
/// Dereference into &mut.
|
/// Dereference into &mut.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn by_ref<T: Clone + 'static>(data: &mut Dynamic) -> &mut T {
|
pub fn by_ref<T: Clone + 'static>(data: &mut Dynamic) -> &mut T {
|
||||||
// Directly cast the &mut Dynamic into &mut T to access the underlying data.
|
// Directly cast the &mut Dynamic into &mut T to access the underlying data.
|
||||||
data.downcast_mut::<T>().unwrap()
|
data.downcast_mut::<T>().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dereference into value.
|
/// Dereference into value.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn by_value<T: Clone + 'static>(data: &mut Dynamic) -> T {
|
pub fn by_value<T: Clone + 'static>(data: &mut Dynamic) -> T {
|
||||||
// We consume the argument and then replace it with () - the argument is not supposed to be used again.
|
// We consume the argument and then replace it with () - the argument is not supposed to be used again.
|
||||||
// This way, we avoid having to clone the argument again, because it is already a clone when passed here.
|
// This way, we avoid having to clone the argument again, because it is already a clone when passed here.
|
||||||
@ -133,14 +134,13 @@ pub fn by_value<T: Clone + 'static>(data: &mut Dynamic) -> T {
|
|||||||
|
|
||||||
/// This macro creates a closure wrapping a registered function.
|
/// This macro creates a closure wrapping a registered function.
|
||||||
macro_rules! make_func {
|
macro_rules! make_func {
|
||||||
($fn_name:ident : $fn:ident : $map:expr ; $($par:ident => $convert:expr),*) => {
|
($fn:ident : $map:expr ; $($par:ident => $convert:expr),*) => {
|
||||||
// ^ function name
|
|
||||||
// ^ function pointer
|
// ^ function pointer
|
||||||
// ^ result mapping function
|
// ^ result mapping function
|
||||||
// ^ function parameter generic type name (A, B, C etc.)
|
// ^ function parameter generic type name (A, B, C etc.)
|
||||||
// ^ dereferencing function
|
// ^ dereferencing function
|
||||||
|
|
||||||
move |args: &mut FnCallArgs, pos: Position| {
|
NativeFunction::new(Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
||||||
// 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)]
|
||||||
@ -156,12 +156,12 @@ macro_rules! make_func {
|
|||||||
|
|
||||||
// Map the result
|
// Map the result
|
||||||
$map(r, pos)
|
$map(r, pos)
|
||||||
};
|
}));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To Dynamic mapping function.
|
/// To Dynamic mapping function.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn map_dynamic<T: Variant + Clone>(
|
pub fn map_dynamic<T: Variant + Clone>(
|
||||||
data: T,
|
data: T,
|
||||||
_pos: Position,
|
_pos: Position,
|
||||||
@ -170,13 +170,13 @@ pub fn map_dynamic<T: Variant + Clone>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// To Dynamic mapping function.
|
/// To Dynamic mapping function.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn map_identity(data: Dynamic, _pos: Position) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn map_identity(data: Dynamic, _pos: Position) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To `Result<Dynamic, Box<EvalAltResult>>` mapping function.
|
/// To `Result<Dynamic, Box<EvalAltResult>>` mapping function.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn map_result<T: Variant + Clone>(
|
pub fn map_result<T: Variant + Clone>(
|
||||||
data: Result<T, Box<EvalAltResult>>,
|
data: Result<T, Box<EvalAltResult>>,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
@ -207,8 +207,7 @@ macro_rules! def_register {
|
|||||||
> RegisterFn<FN, ($($mark,)*), RET> for Engine
|
> RegisterFn<FN, ($($mark,)*), RET> for Engine
|
||||||
{
|
{
|
||||||
fn register_fn(&mut self, name: &str, f: FN) {
|
fn register_fn(&mut self, name: &str, f: FN) {
|
||||||
let fn_name = name.to_string();
|
let func = make_func!(f : map_dynamic ; $($par => $clone),*);
|
||||||
let func = make_func!(fn_name : f : map_dynamic ; $($par => $clone),*);
|
|
||||||
let hash = calc_fn_spec(empty(), name, [$(TypeId::of::<$par>()),*].iter().cloned());
|
let hash = calc_fn_spec(empty(), name, [$(TypeId::of::<$par>()),*].iter().cloned());
|
||||||
self.base_package.functions.insert(hash, Box::new(func));
|
self.base_package.functions.insert(hash, Box::new(func));
|
||||||
}
|
}
|
||||||
@ -225,8 +224,7 @@ macro_rules! def_register {
|
|||||||
> RegisterDynamicFn<FN, ($($mark,)*)> for Engine
|
> RegisterDynamicFn<FN, ($($mark,)*)> for Engine
|
||||||
{
|
{
|
||||||
fn register_dynamic_fn(&mut self, name: &str, f: FN) {
|
fn register_dynamic_fn(&mut self, name: &str, f: FN) {
|
||||||
let fn_name = name.to_string();
|
let func = make_func!(f : map_identity ; $($par => $clone),*);
|
||||||
let func = make_func!(fn_name : f : map_identity ; $($par => $clone),*);
|
|
||||||
let hash = calc_fn_spec(empty(), name, [$(TypeId::of::<$par>()),*].iter().cloned());
|
let hash = calc_fn_spec(empty(), name, [$(TypeId::of::<$par>()),*].iter().cloned());
|
||||||
self.base_package.functions.insert(hash, Box::new(func));
|
self.base_package.functions.insert(hash, Box::new(func));
|
||||||
}
|
}
|
||||||
@ -244,8 +242,7 @@ macro_rules! def_register {
|
|||||||
> RegisterResultFn<FN, ($($mark,)*), RET> for Engine
|
> RegisterResultFn<FN, ($($mark,)*), RET> for Engine
|
||||||
{
|
{
|
||||||
fn register_result_fn(&mut self, name: &str, f: FN) {
|
fn register_result_fn(&mut self, name: &str, f: FN) {
|
||||||
let fn_name = name.to_string();
|
let func = make_func!(f : map_result ; $($par => $clone),*);
|
||||||
let func = make_func!(fn_name : f : map_result ; $($par => $clone),*);
|
|
||||||
let hash = calc_fn_spec(empty(), name, [$(TypeId::of::<$par>()),*].iter().cloned());
|
let hash = calc_fn_spec(empty(), name, [$(TypeId::of::<$par>()),*].iter().cloned());
|
||||||
self.base_package.functions.insert(hash, Box::new(func));
|
self.base_package.functions.insert(hash, Box::new(func));
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,7 @@ mod engine;
|
|||||||
mod error;
|
mod error;
|
||||||
mod fn_call;
|
mod fn_call;
|
||||||
mod fn_func;
|
mod fn_func;
|
||||||
|
mod fn_native;
|
||||||
mod fn_register;
|
mod fn_register;
|
||||||
mod module;
|
mod module;
|
||||||
mod optimize;
|
mod optimize;
|
||||||
@ -90,6 +91,7 @@ pub use any::Dynamic;
|
|||||||
pub use engine::Engine;
|
pub use engine::Engine;
|
||||||
pub use error::{ParseError, ParseErrorType};
|
pub use error::{ParseError, ParseErrorType};
|
||||||
pub use fn_call::FuncArgs;
|
pub use fn_call::FuncArgs;
|
||||||
|
pub use fn_native::NativeCallable;
|
||||||
pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn};
|
pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn};
|
||||||
pub use parser::{AST, INT};
|
pub use parser::{AST, INT};
|
||||||
pub use result::EvalAltResult;
|
pub use result::EvalAltResult;
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
|
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::{Engine, FnAny, FnCallArgs, FunctionsLib, NativeFunction, ScriptedFunction};
|
use crate::engine::{Engine, FunctionsLib};
|
||||||
use crate::parser::{FnAccess, FnDef, AST};
|
use crate::fn_native::{FnAny, FnCallArgs, NativeCallable, NativeFunction, SharedNativeFunction};
|
||||||
|
use crate::parser::{FnAccess, FnDef, SharedFnDef, AST};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::scope::{Entry as ScopeEntry, EntryType as ScopeEntryType, Scope};
|
use crate::scope::{Entry as ScopeEntry, EntryType as ScopeEntryType, Scope};
|
||||||
use crate::token::{Position, Token};
|
use crate::token::{Position, Token};
|
||||||
@ -57,10 +58,10 @@ pub struct Module {
|
|||||||
all_variables: HashMap<u64, Dynamic>,
|
all_variables: HashMap<u64, Dynamic>,
|
||||||
|
|
||||||
/// External Rust functions.
|
/// External Rust functions.
|
||||||
functions: HashMap<u64, (String, FnAccess, Vec<TypeId>, NativeFunction)>,
|
functions: HashMap<u64, (String, FnAccess, Vec<TypeId>, SharedNativeFunction)>,
|
||||||
|
|
||||||
/// Flattened collection of all external Rust functions, including those in sub-modules.
|
/// Flattened collection of all external Rust functions, including those in sub-modules.
|
||||||
all_functions: HashMap<u64, NativeFunction>,
|
all_functions: HashMap<u64, SharedNativeFunction>,
|
||||||
|
|
||||||
/// Script-defined functions.
|
/// Script-defined functions.
|
||||||
fn_lib: FunctionsLib,
|
fn_lib: FunctionsLib,
|
||||||
@ -269,12 +270,14 @@ impl Module {
|
|||||||
) -> u64 {
|
) -> u64 {
|
||||||
let hash = calc_fn_hash(empty(), &fn_name, params.iter().cloned());
|
let hash = calc_fn_hash(empty(), &fn_name, params.iter().cloned());
|
||||||
|
|
||||||
|
let f = Box::new(NativeFunction::from(func)) as Box<dyn NativeCallable>;
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
self.functions
|
let func = Rc::new(f);
|
||||||
.insert(hash, (fn_name, access, params, Rc::new(func)));
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
self.functions
|
let func = Arc::new(f);
|
||||||
.insert(hash, (fn_name, access, params, Arc::new(func)));
|
|
||||||
|
self.functions.insert(hash, (fn_name, access, params, func));
|
||||||
|
|
||||||
hash
|
hash
|
||||||
}
|
}
|
||||||
@ -528,7 +531,7 @@ impl Module {
|
|||||||
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
||||||
/// assert!(module.get_fn(hash).is_some());
|
/// assert!(module.get_fn(hash).is_some());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get_fn(&self, hash: u64) -> Option<&Box<FnAny>> {
|
pub fn get_fn(&self, hash: u64) -> Option<&Box<dyn NativeCallable>> {
|
||||||
self.functions.get(&hash).map(|(_, _, _, v)| v.as_ref())
|
self.functions.get(&hash).map(|(_, _, _, v)| v.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,7 +544,7 @@ impl Module {
|
|||||||
name: &str,
|
name: &str,
|
||||||
hash: u64,
|
hash: u64,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<&Box<FnAny>, Box<EvalAltResult>> {
|
) -> Result<&Box<dyn NativeCallable>, Box<EvalAltResult>> {
|
||||||
self.all_functions
|
self.all_functions
|
||||||
.get(&hash)
|
.get(&hash)
|
||||||
.map(|f| f.as_ref())
|
.map(|f| f.as_ref())
|
||||||
@ -626,8 +629,8 @@ impl Module {
|
|||||||
module: &'a mut Module,
|
module: &'a mut Module,
|
||||||
qualifiers: &mut Vec<&'a str>,
|
qualifiers: &mut Vec<&'a str>,
|
||||||
variables: &mut Vec<(u64, Dynamic)>,
|
variables: &mut Vec<(u64, Dynamic)>,
|
||||||
functions: &mut Vec<(u64, NativeFunction)>,
|
functions: &mut Vec<(u64, SharedNativeFunction)>,
|
||||||
fn_lib: &mut Vec<(u64, ScriptedFunction)>,
|
fn_lib: &mut Vec<(u64, SharedFnDef)>,
|
||||||
) {
|
) {
|
||||||
for (name, m) in module.modules.iter_mut() {
|
for (name, m) in module.modules.iter_mut() {
|
||||||
// Index all the sub-modules first.
|
// Index all the sub-modules first.
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
Engine, FnAny, FnCallArgs, FunctionsLib, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT,
|
Engine, FunctionsLib, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
||||||
KEYWORD_TYPE_OF,
|
|
||||||
};
|
};
|
||||||
|
use crate::fn_native::FnCallArgs;
|
||||||
use crate::packages::{PackageStore, PackagesCollection};
|
use crate::packages::{PackageStore, PackagesCollection};
|
||||||
use crate::parser::{map_dynamic_to_expr, Expr, FnDef, ReturnType, Stmt, AST};
|
use crate::parser::{map_dynamic_to_expr, Expr, FnDef, ReturnType, Stmt, AST};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
@ -123,7 +123,7 @@ fn call_fn(
|
|||||||
base_package
|
base_package
|
||||||
.get_function(hash)
|
.get_function(hash)
|
||||||
.or_else(|| packages.get_function(hash))
|
.or_else(|| packages.get_function(hash))
|
||||||
.map(|func| func(args, pos))
|
.map(|func| func.call(args, pos))
|
||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! This module contains all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
//! This module contains all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
||||||
|
|
||||||
use crate::engine::{FnAny, IteratorFn};
|
use crate::fn_native::{IteratorFn, NativeCallable};
|
||||||
|
|
||||||
use crate::stdlib::{any::TypeId, boxed::Box, collections::HashMap, rc::Rc, sync::Arc, vec::Vec};
|
use crate::stdlib::{any::TypeId, boxed::Box, collections::HashMap, rc::Rc, sync::Arc, vec::Vec};
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ pub trait Package {
|
|||||||
/// Type to store all functions in the package.
|
/// Type to store all functions in the package.
|
||||||
pub struct PackageStore {
|
pub struct PackageStore {
|
||||||
/// All functions, keyed by a hash created from the function name and parameter types.
|
/// All functions, keyed by a hash created from the function name and parameter types.
|
||||||
pub functions: HashMap<u64, Box<FnAny>>,
|
pub functions: HashMap<u64, Box<dyn NativeCallable>>,
|
||||||
|
|
||||||
/// All iterator functions, keyed by the type producing the iterator.
|
/// All iterator functions, keyed by the type producing the iterator.
|
||||||
pub type_iterators: HashMap<TypeId, Box<IteratorFn>>,
|
pub type_iterators: HashMap<TypeId, Box<IteratorFn>>,
|
||||||
@ -64,7 +64,7 @@ impl PackageStore {
|
|||||||
self.functions.contains_key(&hash)
|
self.functions.contains_key(&hash)
|
||||||
}
|
}
|
||||||
/// Get specified function via its hash key.
|
/// Get specified function via its hash key.
|
||||||
pub fn get_function(&self, hash: u64) -> Option<&Box<FnAny>> {
|
pub fn get_function(&self, hash: u64) -> Option<&Box<dyn NativeCallable>> {
|
||||||
self.functions.get(&hash)
|
self.functions.get(&hash)
|
||||||
}
|
}
|
||||||
/// Does the specified TypeId iterator exist in the `PackageStore`?
|
/// Does the specified TypeId iterator exist in the `PackageStore`?
|
||||||
@ -113,7 +113,7 @@ impl PackagesCollection {
|
|||||||
self.packages.iter().any(|p| p.contains_function(hash))
|
self.packages.iter().any(|p| p.contains_function(hash))
|
||||||
}
|
}
|
||||||
/// Get specified function via its hash key.
|
/// Get specified function via its hash key.
|
||||||
pub fn get_function(&self, hash: u64) -> Option<&Box<FnAny>> {
|
pub fn get_function(&self, hash: u64) -> Option<&Box<dyn NativeCallable>> {
|
||||||
self.packages
|
self.packages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.get_function(hash))
|
.map(|p| p.get_function(hash))
|
||||||
|
@ -2,7 +2,7 @@ use super::PackageStore;
|
|||||||
|
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::FnCallArgs;
|
use crate::fn_native::{FnCallArgs, NativeFunction};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ pub fn reg_none<R>(
|
|||||||
map_result(r, pos)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.functions.insert(hash, f);
|
lib.functions.insert(hash, Box::new(NativeFunction::new(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with one parameter to the package.
|
/// Add a function with one parameter to the package.
|
||||||
@ -157,7 +157,7 @@ pub fn reg_unary<T: Variant + Clone, R>(
|
|||||||
map_result(r, pos)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.functions.insert(hash, f);
|
lib.functions.insert(hash, Box::new(NativeFunction::new(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with one mutable reference parameter to the package.
|
/// Add a function with one mutable reference parameter to the package.
|
||||||
@ -215,7 +215,7 @@ pub fn reg_unary_mut<T: Variant + Clone, R>(
|
|||||||
map_result(r, pos)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.functions.insert(hash, f);
|
lib.functions.insert(hash, Box::new(NativeFunction::new(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with two parameters to the package.
|
/// Add a function with two parameters to the package.
|
||||||
@ -271,7 +271,7 @@ pub fn reg_binary<A: Variant + Clone, B: Variant + Clone, R>(
|
|||||||
map_result(r, pos)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.functions.insert(hash, f);
|
lib.functions.insert(hash, Box::new(NativeFunction::new(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with two parameters (the first one being a mutable reference) to the package.
|
/// Add a function with two parameters (the first one being a mutable reference) to the package.
|
||||||
@ -334,7 +334,7 @@ pub fn reg_binary_mut<A: Variant + Clone, B: Variant + Clone, R>(
|
|||||||
map_result(r, pos)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.functions.insert(hash, f);
|
lib.functions.insert(hash, Box::new(NativeFunction::new(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with three parameters to the package.
|
/// Add a function with three parameters to the package.
|
||||||
@ -374,7 +374,7 @@ pub fn reg_trinary<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R
|
|||||||
map_result(r, pos)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.functions.insert(hash, f);
|
lib.functions.insert(hash, Box::new(NativeFunction::new(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a function with three parameters (the first one is a mutable reference) to the package.
|
/// Add a function with three parameters (the first one is a mutable reference) to the package.
|
||||||
@ -414,5 +414,5 @@ pub fn reg_trinary_mut<A: Variant + Clone, B: Variant + Clone, C: Variant + Clon
|
|||||||
map_result(r, pos)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
lib.functions.insert(hash, f);
|
lib.functions.insert(hash, Box::new(NativeFunction::new(f)));
|
||||||
}
|
}
|
||||||
|
@ -202,6 +202,13 @@ pub struct FnDef {
|
|||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A sharable script-defined function.
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
pub type SharedFnDef = Arc<FnDef>;
|
||||||
|
/// A sharable script-defined function.
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
pub type SharedFnDef = Rc<FnDef>;
|
||||||
|
|
||||||
/// `return`/`throw` statement.
|
/// `return`/`throw` statement.
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
pub enum ReturnType {
|
pub enum ReturnType {
|
||||||
|
Loading…
Reference in New Issue
Block a user