Unify all functions under CallableFunction type.
This commit is contained in:
parent
a22f338b03
commit
3295060dba
@ -3,7 +3,7 @@
|
|||||||
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, NativeFunctionABI, PrintCallback, ProgressCallback};
|
use crate::fn_native::{FnCallArgs, PrintCallback, ProgressCallback};
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
use crate::packages::{CorePackage, Package, PackageLibrary, PackagesCollection, StandardPackage};
|
use crate::packages::{CorePackage, Package, PackageLibrary, PackagesCollection, StandardPackage};
|
||||||
@ -229,15 +229,7 @@ impl FunctionsLib {
|
|||||||
// Qualifiers (none) + function name + placeholders (one for each parameter).
|
// Qualifiers (none) + function name + placeholders (one for each parameter).
|
||||||
let args_iter = repeat(EMPTY_TYPE_ID()).take(fn_def.params.len());
|
let args_iter = repeat(EMPTY_TYPE_ID()).take(fn_def.params.len());
|
||||||
let hash = calc_fn_hash(empty(), &fn_def.name, args_iter);
|
let hash = calc_fn_hash(empty(), &fn_def.name, args_iter);
|
||||||
|
(hash, fn_def.into())
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
{
|
|
||||||
(hash, Arc::new(fn_def))
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
{
|
|
||||||
(hash, Rc::new(fn_def))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
@ -268,8 +260,7 @@ impl FunctionsLib {
|
|||||||
match fn_def.as_ref().map(|f| f.access) {
|
match fn_def.as_ref().map(|f| f.access) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(FnAccess::Private) if public_only => None,
|
Some(FnAccess::Private) if public_only => None,
|
||||||
Some(FnAccess::Private) => fn_def,
|
Some(FnAccess::Private) | Some(FnAccess::Public) => fn_def,
|
||||||
Some(FnAccess::Public) => fn_def,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Merge another `FunctionsLib` into this `FunctionsLib`.
|
/// Merge another `FunctionsLib` into this `FunctionsLib`.
|
||||||
@ -659,25 +650,20 @@ impl Engine {
|
|||||||
.get_fn(hashes.0)
|
.get_fn(hashes.0)
|
||||||
.or_else(|| self.packages.get_fn(hashes.0))
|
.or_else(|| self.packages.get_fn(hashes.0))
|
||||||
{
|
{
|
||||||
let mut backup: Dynamic = Default::default();
|
// Calling pure function in method-call?
|
||||||
|
let backup: Option<Dynamic> = if func.is_pure() && is_ref && args.len() > 0 {
|
||||||
let (updated, restore) = match func.abi() {
|
|
||||||
// Calling pure function in method-call
|
|
||||||
NativeFunctionABI::Pure if is_ref && args.len() > 0 => {
|
|
||||||
// Backup the original value. It'll be consumed because the function
|
// Backup the original value. It'll be consumed because the function
|
||||||
// is pure and doesn't know that the first value is a reference (i.e. `is_ref`)
|
// is pure and doesn't know that the first value is a reference (i.e. `is_ref`)
|
||||||
backup = args[0].clone();
|
Some(args[0].clone())
|
||||||
(false, true)
|
} else {
|
||||||
}
|
None
|
||||||
NativeFunctionABI::Pure => (false, false),
|
|
||||||
NativeFunctionABI::Method => (true, false),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run external function
|
// Run external function
|
||||||
let result = match func.call(args) {
|
let result = match func.get_native_fn()(args) {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
// Restore the backup value for the first argument since it has been consumed!
|
// Restore the backup value for the first argument since it has been consumed!
|
||||||
if restore {
|
if let Some(backup) = backup {
|
||||||
*args[0] = backup;
|
*args[0] = backup;
|
||||||
}
|
}
|
||||||
r
|
r
|
||||||
@ -709,7 +695,7 @@ impl Engine {
|
|||||||
.into(),
|
.into(),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
_ => (result, updated),
|
_ => (result, func.is_method()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,14 +766,12 @@ impl Engine {
|
|||||||
let scope_len = scope.len();
|
let scope_len = scope.len();
|
||||||
|
|
||||||
// Put arguments into scope as variables
|
// Put arguments into scope as variables
|
||||||
|
// Actually consume the arguments instead of cloning them
|
||||||
scope.extend(
|
scope.extend(
|
||||||
fn_def
|
fn_def
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.zip(
|
.zip(args.iter_mut().map(|v| mem::take(*v)))
|
||||||
// Actually consume the arguments instead of cloning them
|
|
||||||
args.into_iter().map(|v| mem::take(*v)),
|
|
||||||
)
|
|
||||||
.map(|(name, value)| {
|
.map(|(name, value)| {
|
||||||
let var_name =
|
let var_name =
|
||||||
unsafe_cast_var_name_to_lifetime(name.as_str(), &mut state);
|
unsafe_cast_var_name_to_lifetime(name.as_str(), &mut state);
|
||||||
@ -826,14 +810,12 @@ impl Engine {
|
|||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
|
|
||||||
// Put arguments into scope as variables
|
// Put arguments into scope as variables
|
||||||
|
// Actually consume the arguments instead of cloning them
|
||||||
scope.extend(
|
scope.extend(
|
||||||
fn_def
|
fn_def
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.zip(
|
.zip(args.iter_mut().map(|v| mem::take(*v)))
|
||||||
// Actually consume the arguments instead of cloning them
|
|
||||||
args.into_iter().map(|v| mem::take(*v)),
|
|
||||||
)
|
|
||||||
.map(|(name, value)| (name, ScopeEntryType::Normal, value)),
|
.map(|(name, value)| (name, ScopeEntryType::Normal, value)),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1558,13 +1540,8 @@ 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(fn_def) = module.get_qualified_scripted_fn(*hash_fn_def) {
|
let func = match module.get_qualified_fn(name, *hash_fn_def) {
|
||||||
let args = args.as_mut();
|
Err(err) if matches!(*err, EvalAltResult::ErrorFunctionNotFound(_, _)) => {
|
||||||
let (result, state2) =
|
|
||||||
self.call_script_fn(None, *state, name, fn_def, args, *pos, level)?;
|
|
||||||
*state = state2;
|
|
||||||
Ok(result)
|
|
||||||
} else {
|
|
||||||
// Then search in Rust functions
|
// Then search in Rust functions
|
||||||
self.inc_operations(state, *pos)?;
|
self.inc_operations(state, *pos)?;
|
||||||
|
|
||||||
@ -1573,17 +1550,33 @@ impl Engine {
|
|||||||
// i.e. qualifiers + function name + dummy parameter types (one for each parameter).
|
// i.e. qualifiers + function name + dummy parameter types (one for each parameter).
|
||||||
// 2) Calculate a second hash with no qualifiers, empty function name, and
|
// 2) Calculate a second hash with no qualifiers, empty function name, and
|
||||||
// the actual list of parameter `TypeId`'.s
|
// the actual list of parameter `TypeId`'.s
|
||||||
let hash_fn_args = calc_fn_hash(empty(), "", args.iter().map(|a| a.type_id()));
|
let hash_fn_args =
|
||||||
|
calc_fn_hash(empty(), "", args.iter().map(|a| a.type_id()));
|
||||||
// 3) The final hash is the XOR of the two hashes.
|
// 3) The final hash is the XOR of the two hashes.
|
||||||
let hash_fn_native = *hash_fn_def ^ hash_fn_args;
|
let hash_fn_native = *hash_fn_def ^ hash_fn_args;
|
||||||
|
|
||||||
match module.get_qualified_fn(name, hash_fn_native) {
|
module.get_qualified_fn(name, hash_fn_native)
|
||||||
Ok(func) => func
|
|
||||||
.call(args.as_mut())
|
|
||||||
.map_err(|err| err.new_position(*pos)),
|
|
||||||
Err(_) if def_val.is_some() => Ok(def_val.clone().unwrap()),
|
|
||||||
Err(err) => Err(err),
|
|
||||||
}
|
}
|
||||||
|
r => r,
|
||||||
|
};
|
||||||
|
|
||||||
|
match func {
|
||||||
|
Ok(x) if x.is_script() => {
|
||||||
|
let args = args.as_mut();
|
||||||
|
let fn_def = x.get_fn_def();
|
||||||
|
let (result, state2) =
|
||||||
|
self.call_script_fn(None, *state, name, fn_def, args, *pos, level)?;
|
||||||
|
*state = state2;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
Ok(x) => x.get_native_fn()(args.as_mut()).map_err(|err| err.new_position(*pos)),
|
||||||
|
Err(err)
|
||||||
|
if def_val.is_some()
|
||||||
|
&& matches!(*err, EvalAltResult::ErrorFunctionNotFound(_, _)) =>
|
||||||
|
{
|
||||||
|
Ok(def_val.clone().unwrap())
|
||||||
|
}
|
||||||
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1733,7 +1726,7 @@ impl Engine {
|
|||||||
let iter_type = self.eval_expr(scope, state, expr, level)?;
|
let iter_type = self.eval_expr(scope, state, expr, level)?;
|
||||||
let tid = iter_type.type_id();
|
let tid = iter_type.type_id();
|
||||||
|
|
||||||
if let Some(iter_fn) = self
|
if let Some(func) = self
|
||||||
.global_module
|
.global_module
|
||||||
.get_iter(tid)
|
.get_iter(tid)
|
||||||
.or_else(|| self.packages.get_iter(tid))
|
.or_else(|| self.packages.get_iter(tid))
|
||||||
@ -1744,7 +1737,7 @@ impl Engine {
|
|||||||
let index = scope.len() - 1;
|
let index = scope.len() - 1;
|
||||||
state.scope_level += 1;
|
state.scope_level += 1;
|
||||||
|
|
||||||
for loop_var in iter_fn(iter_type) {
|
for loop_var in func.get_iter_fn()(iter_type) {
|
||||||
*scope.get_mut(index).0 = loop_var;
|
*scope.get_mut(index).0 = loop_var;
|
||||||
self.inc_operations(state, stmt.position())?;
|
self.inc_operations(state, stmt.position())?;
|
||||||
|
|
||||||
|
155
src/fn_native.rs
155
src/fn_native.rs
@ -1,4 +1,5 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
|
use crate::parser::{FnDef, SharedFnDef};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
|
|
||||||
use crate::stdlib::{boxed::Box, rc::Rc, sync::Arc};
|
use crate::stdlib::{boxed::Box, rc::Rc, sync::Arc};
|
||||||
@ -72,70 +73,98 @@ pub trait IteratorCallback: Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + '
|
|||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
impl<F: Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + 'static> IteratorCallback for F {}
|
impl<F: Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + 'static> IteratorCallback for F {}
|
||||||
|
|
||||||
/// A type representing the type of ABI of a native Rust function.
|
/// A type encapsulating a function callable by Rhai.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
pub enum CallableFunction {
|
||||||
pub enum NativeFunctionABI {
|
/// A pure native Rust function with all arguments passed by value.
|
||||||
/// A pure function where all arguments are passed by value.
|
Pure(Box<FnAny>),
|
||||||
Pure,
|
/// A native Rust object method with the first argument passed by reference,
|
||||||
/// An object method where the first argument is the object passed by mutable reference.
|
/// and the rest passed by value.
|
||||||
/// All other arguments are passed by value.
|
Method(Box<FnAny>),
|
||||||
Method,
|
/// An iterator function.
|
||||||
|
Iterator(Box<IteratorFn>),
|
||||||
|
/// A script-defined function.
|
||||||
|
Script(SharedFnDef),
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
impl CallableFunction {
|
||||||
/// Trait implemented by all native Rust functions that are callable by Rhai.
|
/// Is this a pure native Rust function?
|
||||||
|
pub fn is_pure(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CallableFunction::Pure(_) => true,
|
||||||
|
CallableFunction::Method(_)
|
||||||
|
| CallableFunction::Iterator(_)
|
||||||
|
| CallableFunction::Script(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Is this a pure native Rust method-call?
|
||||||
|
pub fn is_method(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CallableFunction::Method(_) => true,
|
||||||
|
CallableFunction::Pure(_)
|
||||||
|
| CallableFunction::Iterator(_)
|
||||||
|
| CallableFunction::Script(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Is this an iterator function?
|
||||||
|
pub fn is_iter(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CallableFunction::Iterator(_) => true,
|
||||||
|
CallableFunction::Pure(_)
|
||||||
|
| CallableFunction::Method(_)
|
||||||
|
| CallableFunction::Script(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Is this a Rhai-scripted function?
|
||||||
|
pub fn is_script(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CallableFunction::Script(_) => true,
|
||||||
|
CallableFunction::Pure(_)
|
||||||
|
| CallableFunction::Method(_)
|
||||||
|
| CallableFunction::Iterator(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Get a reference to a native Rust function.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the `CallableFunction` is not `Pure` or `Method`.
|
||||||
|
pub fn get_native_fn(&self) -> &Box<FnAny> {
|
||||||
|
match self {
|
||||||
|
CallableFunction::Pure(f) | CallableFunction::Method(f) => f,
|
||||||
|
CallableFunction::Iterator(_) | CallableFunction::Script(_) => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Get a reference to a script-defined function definition.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the `CallableFunction` is not `Script`.
|
||||||
|
pub fn get_fn_def(&self) -> &FnDef {
|
||||||
|
match self {
|
||||||
|
CallableFunction::Pure(_)
|
||||||
|
| CallableFunction::Method(_)
|
||||||
|
| CallableFunction::Iterator(_) => panic!(),
|
||||||
|
CallableFunction::Script(f) => f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Get a reference to an iterator function.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the `CallableFunction` is not `Iterator`.
|
||||||
|
pub fn get_iter_fn(&self) -> &Box<IteratorFn> {
|
||||||
|
match self {
|
||||||
|
CallableFunction::Pure(_)
|
||||||
|
| CallableFunction::Method(_)
|
||||||
|
| CallableFunction::Script(_) => panic!(),
|
||||||
|
CallableFunction::Iterator(f) => f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A callable function.
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
pub trait NativeCallable {
|
pub type SharedFunction = Rc<CallableFunction>;
|
||||||
/// Get the ABI type of a native Rust function.
|
/// A callable function.
|
||||||
fn abi(&self) -> NativeFunctionABI;
|
|
||||||
/// Call a native Rust function.
|
|
||||||
fn call(&self, args: &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait implemented by all native Rust functions that are callable by Rhai.
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub trait NativeCallable: Send + Sync {
|
pub type SharedFunction = Arc<CallableFunction>;
|
||||||
/// Get the ABI type of a native Rust function.
|
|
||||||
fn abi(&self) -> NativeFunctionABI;
|
|
||||||
/// Call a native Rust function.
|
|
||||||
fn call(&self, args: &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// A type encapsulating a native Rust function callable by Rhai.
|
|
||||||
pub struct NativeFunction(Box<FnAny>, NativeFunctionABI);
|
|
||||||
|
|
||||||
impl NativeFunction {
|
|
||||||
pub fn abi(&self) -> NativeFunctionABI {
|
|
||||||
self.1
|
|
||||||
}
|
|
||||||
pub fn call(&self, args: &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
(self.0)(args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(Box<FnAny>, NativeFunctionABI)> for NativeFunction {
|
|
||||||
fn from(func: (Box<FnAny>, NativeFunctionABI)) -> Self {
|
|
||||||
Self::new(func.0, func.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl NativeFunction {
|
|
||||||
/// Create a new `NativeFunction`.
|
|
||||||
pub fn new(func: Box<FnAny>, abi: NativeFunctionABI) -> Self {
|
|
||||||
Self(func, abi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An external native Rust function.
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub type SharedNativeFunction = Rc<NativeFunction>;
|
|
||||||
/// An external native Rust function.
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub type SharedNativeFunction = Arc<NativeFunction>;
|
|
||||||
|
|
||||||
/// A type iterator function.
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
pub type SharedIteratorFunction = Rc<Box<IteratorFn>>;
|
|
||||||
/// An external native Rust function.
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
pub type SharedIteratorFunction = Arc<Box<IteratorFn>>;
|
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
use crate::fn_native::{FnCallArgs, NativeFunctionABI::*};
|
use crate::fn_native::{
|
||||||
|
CallableFunction::{Method, Pure},
|
||||||
|
FnCallArgs,
|
||||||
|
};
|
||||||
use crate::parser::FnAccess;
|
use crate::parser::FnAccess;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
|
|
||||||
@ -181,9 +184,9 @@ pub fn map_result<T: Variant + Clone>(
|
|||||||
|
|
||||||
macro_rules! def_register {
|
macro_rules! def_register {
|
||||||
() => {
|
() => {
|
||||||
def_register!(imp Pure;);
|
def_register!(imp Pure :);
|
||||||
};
|
};
|
||||||
(imp $abi:expr ; $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => {
|
(imp $abi:ident : $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => {
|
||||||
// ^ function ABI type
|
// ^ function ABI type
|
||||||
// ^ function parameter generic type name (A, B, C etc.)
|
// ^ function parameter generic type name (A, B, C etc.)
|
||||||
// ^ function parameter marker type (T, Ref<T> or Mut<T>)
|
// ^ function parameter marker type (T, Ref<T> or Mut<T>)
|
||||||
@ -202,9 +205,9 @@ 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) {
|
||||||
self.global_module.set_fn(name.to_string(), $abi, FnAccess::Public,
|
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
||||||
&[$(TypeId::of::<$par>()),*],
|
&[$(TypeId::of::<$par>()),*],
|
||||||
make_func!(f : map_dynamic ; $($par => $clone),*)
|
$abi(make_func!(f : map_dynamic ; $($par => $clone),*))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,9 +223,9 @@ 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) {
|
||||||
self.global_module.set_fn(name.to_string(), $abi, FnAccess::Public,
|
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
||||||
&[$(TypeId::of::<$par>()),*],
|
&[$(TypeId::of::<$par>()),*],
|
||||||
make_func!(f : map_identity ; $($par => $clone),*)
|
$abi(make_func!(f : map_identity ; $($par => $clone),*))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,9 +242,9 @@ 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) {
|
||||||
self.global_module.set_fn(name.to_string(), $abi, FnAccess::Public,
|
self.global_module.set_fn(name.to_string(), FnAccess::Public,
|
||||||
&[$(TypeId::of::<$par>()),*],
|
&[$(TypeId::of::<$par>()),*],
|
||||||
make_func!(f : map_result ; $($par => $clone),*)
|
$abi(make_func!(f : map_result ; $($par => $clone),*))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,8 +252,9 @@ macro_rules! def_register {
|
|||||||
//def_register!(imp_pop $($par => $mark => $param),*);
|
//def_register!(imp_pop $($par => $mark => $param),*);
|
||||||
};
|
};
|
||||||
($p0:ident $(, $p:ident)*) => {
|
($p0:ident $(, $p:ident)*) => {
|
||||||
def_register!(imp Pure ; $p0 => $p0 => $p0 => by_value $(, $p => $p => $p => by_value)*);
|
def_register!(imp Pure : $p0 => $p0 => $p0 => by_value $(, $p => $p => $p => by_value)*);
|
||||||
def_register!(imp Method ; $p0 => Mut<$p0> => &mut $p0 => by_ref $(, $p => $p => $p => by_value)*);
|
def_register!(imp Method : $p0 => Mut<$p0> => &mut $p0 => by_ref $(, $p => $p => $p => by_value)*);
|
||||||
|
// ^ CallableFunction
|
||||||
// handle the first parameter ^ first parameter passed through
|
// handle the first parameter ^ first parameter passed through
|
||||||
// ^ others passed by value (by_value)
|
// ^ others passed by value (by_value)
|
||||||
|
|
||||||
|
@ -91,7 +91,6 @@ mod utils;
|
|||||||
pub use any::Dynamic;
|
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_native::NativeCallable;
|
|
||||||
pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn};
|
pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn};
|
||||||
pub use module::Module;
|
pub use module::Module;
|
||||||
pub use parser::{AST, INT};
|
pub use parser::{AST, INT};
|
||||||
|
@ -4,10 +4,11 @@ use crate::any::{Dynamic, Variant};
|
|||||||
use crate::calc_fn_hash;
|
use crate::calc_fn_hash;
|
||||||
use crate::engine::{Engine, FunctionsLib};
|
use crate::engine::{Engine, FunctionsLib};
|
||||||
use crate::fn_native::{
|
use crate::fn_native::{
|
||||||
FnAny, FnCallArgs, IteratorFn, NativeFunction, NativeFunctionABI, NativeFunctionABI::*,
|
CallableFunction,
|
||||||
SharedIteratorFunction, SharedNativeFunction,
|
CallableFunction::{Method, Pure},
|
||||||
|
FnCallArgs, IteratorFn, SharedFunction,
|
||||||
};
|
};
|
||||||
use crate::parser::{FnAccess, FnDef, SharedFnDef, AST};
|
use crate::parser::{FnAccess, 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};
|
||||||
@ -51,19 +52,17 @@ pub struct Module {
|
|||||||
all_variables: HashMap<u64, Dynamic>,
|
all_variables: HashMap<u64, Dynamic>,
|
||||||
|
|
||||||
/// External Rust functions.
|
/// External Rust functions.
|
||||||
functions: HashMap<u64, (String, FnAccess, StaticVec<TypeId>, SharedNativeFunction)>,
|
functions: HashMap<u64, (String, FnAccess, StaticVec<TypeId>, SharedFunction)>,
|
||||||
|
|
||||||
/// Flattened collection of all external Rust functions, including those in sub-modules.
|
|
||||||
all_functions: HashMap<u64, SharedNativeFunction>,
|
|
||||||
|
|
||||||
/// Script-defined functions.
|
/// Script-defined functions.
|
||||||
fn_lib: FunctionsLib,
|
fn_lib: FunctionsLib,
|
||||||
|
|
||||||
/// Flattened collection of all script-defined functions, including those in sub-modules.
|
|
||||||
all_fn_lib: FunctionsLib,
|
|
||||||
|
|
||||||
/// Iterator functions, keyed by the type producing the iterator.
|
/// Iterator functions, keyed by the type producing the iterator.
|
||||||
type_iterators: HashMap<TypeId, SharedIteratorFunction>,
|
type_iterators: HashMap<TypeId, SharedFunction>,
|
||||||
|
|
||||||
|
/// Flattened collection of all external Rust functions, native or scripted,
|
||||||
|
/// including those in sub-modules.
|
||||||
|
all_functions: HashMap<u64, SharedFunction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Module {
|
impl fmt::Debug for Module {
|
||||||
@ -278,23 +277,16 @@ impl Module {
|
|||||||
pub fn set_fn(
|
pub fn set_fn(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: String,
|
name: String,
|
||||||
abi: NativeFunctionABI,
|
|
||||||
access: FnAccess,
|
access: FnAccess,
|
||||||
params: &[TypeId],
|
params: &[TypeId],
|
||||||
func: Box<FnAny>,
|
func: CallableFunction,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let hash_fn = calc_fn_hash(empty(), &name, params.iter().cloned());
|
let hash_fn = calc_fn_hash(empty(), &name, params.iter().cloned());
|
||||||
|
|
||||||
let f = NativeFunction::from((func, abi));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
let func = Rc::new(f);
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
let func = Arc::new(f);
|
|
||||||
|
|
||||||
let params = params.into_iter().cloned().collect();
|
let params = params.into_iter().cloned().collect();
|
||||||
|
|
||||||
self.functions.insert(hash_fn, (name, access, params, func));
|
self.functions
|
||||||
|
.insert(hash_fn, (name, access, params, func.into()));
|
||||||
|
|
||||||
hash_fn
|
hash_fn
|
||||||
}
|
}
|
||||||
@ -320,7 +312,7 @@ impl Module {
|
|||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &mut FnCallArgs| func().map(Dynamic::from);
|
let f = move |_: &mut FnCallArgs| func().map(Dynamic::from);
|
||||||
let arg_types = [];
|
let arg_types = [];
|
||||||
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Pure(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking one parameter into the module, returning a hash key.
|
/// Set a Rust function taking one parameter into the module, returning a hash key.
|
||||||
@ -345,7 +337,7 @@ impl Module {
|
|||||||
let f =
|
let f =
|
||||||
move |args: &mut FnCallArgs| func(mem::take(args[0]).cast::<A>()).map(Dynamic::from);
|
move |args: &mut FnCallArgs| func(mem::take(args[0]).cast::<A>()).map(Dynamic::from);
|
||||||
let arg_types = [TypeId::of::<A>()];
|
let arg_types = [TypeId::of::<A>()];
|
||||||
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Pure(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking one mutable parameter into the module, returning a hash key.
|
/// Set a Rust function taking one mutable parameter into the module, returning a hash key.
|
||||||
@ -371,7 +363,7 @@ impl Module {
|
|||||||
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
|
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>()];
|
let arg_types = [TypeId::of::<A>()];
|
||||||
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Method(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking two parameters into the module, returning a hash key.
|
/// Set a Rust function taking two parameters into the module, returning a hash key.
|
||||||
@ -402,7 +394,7 @@ impl Module {
|
|||||||
func(a, b).map(Dynamic::from)
|
func(a, b).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
||||||
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Pure(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking two parameters (the first one mutable) into the module,
|
/// Set a Rust function taking two parameters (the first one mutable) into the module,
|
||||||
@ -437,7 +429,7 @@ impl Module {
|
|||||||
func(a, b).map(Dynamic::from)
|
func(a, b).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
||||||
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Method(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking three parameters into the module, returning a hash key.
|
/// Set a Rust function taking three parameters into the module, returning a hash key.
|
||||||
@ -475,7 +467,7 @@ impl Module {
|
|||||||
func(a, b, c).map(Dynamic::from)
|
func(a, b, c).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Pure(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking three parameters (the first one mutable) into the module,
|
/// Set a Rust function taking three parameters (the first one mutable) into the module,
|
||||||
@ -514,7 +506,7 @@ impl Module {
|
|||||||
func(a, b, c).map(Dynamic::from)
|
func(a, b, c).map(Dynamic::from)
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Method(Box::new(f)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a Rust function.
|
/// Get a Rust function.
|
||||||
@ -531,7 +523,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_fn: u64) -> Option<&NativeFunction> {
|
pub fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
|
||||||
self.functions.get(&hash_fn).map(|(_, _, _, v)| v.as_ref())
|
self.functions.get(&hash_fn).map(|(_, _, _, v)| v.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,7 +535,7 @@ impl Module {
|
|||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
hash_fn_native: u64,
|
hash_fn_native: u64,
|
||||||
) -> Result<&NativeFunction, Box<EvalAltResult>> {
|
) -> Result<&CallableFunction, Box<EvalAltResult>> {
|
||||||
self.all_functions
|
self.all_functions
|
||||||
.get(&hash_fn_native)
|
.get(&hash_fn_native)
|
||||||
.map(|f| f.as_ref())
|
.map(|f| f.as_ref())
|
||||||
@ -555,13 +547,6 @@ impl Module {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a modules-qualified script-defined functions.
|
|
||||||
///
|
|
||||||
/// The `u64` hash is calculated by the function `crate::calc_fn_hash`.
|
|
||||||
pub(crate) fn get_qualified_scripted_fn(&mut self, hash_fn_def: u64) -> Option<&FnDef> {
|
|
||||||
self.all_fn_lib.get_function(hash_fn_def)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new `Module` by evaluating an `AST`.
|
/// Create a new `Module` by evaluating an `AST`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -620,13 +605,12 @@ impl Module {
|
|||||||
module: &'a Module,
|
module: &'a 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, SharedNativeFunction)>,
|
functions: &mut Vec<(u64, SharedFunction)>,
|
||||||
fn_lib: &mut Vec<(u64, SharedFnDef)>,
|
|
||||||
) {
|
) {
|
||||||
for (name, m) in &module.modules {
|
for (name, m) in &module.modules {
|
||||||
// Index all the sub-modules first.
|
// Index all the sub-modules first.
|
||||||
qualifiers.push(name);
|
qualifiers.push(name);
|
||||||
index_module(m, qualifiers, variables, functions, fn_lib);
|
index_module(m, qualifiers, variables, functions);
|
||||||
qualifiers.pop();
|
qualifiers.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -672,25 +656,17 @@ impl Module {
|
|||||||
&fn_def.name,
|
&fn_def.name,
|
||||||
repeat(EMPTY_TYPE_ID()).take(fn_def.params.len()),
|
repeat(EMPTY_TYPE_ID()).take(fn_def.params.len()),
|
||||||
);
|
);
|
||||||
fn_lib.push((hash_fn_def, fn_def.clone()));
|
functions.push((hash_fn_def, CallableFunction::Script(fn_def.clone()).into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut variables = Vec::new();
|
let mut variables = Vec::new();
|
||||||
let mut functions = Vec::new();
|
let mut functions = Vec::new();
|
||||||
let mut fn_lib = Vec::new();
|
|
||||||
|
|
||||||
index_module(
|
index_module(self, &mut vec!["root"], &mut variables, &mut functions);
|
||||||
self,
|
|
||||||
&mut vec!["root"],
|
|
||||||
&mut variables,
|
|
||||||
&mut functions,
|
|
||||||
&mut fn_lib,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.all_variables = variables.into_iter().collect();
|
self.all_variables = variables.into_iter().collect();
|
||||||
self.all_functions = functions.into_iter().collect();
|
self.all_functions = functions.into_iter().collect();
|
||||||
self.all_fn_lib = fn_lib.into();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does a type iterator exist in the module?
|
/// Does a type iterator exist in the module?
|
||||||
@ -701,14 +677,16 @@ impl Module {
|
|||||||
/// Set a type iterator into the module.
|
/// Set a type iterator into the module.
|
||||||
pub fn set_iter(&mut self, typ: TypeId, func: Box<IteratorFn>) {
|
pub fn set_iter(&mut self, typ: TypeId, func: Box<IteratorFn>) {
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
self.type_iterators.insert(typ, Rc::new(func));
|
self.type_iterators
|
||||||
|
.insert(typ, Rc::new(CallableFunction::Iterator(func)));
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
self.type_iterators.insert(typ, Arc::new(func));
|
self.type_iterators
|
||||||
|
.insert(typ, Arc::new(CallableFunction::Iterator(func)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the specified type iterator.
|
/// Get the specified type iterator.
|
||||||
pub fn get_iter(&self, id: TypeId) -> Option<&SharedIteratorFunction> {
|
pub fn get_iter(&self, id: TypeId) -> Option<&CallableFunction> {
|
||||||
self.type_iterators.get(&id)
|
self.type_iterators.get(&id).map(|v| v.as_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,12 +119,12 @@ fn call_fn(
|
|||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
|
||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
let hash = calc_fn_hash(empty(), fn_name, args.iter().map(|a| a.type_id()));
|
let hash_fn = calc_fn_hash(empty(), fn_name, args.iter().map(|a| a.type_id()));
|
||||||
|
|
||||||
global_module
|
global_module
|
||||||
.get_fn(hash)
|
.get_fn(hash_fn)
|
||||||
.or_else(|| packages.get_fn(hash))
|
.or_else(|| packages.get_fn(hash_fn))
|
||||||
.map(|func| func.call(args))
|
.map(|func| func.get_native_fn()(args))
|
||||||
.transpose()
|
.transpose()
|
||||||
.map_err(|err| err.new_position(pos))
|
.map_err(|err| err.new_position(pos))
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Module containing all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
//! Module containing all built-in _packages_ available to Rhai, plus facilities to define custom packages.
|
||||||
|
|
||||||
use crate::fn_native::{NativeFunction, SharedIteratorFunction};
|
use crate::fn_native::CallableFunction;
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
use crate::utils::StaticVec;
|
use crate::utils::StaticVec;
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ impl PackagesCollection {
|
|||||||
self.packages.iter().any(|p| p.contains_fn(hash))
|
self.packages.iter().any(|p| p.contains_fn(hash))
|
||||||
}
|
}
|
||||||
/// Get specified function via its hash key.
|
/// Get specified function via its hash key.
|
||||||
pub fn get_fn(&self, hash: u64) -> Option<&NativeFunction> {
|
pub fn get_fn(&self, hash: u64) -> Option<&CallableFunction> {
|
||||||
self.packages
|
self.packages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.get_fn(hash))
|
.map(|p| p.get_fn(hash))
|
||||||
@ -81,7 +81,7 @@ impl PackagesCollection {
|
|||||||
self.packages.iter().any(|p| p.contains_iter(id))
|
self.packages.iter().any(|p| p.contains_iter(id))
|
||||||
}
|
}
|
||||||
/// Get the specified TypeId iterator.
|
/// Get the specified TypeId iterator.
|
||||||
pub fn get_iter(&self, id: TypeId) -> Option<&SharedIteratorFunction> {
|
pub fn get_iter(&self, id: TypeId) -> Option<&CallableFunction> {
|
||||||
self.packages
|
self.packages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.get_iter(id))
|
.map(|p| p.get_iter(id))
|
||||||
|
@ -36,10 +36,6 @@ pub enum EvalAltResult {
|
|||||||
/// An error has occurred inside a called function.
|
/// An error has occurred inside a called function.
|
||||||
/// Wrapped values re the name of the function and the interior error.
|
/// Wrapped values re the name of the function and the interior error.
|
||||||
ErrorInFunctionCall(String, Box<EvalAltResult>, Position),
|
ErrorInFunctionCall(String, Box<EvalAltResult>, Position),
|
||||||
/// Function call has incorrect number of arguments.
|
|
||||||
/// Wrapped values are the name of the function, the number of parameters required
|
|
||||||
/// and the actual number of arguments passed.
|
|
||||||
ErrorFunctionArgsMismatch(String, usize, usize, Position),
|
|
||||||
/// Non-boolean operand encountered for boolean operator. Wrapped value is the operator.
|
/// Non-boolean operand encountered for boolean operator. Wrapped value is the operator.
|
||||||
ErrorBooleanArgMismatch(String, Position),
|
ErrorBooleanArgMismatch(String, Position),
|
||||||
/// Non-character value encountered where a character is required.
|
/// Non-character value encountered where a character is required.
|
||||||
@ -108,9 +104,6 @@ impl EvalAltResult {
|
|||||||
Self::ErrorParsing(p) => p.desc(),
|
Self::ErrorParsing(p) => p.desc(),
|
||||||
Self::ErrorInFunctionCall(_, _, _) => "Error in called function",
|
Self::ErrorInFunctionCall(_, _, _) => "Error in called function",
|
||||||
Self::ErrorFunctionNotFound(_, _) => "Function not found",
|
Self::ErrorFunctionNotFound(_, _) => "Function not found",
|
||||||
Self::ErrorFunctionArgsMismatch(_, _, _, _) => {
|
|
||||||
"Function call with wrong number of arguments"
|
|
||||||
}
|
|
||||||
Self::ErrorBooleanArgMismatch(_, _) => "Boolean operator expects boolean operands",
|
Self::ErrorBooleanArgMismatch(_, _) => "Boolean operator expects boolean operands",
|
||||||
Self::ErrorCharMismatch(_) => "Character expected",
|
Self::ErrorCharMismatch(_) => "Character expected",
|
||||||
Self::ErrorNumericIndexExpr(_) => {
|
Self::ErrorNumericIndexExpr(_) => {
|
||||||
@ -208,21 +201,6 @@ impl fmt::Display for EvalAltResult {
|
|||||||
Self::ErrorLoopBreak(_, pos) => write!(f, "{} ({})", desc, pos),
|
Self::ErrorLoopBreak(_, pos) => write!(f, "{} ({})", desc, pos),
|
||||||
Self::Return(_, pos) => write!(f, "{} ({})", desc, pos),
|
Self::Return(_, pos) => write!(f, "{} ({})", desc, pos),
|
||||||
|
|
||||||
Self::ErrorFunctionArgsMismatch(fn_name, 0, n, pos) => write!(
|
|
||||||
f,
|
|
||||||
"Function '{}' expects no argument but {} found ({})",
|
|
||||||
fn_name, n, pos
|
|
||||||
),
|
|
||||||
Self::ErrorFunctionArgsMismatch(fn_name, 1, n, pos) => write!(
|
|
||||||
f,
|
|
||||||
"Function '{}' expects one argument but {} found ({})",
|
|
||||||
fn_name, n, pos
|
|
||||||
),
|
|
||||||
Self::ErrorFunctionArgsMismatch(fn_name, need, n, pos) => write!(
|
|
||||||
f,
|
|
||||||
"Function '{}' expects {} argument(s) but {} found ({})",
|
|
||||||
fn_name, need, n, pos
|
|
||||||
),
|
|
||||||
Self::ErrorBooleanArgMismatch(op, pos) => {
|
Self::ErrorBooleanArgMismatch(op, pos) => {
|
||||||
write!(f, "{} operator expects boolean operands ({})", op, pos)
|
write!(f, "{} operator expects boolean operands ({})", op, pos)
|
||||||
}
|
}
|
||||||
@ -292,7 +270,6 @@ impl EvalAltResult {
|
|||||||
|
|
||||||
Self::ErrorFunctionNotFound(_, pos)
|
Self::ErrorFunctionNotFound(_, pos)
|
||||||
| Self::ErrorInFunctionCall(_, _, pos)
|
| Self::ErrorInFunctionCall(_, _, pos)
|
||||||
| Self::ErrorFunctionArgsMismatch(_, _, _, pos)
|
|
||||||
| Self::ErrorBooleanArgMismatch(_, pos)
|
| Self::ErrorBooleanArgMismatch(_, pos)
|
||||||
| Self::ErrorCharMismatch(pos)
|
| Self::ErrorCharMismatch(pos)
|
||||||
| Self::ErrorArrayBounds(_, _, pos)
|
| Self::ErrorArrayBounds(_, _, pos)
|
||||||
@ -331,7 +308,6 @@ impl EvalAltResult {
|
|||||||
|
|
||||||
Self::ErrorFunctionNotFound(_, pos)
|
Self::ErrorFunctionNotFound(_, pos)
|
||||||
| Self::ErrorInFunctionCall(_, _, pos)
|
| Self::ErrorInFunctionCall(_, _, pos)
|
||||||
| Self::ErrorFunctionArgsMismatch(_, _, _, pos)
|
|
||||||
| Self::ErrorBooleanArgMismatch(_, pos)
|
| Self::ErrorBooleanArgMismatch(_, pos)
|
||||||
| Self::ErrorCharMismatch(pos)
|
| Self::ErrorCharMismatch(pos)
|
||||||
| Self::ErrorArrayBounds(_, _, pos)
|
| Self::ErrorArrayBounds(_, _, pos)
|
||||||
|
Loading…
Reference in New Issue
Block a user