Remove lifetime from Engine.
This commit is contained in:
parent
4f2350734f
commit
f8e9d66a0b
86
src/api.rs
86
src/api.rs
@ -1,7 +1,7 @@
|
|||||||
//! Module that defines the extern API of `Engine`.
|
//! Module that defines the extern API of `Engine`.
|
||||||
|
|
||||||
use crate::any::{Dynamic, Variant};
|
use crate::any::{Dynamic, Variant};
|
||||||
use crate::engine::{make_getter, make_setter, Engine, FnAny, FnSpec, Map};
|
use crate::engine::{calc_fn_spec, make_getter, make_setter, Engine, FnAny, Map};
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
use crate::fn_call::FuncArgs;
|
use crate::fn_call::FuncArgs;
|
||||||
use crate::fn_register::RegisterFn;
|
use crate::fn_register::RegisterFn;
|
||||||
@ -59,18 +59,16 @@ pub trait IteratorCallback: Fn(&Dynamic) -> Box<dyn Iterator<Item = Dynamic>> +
|
|||||||
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 {}
|
||||||
|
|
||||||
/// Engine public API
|
/// Engine public API
|
||||||
impl<'e> Engine<'e> {
|
impl Engine {
|
||||||
/// Register a custom function.
|
/// Register a custom function.
|
||||||
pub(crate) fn register_fn_raw(&mut self, fn_name: &str, args: Vec<TypeId>, f: Box<FnAny>) {
|
pub(crate) fn register_fn_raw(&mut self, fn_name: &str, args: Vec<TypeId>, f: Box<FnAny>) {
|
||||||
let spec = FnSpec {
|
|
||||||
name: fn_name.to_string().into(),
|
|
||||||
args,
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.functions.is_none() {
|
if self.functions.is_none() {
|
||||||
self.functions = Some(HashMap::new());
|
self.functions = Some(HashMap::new());
|
||||||
}
|
}
|
||||||
self.functions.as_mut().unwrap().insert(spec, f);
|
self.functions
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.insert(calc_fn_spec(fn_name, args.into_iter()), f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a custom type for use with the `Engine`.
|
/// Register a custom type for use with the `Engine`.
|
||||||
@ -969,23 +967,25 @@ impl<'e> Engine<'e> {
|
|||||||
/// ```
|
/// ```
|
||||||
/// # fn main() -> Result<(), rhai::EvalAltResult> {
|
/// # fn main() -> Result<(), rhai::EvalAltResult> {
|
||||||
/// # use std::sync::RwLock;
|
/// # use std::sync::RwLock;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
/// use rhai::Engine;
|
/// use rhai::Engine;
|
||||||
///
|
///
|
||||||
/// let result = RwLock::new(String::from(""));
|
/// let result = Arc::new(RwLock::new(String::from("")));
|
||||||
/// {
|
|
||||||
/// let mut engine = Engine::new();
|
|
||||||
///
|
///
|
||||||
/// // Override action of 'print' function
|
/// let mut engine = Engine::new();
|
||||||
/// engine.on_print(|s| result.write().unwrap().push_str(s));
|
///
|
||||||
|
/// // Override action of 'print' function
|
||||||
|
/// let logger = result.clone();
|
||||||
|
/// engine.on_print(move |s| logger.write().unwrap().push_str(s));
|
||||||
|
///
|
||||||
|
/// engine.consume("print(40 + 2);")?;
|
||||||
///
|
///
|
||||||
/// engine.consume("print(40 + 2);")?;
|
|
||||||
/// }
|
|
||||||
/// assert_eq!(*result.read().unwrap(), "42");
|
/// assert_eq!(*result.read().unwrap(), "42");
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub fn on_print(&mut self, callback: impl Fn(&str) + Send + Sync + 'e) {
|
pub fn on_print(&mut self, callback: impl Fn(&str) + Send + Sync + 'static) {
|
||||||
self.on_print = Some(Box::new(callback));
|
self.on_print = Some(Box::new(callback));
|
||||||
}
|
}
|
||||||
/// Override default action of `print` (print to stdout using `println!`)
|
/// Override default action of `print` (print to stdout using `println!`)
|
||||||
@ -995,23 +995,25 @@ impl<'e> Engine<'e> {
|
|||||||
/// ```
|
/// ```
|
||||||
/// # fn main() -> Result<(), rhai::EvalAltResult> {
|
/// # fn main() -> Result<(), rhai::EvalAltResult> {
|
||||||
/// # use std::sync::RwLock;
|
/// # use std::sync::RwLock;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
/// use rhai::Engine;
|
/// use rhai::Engine;
|
||||||
///
|
///
|
||||||
/// let result = RwLock::new(String::from(""));
|
/// let result = Arc::new(RwLock::new(String::from("")));
|
||||||
/// {
|
|
||||||
/// let mut engine = Engine::new();
|
|
||||||
///
|
///
|
||||||
/// // Override action of 'print' function
|
/// let mut engine = Engine::new();
|
||||||
/// engine.on_print(|s| result.write().unwrap().push_str(s));
|
///
|
||||||
|
/// // Override action of 'print' function
|
||||||
|
/// let logger = result.clone();
|
||||||
|
/// engine.on_print(move |s| logger.write().unwrap().push_str(s));
|
||||||
|
///
|
||||||
|
/// engine.consume("print(40 + 2);")?;
|
||||||
///
|
///
|
||||||
/// engine.consume("print(40 + 2);")?;
|
|
||||||
/// }
|
|
||||||
/// assert_eq!(*result.read().unwrap(), "42");
|
/// assert_eq!(*result.read().unwrap(), "42");
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
pub fn on_print(&mut self, callback: impl Fn(&str) + 'e) {
|
pub fn on_print(&mut self, callback: impl Fn(&str) + 'static) {
|
||||||
self.on_print = Some(Box::new(callback));
|
self.on_print = Some(Box::new(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1022,23 +1024,25 @@ impl<'e> Engine<'e> {
|
|||||||
/// ```
|
/// ```
|
||||||
/// # fn main() -> Result<(), rhai::EvalAltResult> {
|
/// # fn main() -> Result<(), rhai::EvalAltResult> {
|
||||||
/// # use std::sync::RwLock;
|
/// # use std::sync::RwLock;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
/// use rhai::Engine;
|
/// use rhai::Engine;
|
||||||
///
|
///
|
||||||
/// let result = RwLock::new(String::from(""));
|
/// let result = Arc::new(RwLock::new(String::from("")));
|
||||||
/// {
|
|
||||||
/// let mut engine = Engine::new();
|
|
||||||
///
|
///
|
||||||
/// // Override action of 'print' function
|
/// let mut engine = Engine::new();
|
||||||
/// engine.on_debug(|s| result.write().unwrap().push_str(s));
|
///
|
||||||
|
/// // Override action of 'print' function
|
||||||
|
/// let logger = result.clone();
|
||||||
|
/// engine.on_debug(move |s| logger.write().unwrap().push_str(s));
|
||||||
|
///
|
||||||
|
/// engine.consume(r#"debug("hello");"#)?;
|
||||||
///
|
///
|
||||||
/// engine.consume(r#"debug("hello");"#)?;
|
|
||||||
/// }
|
|
||||||
/// assert_eq!(*result.read().unwrap(), r#""hello""#);
|
/// assert_eq!(*result.read().unwrap(), r#""hello""#);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub fn on_debug(&mut self, callback: impl Fn(&str) + Send + Sync + 'e) {
|
pub fn on_debug(&mut self, callback: impl Fn(&str) + Send + Sync + 'static) {
|
||||||
self.on_debug = Some(Box::new(callback));
|
self.on_debug = Some(Box::new(callback));
|
||||||
}
|
}
|
||||||
/// Override default action of `debug` (print to stdout using `println!`)
|
/// Override default action of `debug` (print to stdout using `println!`)
|
||||||
@ -1048,23 +1052,25 @@ impl<'e> Engine<'e> {
|
|||||||
/// ```
|
/// ```
|
||||||
/// # fn main() -> Result<(), rhai::EvalAltResult> {
|
/// # fn main() -> Result<(), rhai::EvalAltResult> {
|
||||||
/// # use std::sync::RwLock;
|
/// # use std::sync::RwLock;
|
||||||
|
/// # use std::sync::Arc;
|
||||||
/// use rhai::Engine;
|
/// use rhai::Engine;
|
||||||
///
|
///
|
||||||
/// let result = RwLock::new(String::from(""));
|
/// let result = Arc::new(RwLock::new(String::from("")));
|
||||||
/// {
|
|
||||||
/// let mut engine = Engine::new();
|
|
||||||
///
|
///
|
||||||
/// // Override action of 'print' function
|
/// let mut engine = Engine::new();
|
||||||
/// engine.on_debug(|s| result.write().unwrap().push_str(s));
|
///
|
||||||
|
/// // Override action of 'print' function
|
||||||
|
/// let logger = result.clone();
|
||||||
|
/// engine.on_debug(move |s| logger.write().unwrap().push_str(s));
|
||||||
|
///
|
||||||
|
/// engine.consume(r#"debug("hello");"#)?;
|
||||||
///
|
///
|
||||||
/// engine.consume(r#"debug("hello");"#)?;
|
|
||||||
/// }
|
|
||||||
/// assert_eq!(*result.read().unwrap(), r#""hello""#);
|
/// assert_eq!(*result.read().unwrap(), r#""hello""#);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
pub fn on_debug(&mut self, callback: impl Fn(&str) + 'e) {
|
pub fn on_debug(&mut self, callback: impl Fn(&str) + 'static) {
|
||||||
self.on_debug = Some(Box::new(callback));
|
self.on_debug = Some(Box::new(callback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ fn ne<T: PartialEq>(x: T, y: T) -> bool {
|
|||||||
x != y
|
x != y
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engine<'_> {
|
impl Engine {
|
||||||
/// Register the core built-in library.
|
/// Register the core built-in library.
|
||||||
pub(crate) fn register_core_lib(&mut self) {
|
pub(crate) fn register_core_lib(&mut self) {
|
||||||
// Checked add
|
// Checked add
|
||||||
@ -770,7 +770,7 @@ macro_rules! reg_fn2y {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Register the built-in library.
|
/// Register the built-in library.
|
||||||
impl Engine<'_> {
|
impl Engine {
|
||||||
pub fn register_stdlib(&mut self) {
|
pub fn register_stdlib(&mut self) {
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
{
|
{
|
||||||
|
@ -10,17 +10,16 @@ use crate::token::Position;
|
|||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
borrow::Cow,
|
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::HashMap,
|
collections::{hash_map::DefaultHasher, HashMap},
|
||||||
format,
|
format,
|
||||||
|
hash::{Hash, Hasher},
|
||||||
iter::once,
|
iter::once,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
vec,
|
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -114,12 +113,6 @@ impl<'a> From<&'a mut Dynamic> for Target<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
|
||||||
pub struct FnSpec<'a> {
|
|
||||||
pub name: Cow<'a, str>,
|
|
||||||
pub args: Vec<TypeId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type that holds a library of script-defined functions.
|
/// A type that holds a library 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
|
||||||
@ -239,9 +232,9 @@ impl DerefMut for FunctionsLib {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Currently, `Engine` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
|
/// Currently, `Engine` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
|
||||||
pub struct Engine<'e> {
|
pub struct Engine {
|
||||||
/// A hashmap containing all compiled functions known to the engine.
|
/// A hashmap containing all compiled functions known to the engine.
|
||||||
pub(crate) functions: Option<HashMap<FnSpec<'e>, Box<FnAny>>>,
|
pub(crate) functions: Option<HashMap<u64, Box<FnAny>>>,
|
||||||
|
|
||||||
/// A hashmap containing all iterators known to the engine.
|
/// A hashmap containing all iterators known to the engine.
|
||||||
pub(crate) type_iterators: Option<HashMap<TypeId, Box<IteratorFn>>>,
|
pub(crate) type_iterators: Option<HashMap<TypeId, Box<IteratorFn>>>,
|
||||||
@ -250,17 +243,17 @@ pub struct Engine<'e> {
|
|||||||
|
|
||||||
/// Closure for implementing the `print` command.
|
/// Closure for implementing the `print` command.
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub(crate) on_print: Option<Box<dyn Fn(&str) + Send + Sync + 'e>>,
|
pub(crate) on_print: Option<Box<dyn Fn(&str) + Send + Sync + 'static>>,
|
||||||
/// Closure for implementing the `print` command.
|
/// Closure for implementing the `print` command.
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
pub(crate) on_print: Option<Box<dyn Fn(&str) + 'e>>,
|
pub(crate) on_print: Option<Box<dyn Fn(&str) + 'static>>,
|
||||||
|
|
||||||
/// Closure for implementing the `debug` command.
|
/// Closure for implementing the `debug` command.
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub(crate) on_debug: Option<Box<dyn Fn(&str) + Send + Sync + 'e>>,
|
pub(crate) on_debug: Option<Box<dyn Fn(&str) + Send + Sync + 'static>>,
|
||||||
/// Closure for implementing the `debug` command.
|
/// Closure for implementing the `debug` command.
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
pub(crate) on_debug: Option<Box<dyn Fn(&str) + 'e>>,
|
pub(crate) on_debug: Option<Box<dyn Fn(&str) + 'static>>,
|
||||||
|
|
||||||
/// Optimize the AST after compilation.
|
/// Optimize the AST after compilation.
|
||||||
pub(crate) optimization_level: OptimizationLevel,
|
pub(crate) optimization_level: OptimizationLevel,
|
||||||
@ -271,7 +264,7 @@ pub struct Engine<'e> {
|
|||||||
pub(crate) max_call_stack_depth: usize,
|
pub(crate) max_call_stack_depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Engine<'_> {
|
impl Default for Engine {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
// Create the new scripting Engine
|
// Create the new scripting Engine
|
||||||
let mut engine = Engine {
|
let mut engine = Engine {
|
||||||
@ -349,7 +342,14 @@ fn extract_prop_from_setter(fn_name: &str) -> Option<&str> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engine<'_> {
|
pub(crate) fn calc_fn_spec(fn_name: &str, params: impl Iterator<Item = TypeId>) -> u64 {
|
||||||
|
let mut s = DefaultHasher::new();
|
||||||
|
fn_name.hash(&mut s);
|
||||||
|
params.for_each(|t| t.hash(&mut s));
|
||||||
|
s.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Engine {
|
||||||
/// Create a new `Engine`
|
/// Create a new `Engine`
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
@ -471,11 +471,6 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let spec = FnSpec {
|
|
||||||
name: fn_name.into(),
|
|
||||||
args: args.iter().map(|a| a.type_id()).collect(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Argument must be a string
|
// Argument must be a string
|
||||||
fn cast_to_string(r: &Dynamic, pos: Position) -> Result<&str, EvalAltResult> {
|
fn cast_to_string(r: &Dynamic, pos: Position) -> Result<&str, EvalAltResult> {
|
||||||
r.as_str()
|
r.as_str()
|
||||||
@ -483,7 +478,9 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
if let Some(func) = self.functions.as_ref().and_then(|f| f.get(&spec)) {
|
let fn_spec = calc_fn_spec(fn_name, args.iter().map(|a| a.type_id()));
|
||||||
|
|
||||||
|
if let Some(func) = self.functions.as_ref().and_then(|f| f.get(&fn_spec)) {
|
||||||
// Run external function
|
// Run external function
|
||||||
let result = func(args, pos)?;
|
let result = func(args, pos)?;
|
||||||
|
|
||||||
@ -519,7 +516,7 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prop) = extract_prop_from_setter(fn_name) {
|
if let Some(prop) = extract_prop_from_setter(fn_name) {
|
||||||
let (arg, value) = args.split_at_mut(0);
|
let (arg, value) = args.split_at_mut(1);
|
||||||
|
|
||||||
return match arg[0] {
|
return match arg[0] {
|
||||||
// Map property update
|
// Map property update
|
||||||
@ -1336,10 +1333,8 @@ impl Engine<'_> {
|
|||||||
name: &str,
|
name: &str,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
engine.functions.as_ref().map_or(false, |lib| {
|
engine.functions.as_ref().map_or(false, |lib| {
|
||||||
lib.contains_key(&FnSpec {
|
let fn_spec = calc_fn_spec(name, [TypeId::of::<String>()].iter().cloned());
|
||||||
name: name.into(),
|
lib.contains_key(&fn_spec)
|
||||||
args: vec![TypeId::of::<String>()],
|
|
||||||
})
|
|
||||||
}) || fn_lib.map_or(false, |lib| lib.has_function(name, 1))
|
}) || fn_lib.map_or(false, |lib| lib.has_function(name, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,13 +88,13 @@ macro_rules! def_anonymous_fn {
|
|||||||
def_anonymous_fn!(imp);
|
def_anonymous_fn!(imp);
|
||||||
};
|
};
|
||||||
(imp $($par:ident),*) => {
|
(imp $($par:ident),*) => {
|
||||||
impl<'e, $($par: Variant + Clone,)* RET: Variant + Clone> Func<($($par,)*), RET> for Engine<'e>
|
impl<$($par: Variant + Clone,)* RET: Variant + Clone> Func<($($par,)*), RET> for Engine
|
||||||
{
|
{
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
type Output = Box<dyn Fn($($par),*) -> Result<RET, EvalAltResult> + Send + Sync + 'e>;
|
type Output = Box<dyn Fn($($par),*) -> Result<RET, EvalAltResult> + Send + Sync>;
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
type Output = Box<dyn Fn($($par),*) -> Result<RET, EvalAltResult> + 'e>;
|
type Output = Box<dyn Fn($($par),*) -> Result<RET, EvalAltResult>>;
|
||||||
|
|
||||||
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
|
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output {
|
||||||
let name = entry_point.to_string();
|
let name = entry_point.to_string();
|
||||||
|
@ -146,7 +146,7 @@ macro_rules! def_register {
|
|||||||
FN: Fn($($param),*) -> RET + 'static,
|
FN: Fn($($param),*) -> RET + 'static,
|
||||||
|
|
||||||
RET: Variant + Clone
|
RET: Variant + Clone
|
||||||
> 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 fn_name = name.to_string();
|
||||||
@ -184,7 +184,7 @@ macro_rules! def_register {
|
|||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
FN: Fn($($param),*) -> Dynamic + 'static,
|
FN: Fn($($param),*) -> Dynamic + 'static,
|
||||||
> 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 fn_name = name.to_string();
|
||||||
@ -221,7 +221,7 @@ macro_rules! def_register {
|
|||||||
FN: Fn($($param),*) -> Result<RET, EvalAltResult> + 'static,
|
FN: Fn($($param),*) -> Result<RET, EvalAltResult> + 'static,
|
||||||
|
|
||||||
RET: Variant + Clone
|
RET: Variant + Clone
|
||||||
> 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 fn_name = name.to_string();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
Engine, FnAny, FnCallArgs, FnSpec, FunctionsLib, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT,
|
calc_fn_spec, Engine, FnAny, FnCallArgs, FunctionsLib, KEYWORD_DEBUG, KEYWORD_EVAL,
|
||||||
KEYWORD_TYPE_OF,
|
KEYWORD_PRINT, KEYWORD_TYPE_OF,
|
||||||
};
|
};
|
||||||
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;
|
||||||
@ -50,7 +50,7 @@ struct State<'a> {
|
|||||||
/// Collection of constants to use for eager function evaluations.
|
/// Collection of constants to use for eager function evaluations.
|
||||||
constants: Vec<(String, Expr)>,
|
constants: Vec<(String, Expr)>,
|
||||||
/// An `Engine` instance for eager function evaluation.
|
/// An `Engine` instance for eager function evaluation.
|
||||||
engine: &'a Engine<'a>,
|
engine: &'a Engine,
|
||||||
/// Library of script-defined functions.
|
/// Library of script-defined functions.
|
||||||
fn_lib: &'a [(&'a str, usize)],
|
fn_lib: &'a [(&'a str, usize)],
|
||||||
/// Optimization level.
|
/// Optimization level.
|
||||||
@ -60,7 +60,7 @@ struct State<'a> {
|
|||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
/// Create a new State.
|
/// Create a new State.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
engine: &'a Engine<'a>,
|
engine: &'a Engine,
|
||||||
fn_lib: &'a [(&'a str, usize)],
|
fn_lib: &'a [(&'a str, usize)],
|
||||||
level: OptimizationLevel,
|
level: OptimizationLevel,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -110,19 +110,14 @@ impl<'a> State<'a> {
|
|||||||
|
|
||||||
/// Call a registered function
|
/// Call a registered function
|
||||||
fn call_fn(
|
fn call_fn(
|
||||||
functions: Option<&HashMap<FnSpec, Box<FnAny>>>,
|
functions: Option<&HashMap<u64, Box<FnAny>>>,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<Option<Dynamic>, EvalAltResult> {
|
) -> Result<Option<Dynamic>, EvalAltResult> {
|
||||||
let spec = FnSpec {
|
|
||||||
name: fn_name.into(),
|
|
||||||
args: args.iter().map(|a| a.type_id()).collect(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
functions
|
functions
|
||||||
.and_then(|f| f.get(&spec))
|
.and_then(|f| f.get(&calc_fn_spec(fn_name, args.iter().map(|a| a.type_id()))))
|
||||||
.map(|func| func(args, pos))
|
.map(|func| func(args, pos))
|
||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
@ -621,7 +616,7 @@ fn optimize_expr<'a>(expr: Expr, state: &mut State<'a>) -> Expr {
|
|||||||
|
|
||||||
fn optimize<'a>(
|
fn optimize<'a>(
|
||||||
statements: Vec<Stmt>,
|
statements: Vec<Stmt>,
|
||||||
engine: &Engine<'a>,
|
engine: &Engine,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
fn_lib: &'a [(&'a str, usize)],
|
fn_lib: &'a [(&'a str, usize)],
|
||||||
level: OptimizationLevel,
|
level: OptimizationLevel,
|
||||||
|
@ -1759,9 +1759,9 @@ fn parse_fn<'a>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_global_expr<'a, 'e>(
|
pub fn parse_global_expr<'a>(
|
||||||
input: &mut Peekable<TokenIterator<'a>>,
|
input: &mut Peekable<TokenIterator<'a>>,
|
||||||
engine: &Engine<'e>,
|
engine: &Engine,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
) -> Result<AST, ParseError> {
|
) -> Result<AST, ParseError> {
|
||||||
@ -1841,9 +1841,9 @@ fn parse_global_level<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Run the parser on an input stream, returning an AST.
|
/// Run the parser on an input stream, returning an AST.
|
||||||
pub fn parse<'a, 'e>(
|
pub fn parse<'a>(
|
||||||
input: &mut Peekable<TokenIterator<'a>>,
|
input: &mut Peekable<TokenIterator<'a>>,
|
||||||
engine: &Engine<'e>,
|
engine: &Engine,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
) -> Result<AST, ParseError> {
|
) -> Result<AST, ParseError> {
|
||||||
|
@ -81,18 +81,18 @@ fn test_side_effects_command() -> Result<(), EvalAltResult> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_side_effects_print() -> Result<(), EvalAltResult> {
|
fn test_side_effects_print() -> Result<(), EvalAltResult> {
|
||||||
|
use std::sync::Arc;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
let result = RwLock::new(String::from(""));
|
let result = Arc::new(RwLock::new(String::from("")));
|
||||||
|
|
||||||
{
|
let mut engine = Engine::new();
|
||||||
let mut engine = Engine::new();
|
|
||||||
|
|
||||||
// Override action of 'print' function
|
// Override action of 'print' function
|
||||||
engine.on_print(|s| result.write().unwrap().push_str(s));
|
let logger = result.clone();
|
||||||
|
engine.on_print(move |s| logger.write().unwrap().push_str(s));
|
||||||
|
|
||||||
engine.consume("print(40 + 2);")?;
|
engine.consume("print(40 + 2);")?;
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(*result.read().unwrap(), "42");
|
assert_eq!(*result.read().unwrap(), "42");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user