Simplify API by introducing the Dynamic and Array type aliases.
This commit is contained in:
parent
2e296ff9d7
commit
51abc4a2c1
29
src/any.rs
29
src/any.rs
@ -1,12 +1,15 @@
|
|||||||
use std::any::{type_name, Any as StdAny, TypeId};
|
use std::any::{type_name, Any as StdAny, TypeId};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
pub type Variant = dyn Any;
|
||||||
|
pub type Dynamic = Box<Variant>;
|
||||||
|
|
||||||
pub trait Any: StdAny {
|
pub trait Any: StdAny {
|
||||||
fn type_id(&self) -> TypeId;
|
fn type_id(&self) -> TypeId;
|
||||||
|
|
||||||
fn type_name(&self) -> String;
|
fn type_name(&self) -> String;
|
||||||
|
|
||||||
fn box_clone(&self) -> Box<dyn Any>;
|
fn into_dynamic(&self) -> Dynamic;
|
||||||
|
|
||||||
/// This type may only be implemented by `rhai`.
|
/// This type may only be implemented by `rhai`.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -27,7 +30,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn box_clone(&self) -> Box<dyn Any> {
|
fn into_dynamic(&self) -> Dynamic {
|
||||||
Box::new(self.clone())
|
Box::new(self.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,15 +39,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl dyn Any {
|
impl Variant {
|
||||||
//#[inline]
|
//#[inline]
|
||||||
// fn box_clone(&self) -> Box<dyn Any> {
|
// fn into_dynamic(&self) -> Box<Variant> {
|
||||||
// Any::box_clone(self)
|
// Any::into_dynamic(self)
|
||||||
// }
|
// }
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is<T: Any>(&self) -> bool {
|
pub fn is<T: Any>(&self) -> bool {
|
||||||
let t = TypeId::of::<T>();
|
let t = TypeId::of::<T>();
|
||||||
let boxed = <dyn Any as Any>::type_id(self);
|
let boxed = <Variant as Any>::type_id(self);
|
||||||
|
|
||||||
t == boxed
|
t == boxed
|
||||||
}
|
}
|
||||||
@ -52,7 +55,7 @@ impl dyn Any {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
||||||
if self.is::<T>() {
|
if self.is::<T>() {
|
||||||
unsafe { Some(&*(self as *const dyn Any as *const T)) }
|
unsafe { Some(&*(self as *const Variant as *const T)) }
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -61,20 +64,20 @@ impl dyn Any {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
||||||
if self.is::<T>() {
|
if self.is::<T>() {
|
||||||
unsafe { Some(&mut *(self as *mut dyn Any as *mut T)) }
|
unsafe { Some(&mut *(self as *mut Variant as *mut T)) }
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Box<dyn Any> {
|
impl Clone for Dynamic {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Any::box_clone(self.as_ref() as &dyn Any)
|
Any::into_dynamic(self.as_ref() as &Variant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for dyn Any {
|
impl fmt::Debug for Variant {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.pad("?")
|
f.pad("?")
|
||||||
}
|
}
|
||||||
@ -84,11 +87,11 @@ pub trait AnyExt: Sized {
|
|||||||
fn downcast<T: Any + Clone>(self) -> Result<Box<T>, Self>;
|
fn downcast<T: Any + Clone>(self) -> Result<Box<T>, Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnyExt for Box<dyn Any> {
|
impl AnyExt for Dynamic {
|
||||||
fn downcast<T: Any + Clone>(self) -> Result<Box<T>, Self> {
|
fn downcast<T: Any + Clone>(self) -> Result<Box<T>, Self> {
|
||||||
if self.is::<T>() {
|
if self.is::<T>() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let raw: *mut dyn Any = Box::into_raw(self);
|
let raw: *mut Variant = Box::into_raw(self);
|
||||||
Ok(Box::from_raw(raw as *mut T))
|
Ok(Box::from_raw(raw as *mut T))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
12
src/call.rs
12
src/call.rs
@ -1,24 +1,22 @@
|
|||||||
//! Helper module which defines `FnArgs`
|
//! Helper module which defines `FnArgs`
|
||||||
//! to make function calling easier.
|
//! to make function calling easier.
|
||||||
|
|
||||||
use crate::any::Any;
|
use crate::any::{Any, Variant};
|
||||||
|
|
||||||
pub trait FunArgs<'a> {
|
pub trait FunArgs<'a> {
|
||||||
fn into_vec(self) -> Vec<&'a mut dyn Any>;
|
fn into_vec(self) -> Vec<&'a mut Variant>;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_args {
|
macro_rules! impl_args {
|
||||||
($($p:ident),*) => {
|
($($p:ident),*) => {
|
||||||
impl<'a, $($p),*> FunArgs<'a> for ($(&'a mut $p,)*)
|
impl<'a, $($p: Any + Clone),*> FunArgs<'a> for ($(&'a mut $p,)*)
|
||||||
where
|
|
||||||
$($p: Any + Clone),*
|
|
||||||
{
|
{
|
||||||
fn into_vec(self) -> Vec<&'a mut dyn Any> {
|
fn into_vec(self) -> Vec<&'a mut Variant> {
|
||||||
let ($($p,)*) = self;
|
let ($($p,)*) = self;
|
||||||
|
|
||||||
#[allow(unused_variables, unused_mut)]
|
#[allow(unused_variables, unused_mut)]
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
$(v.push($p as &mut dyn Any);)*
|
$(v.push($p as &mut Variant);)*
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,14 @@ use std::fmt;
|
|||||||
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub};
|
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub};
|
||||||
use std::{convert::TryInto, sync::Arc};
|
use std::{convert::TryInto, sync::Arc};
|
||||||
|
|
||||||
use crate::any::{Any, AnyExt};
|
use crate::any::{Any, AnyExt, Dynamic, Variant};
|
||||||
use crate::call::FunArgs;
|
use crate::call::FunArgs;
|
||||||
use crate::fn_register::{RegisterBoxFn, RegisterFn};
|
use crate::fn_register::{RegisterBoxFn, RegisterFn};
|
||||||
use crate::parser::{lex, parse, Expr, FnDef, ParseError, Stmt, AST};
|
use crate::parser::{lex, parse, Expr, FnDef, ParseError, Stmt, AST};
|
||||||
use fmt::{Debug, Display};
|
use fmt::{Debug, Display};
|
||||||
|
|
||||||
type Array = Vec<Box<dyn Any>>;
|
pub type Array = Vec<Dynamic>;
|
||||||
|
pub type FnCallArgs<'a> = Vec<&'a mut Variant>;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum EvalAltResult {
|
pub enum EvalAltResult {
|
||||||
@ -30,7 +31,7 @@ pub enum EvalAltResult {
|
|||||||
ErrorCantOpenScriptFile(String),
|
ErrorCantOpenScriptFile(String),
|
||||||
ErrorMalformedDotExpression,
|
ErrorMalformedDotExpression,
|
||||||
LoopBreak,
|
LoopBreak,
|
||||||
Return(Box<dyn Any>),
|
Return(Dynamic),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EvalAltResult {
|
impl EvalAltResult {
|
||||||
@ -131,7 +132,7 @@ pub struct FnSpec {
|
|||||||
args: Option<Vec<TypeId>>,
|
args: Option<Vec<TypeId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type IteratorFn = dyn Fn(&Box<dyn Any>) -> Box<dyn Iterator<Item = Box<dyn Any>>>;
|
type IteratorFn = dyn Fn(&Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
|
||||||
|
|
||||||
/// Rhai's engine type. This is what you use to run Rhai scripts
|
/// Rhai's engine type. This is what you use to run Rhai scripts
|
||||||
///
|
///
|
||||||
@ -160,7 +161,7 @@ pub enum FnIntExt {
|
|||||||
Int(FnDef),
|
Int(FnDef),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FnAny = dyn Fn(Vec<&mut dyn Any>) -> Result<Box<dyn Any>, EvalAltResult>;
|
pub type FnAny = dyn Fn(FnCallArgs) -> Result<Dynamic, EvalAltResult>;
|
||||||
|
|
||||||
/// A type containing information about current scope.
|
/// A type containing information about current scope.
|
||||||
/// Useful for keeping state between `Engine` runs
|
/// Useful for keeping state between `Engine` runs
|
||||||
@ -176,7 +177,7 @@ pub type FnAny = dyn Fn(Vec<&mut dyn Any>) -> Result<Box<dyn Any>, EvalAltResult
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Between runs, `Engine` only remembers functions when not using own `Scope`.
|
/// Between runs, `Engine` only remembers functions when not using own `Scope`.
|
||||||
pub type Scope = Vec<(String, Box<dyn Any>)>;
|
pub type Scope = Vec<(String, Dynamic)>;
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
pub fn call_fn<'a, I, A, T>(&self, ident: I, args: A) -> Result<T, EvalAltResult>
|
pub fn call_fn<'a, I, A, T>(&self, ident: I, args: A) -> Result<T, EvalAltResult>
|
||||||
@ -195,11 +196,7 @@ impl Engine {
|
|||||||
|
|
||||||
/// Universal method for calling functions, that are either
|
/// Universal method for calling functions, that are either
|
||||||
/// registered with the `Engine` or written in Rhai
|
/// registered with the `Engine` or written in Rhai
|
||||||
pub fn call_fn_raw(
|
pub fn call_fn_raw(&self, ident: String, args: FnCallArgs) -> Result<Dynamic, EvalAltResult> {
|
||||||
&self,
|
|
||||||
ident: String,
|
|
||||||
args: Vec<&mut dyn Any>,
|
|
||||||
) -> Result<Box<dyn Any>, EvalAltResult> {
|
|
||||||
debug_println!(
|
debug_println!(
|
||||||
"Trying to call function {:?} with args {:?}",
|
"Trying to call function {:?} with args {:?}",
|
||||||
ident,
|
ident,
|
||||||
@ -225,7 +222,7 @@ impl Engine {
|
|||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let typenames = args
|
let typenames = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| (*(&**x).box_clone()).type_name())
|
.map(|x| (*(&**x).into_dynamic()).type_name())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
EvalAltResult::ErrorFunctionNotFound(format!(
|
EvalAltResult::ErrorFunctionNotFound(format!(
|
||||||
"{} ({})",
|
"{} ({})",
|
||||||
@ -260,7 +257,7 @@ impl Engine {
|
|||||||
f.params
|
f.params
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.zip(args.iter().map(|x| (&**x).box_clone())),
|
.zip(args.iter().map(|x| (&**x).into_dynamic())),
|
||||||
);
|
);
|
||||||
|
|
||||||
match self.eval_stmt(&mut scope, &*f.body) {
|
match self.eval_stmt(&mut scope, &*f.body) {
|
||||||
@ -288,13 +285,13 @@ impl Engine {
|
|||||||
/// Register an iterator adapter for a type.
|
/// Register an iterator adapter for a type.
|
||||||
pub fn register_iterator<T: Any, F>(&mut self, f: F)
|
pub fn register_iterator<T: Any, F>(&mut self, f: F)
|
||||||
where
|
where
|
||||||
F: 'static + Fn(&Box<dyn Any>) -> Box<dyn Iterator<Item = Box<dyn Any>>>,
|
F: 'static + Fn(&Dynamic) -> Box<dyn Iterator<Item = Dynamic>>,
|
||||||
{
|
{
|
||||||
self.type_iterators.insert(TypeId::of::<T>(), Arc::new(f));
|
self.type_iterators.insert(TypeId::of::<T>(), Arc::new(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a get function for a member of a registered type
|
/// Register a get function for a member of a registered type
|
||||||
pub fn register_get<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, get_fn: F)
|
pub fn register_get<T: Any + Clone, U: Any + Clone, F>(&mut self, name: &str, get_fn: F)
|
||||||
where
|
where
|
||||||
F: 'static + Fn(&mut T) -> U,
|
F: 'static + Fn(&mut T) -> U,
|
||||||
{
|
{
|
||||||
@ -303,7 +300,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Register a set function for a member of a registered type
|
/// Register a set function for a member of a registered type
|
||||||
pub fn register_set<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, set_fn: F)
|
pub fn register_set<T: Any + Clone, U: Any + Clone, F>(&mut self, name: &str, set_fn: F)
|
||||||
where
|
where
|
||||||
F: 'static + Fn(&mut T, U) -> (),
|
F: 'static + Fn(&mut T, U) -> (),
|
||||||
{
|
{
|
||||||
@ -312,7 +309,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Shorthand for registering both getters and setters
|
/// Shorthand for registering both getters and setters
|
||||||
pub fn register_get_set<T: Clone + Any, U: Clone + Any, F, G>(
|
pub fn register_get_set<T: Any + Clone, U: Any + Clone, F, G>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
get_fn: F,
|
get_fn: F,
|
||||||
@ -328,9 +325,9 @@ impl Engine {
|
|||||||
fn get_dot_val_helper(
|
fn get_dot_val_helper(
|
||||||
&self,
|
&self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut dyn Any,
|
this_ptr: &mut Variant,
|
||||||
dot_rhs: &Expr,
|
dot_rhs: &Expr,
|
||||||
) -> Result<Box<dyn Any>, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
|
|
||||||
match *dot_rhs {
|
match *dot_rhs {
|
||||||
@ -389,7 +386,7 @@ impl Engine {
|
|||||||
map: F,
|
map: F,
|
||||||
) -> Result<(usize, T), EvalAltResult>
|
) -> Result<(usize, T), EvalAltResult>
|
||||||
where
|
where
|
||||||
F: FnOnce(&'a mut dyn Any) -> Result<T, EvalAltResult>,
|
F: FnOnce(&'a mut Variant) -> Result<T, EvalAltResult>,
|
||||||
{
|
{
|
||||||
scope
|
scope
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@ -405,7 +402,7 @@ impl Engine {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
id: &str,
|
id: &str,
|
||||||
idx: &Expr,
|
idx: &Expr,
|
||||||
) -> Result<(usize, usize, Box<dyn Any>), EvalAltResult> {
|
) -> Result<(usize, usize, Dynamic), EvalAltResult> {
|
||||||
let idx_boxed = self
|
let idx_boxed = self
|
||||||
.eval_expr(scope, idx)?
|
.eval_expr(scope, idx)?
|
||||||
.downcast::<i64>()
|
.downcast::<i64>()
|
||||||
@ -433,10 +430,10 @@ impl Engine {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
dot_lhs: &Expr,
|
dot_lhs: &Expr,
|
||||||
dot_rhs: &Expr,
|
dot_rhs: &Expr,
|
||||||
) -> Result<Box<dyn Any>, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
match *dot_lhs {
|
match *dot_lhs {
|
||||||
Expr::Identifier(ref id) => {
|
Expr::Identifier(ref id) => {
|
||||||
let (sc_idx, mut target) = Self::search_scope(scope, id, |x| Ok(x.box_clone()))?;
|
let (sc_idx, mut target) = Self::search_scope(scope, id, |x| Ok(x.into_dynamic()))?;
|
||||||
let value = self.get_dot_val_helper(scope, target.as_mut(), dot_rhs);
|
let value = self.get_dot_val_helper(scope, target.as_mut(), dot_rhs);
|
||||||
|
|
||||||
// In case the expression mutated `target`, we need to reassign it because
|
// In case the expression mutated `target`, we need to reassign it because
|
||||||
@ -461,10 +458,10 @@ impl Engine {
|
|||||||
|
|
||||||
fn set_dot_val_helper(
|
fn set_dot_val_helper(
|
||||||
&self,
|
&self,
|
||||||
this_ptr: &mut dyn Any,
|
this_ptr: &mut Variant,
|
||||||
dot_rhs: &Expr,
|
dot_rhs: &Expr,
|
||||||
mut source_val: Box<dyn Any>,
|
mut source_val: Dynamic,
|
||||||
) -> Result<Box<dyn Any>, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
match *dot_rhs {
|
match *dot_rhs {
|
||||||
Expr::Identifier(ref id) => {
|
Expr::Identifier(ref id) => {
|
||||||
let set_fn_name = "set$".to_string() + id;
|
let set_fn_name = "set$".to_string() + id;
|
||||||
@ -495,11 +492,11 @@ impl Engine {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
dot_lhs: &Expr,
|
dot_lhs: &Expr,
|
||||||
dot_rhs: &Expr,
|
dot_rhs: &Expr,
|
||||||
source_val: Box<dyn Any>,
|
source_val: Dynamic,
|
||||||
) -> Result<Box<dyn Any>, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
match *dot_lhs {
|
match *dot_lhs {
|
||||||
Expr::Identifier(ref id) => {
|
Expr::Identifier(ref id) => {
|
||||||
let (sc_idx, mut target) = Self::search_scope(scope, id, |x| Ok(x.box_clone()))?;
|
let (sc_idx, mut target) = Self::search_scope(scope, id, |x| Ok(x.into_dynamic()))?;
|
||||||
let value = self.set_dot_val_helper(target.as_mut(), dot_rhs, source_val);
|
let value = self.set_dot_val_helper(target.as_mut(), dot_rhs, source_val);
|
||||||
|
|
||||||
// In case the expression mutated `target`, we need to reassign it because
|
// In case the expression mutated `target`, we need to reassign it because
|
||||||
@ -522,7 +519,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_expr(&self, scope: &mut Scope, expr: &Expr) -> Result<Box<dyn Any>, EvalAltResult> {
|
fn eval_expr(&self, scope: &mut Scope, expr: &Expr) -> Result<Dynamic, EvalAltResult> {
|
||||||
match *expr {
|
match *expr {
|
||||||
Expr::IntegerConstant(i) => Ok(Box::new(i)),
|
Expr::IntegerConstant(i) => Ok(Box::new(i)),
|
||||||
Expr::FloatConstant(i) => Ok(Box::new(i)),
|
Expr::FloatConstant(i) => Ok(Box::new(i)),
|
||||||
@ -616,12 +613,12 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_stmt(&self, scope: &mut Scope, stmt: &Stmt) -> Result<Box<dyn Any>, EvalAltResult> {
|
fn eval_stmt(&self, scope: &mut Scope, stmt: &Stmt) -> Result<Dynamic, EvalAltResult> {
|
||||||
match *stmt {
|
match *stmt {
|
||||||
Stmt::Expr(ref e) => self.eval_expr(scope, e),
|
Stmt::Expr(ref e) => self.eval_expr(scope, e),
|
||||||
Stmt::Block(ref b) => {
|
Stmt::Block(ref b) => {
|
||||||
let prev_len = scope.len();
|
let prev_len = scope.len();
|
||||||
let mut last_result: Result<Box<dyn Any>, EvalAltResult> = Ok(Box::new(()));
|
let mut last_result: Result<Dynamic, EvalAltResult> = Ok(Box::new(()));
|
||||||
|
|
||||||
for s in b.iter() {
|
for s in b.iter() {
|
||||||
last_result = self.eval_stmt(scope, s);
|
last_result = self.eval_stmt(scope, s);
|
||||||
@ -801,7 +798,7 @@ impl Engine {
|
|||||||
ast: &AST,
|
ast: &AST,
|
||||||
) -> Result<T, EvalAltResult> {
|
) -> Result<T, EvalAltResult> {
|
||||||
let AST(os, fns) = ast;
|
let AST(os, fns) = ast;
|
||||||
let mut x: Result<Box<dyn Any>, EvalAltResult> = Ok(Box::new(()));
|
let mut x: Result<Dynamic, EvalAltResult> = Ok(Box::new(()));
|
||||||
|
|
||||||
for f in fns {
|
for f in fns {
|
||||||
let name = f.name.clone();
|
let name = f.name.clone();
|
||||||
@ -1093,8 +1090,14 @@ impl Engine {
|
|||||||
reg_func2x!(engine, "push", push, &mut Array, (), f32, f64, bool);
|
reg_func2x!(engine, "push", push, &mut Array, (), f32, f64, bool);
|
||||||
reg_func2x!(engine, "push", push, &mut Array, (), String, Array, ());
|
reg_func2x!(engine, "push", push, &mut Array, (), String, Array, ());
|
||||||
|
|
||||||
engine.register_box_fn("pop", |list: &mut Array| list.pop().unwrap());
|
engine.register_dynamic_fn("pop", |list: &mut Array| list.pop().unwrap_or(Box::new(())));
|
||||||
engine.register_box_fn("shift", |list: &mut Array| list.remove(0));
|
engine.register_dynamic_fn("shift", |list: &mut Array| {
|
||||||
|
if list.len() > 0 {
|
||||||
|
list.remove(0)
|
||||||
|
} else {
|
||||||
|
Box::new(())
|
||||||
|
}
|
||||||
|
});
|
||||||
engine.register_fn("len", |list: &mut Array| -> i64 {
|
engine.register_fn("len", |list: &mut Array| -> i64 {
|
||||||
list.len().try_into().unwrap()
|
list.len().try_into().unwrap()
|
||||||
});
|
});
|
||||||
@ -1127,7 +1130,7 @@ impl Engine {
|
|||||||
a.downcast_ref::<Range<i64>>()
|
a.downcast_ref::<Range<i64>>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone()
|
.clone()
|
||||||
.map(|n| Box::new(n) as Box<dyn Any>),
|
.map(|n| Box::new(n) as Dynamic),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
|
||||||
use crate::any::Any;
|
use crate::any::{Any, Dynamic};
|
||||||
use crate::engine::{Engine, EvalAltResult};
|
use crate::engine::{Engine, EvalAltResult, FnCallArgs};
|
||||||
|
|
||||||
pub trait RegisterFn<FN, ARGS, RET> {
|
pub trait RegisterFn<FN, ARGS, RET> {
|
||||||
fn register_fn(&mut self, name: &str, f: FN);
|
fn register_fn(&mut self, name: &str, f: FN);
|
||||||
}
|
}
|
||||||
pub trait RegisterBoxFn<FN, ARGS> {
|
pub trait RegisterBoxFn<FN, ARGS> {
|
||||||
fn register_box_fn(&mut self, name: &str, f: FN);
|
fn register_dynamic_fn(&mut self, name: &str, f: FN);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Ref<A>(A);
|
pub struct Ref<A>(A);
|
||||||
@ -23,14 +23,14 @@ macro_rules! def_register {
|
|||||||
def_register!(imp);
|
def_register!(imp);
|
||||||
};
|
};
|
||||||
(imp $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => {
|
(imp $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => {
|
||||||
impl<$($par,)* FN, RET> RegisterFn<FN, ($($mark,)*), RET> for Engine
|
impl<
|
||||||
where
|
|
||||||
$($par: Any + Clone,)*
|
$($par: Any + Clone,)*
|
||||||
FN: Fn($($param),*) -> RET + 'static,
|
FN: Fn($($param),*) -> RET + 'static,
|
||||||
RET: Any,
|
RET: Any
|
||||||
|
> 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 fun = move |mut args: Vec<&mut dyn Any>| {
|
let fun = move |mut args: FnCallArgs| {
|
||||||
// Check for length at the beginning to avoid
|
// Check for length at the beginning to avoid
|
||||||
// per-element bound checks.
|
// per-element bound checks.
|
||||||
if args.len() != count_args!($($par)*) {
|
if args.len() != count_args!($($par)*) {
|
||||||
@ -48,19 +48,19 @@ macro_rules! def_register {
|
|||||||
// Call the user-supplied function using ($clone) to
|
// Call the user-supplied function using ($clone) to
|
||||||
// potentially clone the value, otherwise pass the reference.
|
// potentially clone the value, otherwise pass the reference.
|
||||||
let r = f($(($clone)($par)),*);
|
let r = f($(($clone)($par)),*);
|
||||||
Ok(Box::new(r) as Box<dyn Any>)
|
Ok(Box::new(r) as Dynamic)
|
||||||
};
|
};
|
||||||
self.register_fn_raw(name.to_owned(), Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
self.register_fn_raw(name.to_owned(), Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($par,)* FN> RegisterBoxFn<FN, ($($mark,)*)> for Engine
|
impl<
|
||||||
where
|
|
||||||
$($par: Any + Clone,)*
|
$($par: Any + Clone,)*
|
||||||
FN: Fn($($param),*) -> Box<dyn Any> + 'static
|
FN: Fn($($param),*) -> Dynamic + 'static,
|
||||||
|
> RegisterBoxFn<FN, ($($mark,)*)> for Engine
|
||||||
{
|
{
|
||||||
fn register_box_fn(&mut self, name: &str, f: FN) {
|
fn register_dynamic_fn(&mut self, name: &str, f: FN) {
|
||||||
let fun = move |mut args: Vec<&mut dyn Any>| {
|
let fun = move |mut args: FnCallArgs| {
|
||||||
// Check for length at the beginning to avoid
|
// Check for length at the beginning to avoid
|
||||||
// per-element bound checks.
|
// per-element bound checks.
|
||||||
if args.len() != count_args!($($par)*) {
|
if args.len() != count_args!($($par)*) {
|
||||||
|
@ -45,7 +45,7 @@ mod engine;
|
|||||||
mod fn_register;
|
mod fn_register;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
pub use any::Any;
|
pub use any::Dynamic;
|
||||||
pub use engine::{Engine, EvalAltResult, Scope};
|
pub use engine::{Array, Engine, EvalAltResult, Scope};
|
||||||
pub use fn_register::{RegisterBoxFn, RegisterFn};
|
pub use fn_register::{RegisterBoxFn, RegisterFn};
|
||||||
pub use parser::{ParseError, ParseErrorType, AST};
|
pub use parser::{ParseError, ParseErrorType, AST};
|
||||||
|
Loading…
Reference in New Issue
Block a user