From d0711394f000d5254d9a0ec215f73c95961884ff Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 6 Jul 2020 21:30:35 +0800 Subject: [PATCH] Expose FnPtr and move name checking into --- .gitignore | 4 +++- src/engine.rs | 18 ++++++------------ src/fn_native.rs | 40 ++++++++++++++++++++++++++++++++++++---- src/lib.rs | 2 +- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 140811c2..e884ce0f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ target/ Cargo.lock .vscode/ .cargo/ -doc/book/ \ No newline at end of file +doc/book/ +before +after diff --git a/src/engine.rs b/src/engine.rs index e8a47960..f999235b 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -11,7 +11,7 @@ use crate::parser::{Expr, FnAccess, ImmutableString, ReturnType, ScriptFnDef, St use crate::r#unsafe::unsafe_cast_var_name_to_lifetime; use crate::result::EvalAltResult; use crate::scope::{EntryType as ScopeEntryType, Scope}; -use crate::token::{is_valid_identifier, Position}; +use crate::token::Position; use crate::utils::StaticVec; #[cfg(not(feature = "no_float"))] @@ -22,6 +22,7 @@ use crate::stdlib::{ borrow::Cow, boxed::Box, collections::{HashMap, HashSet}, + convert::TryFrom, format, iter::{empty, once}, mem, @@ -1735,6 +1736,7 @@ impl Engine { let expr = args_expr.get(0); let arg_value = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?; + return arg_value .take_immutable_string() .map_err(|typ| { @@ -1744,17 +1746,9 @@ impl Engine { expr.position(), )) }) - .and_then(|s| { - if is_valid_identifier(s.chars()) { - Ok(s) - } else { - Err(Box::new(EvalAltResult::ErrorFunctionNotFound( - s.to_string(), - expr.position(), - ))) - } - }) - .map(|s| FnPtr::from(s).into()); + .and_then(|s| FnPtr::try_from(s)) + .map(Into::::into) + .map_err(|err| err.new_position(*pos)); } } diff --git a/src/fn_native.rs b/src/fn_native.rs index 49cb4570..be4d6593 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -3,9 +3,10 @@ use crate::engine::Engine; use crate::module::Module; use crate::parser::ScriptFnDef; use crate::result::EvalAltResult; +use crate::token::{is_valid_identifier, Position}; use crate::utils::ImmutableString; -use crate::stdlib::{boxed::Box, fmt, rc::Rc, sync::Arc}; +use crate::stdlib::{boxed::Box, convert::TryFrom, fmt, rc::Rc, sync::Arc}; /// Trait that maps to `Send + Sync` only under the `sync` feature. #[cfg(feature = "sync")] @@ -52,6 +53,10 @@ pub type FnCallArgs<'a> = [&'a mut Dynamic]; pub struct FnPtr(ImmutableString); impl FnPtr { + /// Create a new function pointer. + pub(crate) fn new>(name: S) -> Self { + Self(name.into()) + } /// Get the name of the function. pub fn fn_name(&self) -> &str { self.get_fn_name().as_ref() @@ -72,9 +77,36 @@ impl fmt::Display for FnPtr { } } -impl> From for FnPtr { - fn from(value: S) -> Self { - Self(value.into()) +impl TryFrom for FnPtr { + type Error = Box; + + fn try_from(value: ImmutableString) -> Result { + if is_valid_identifier(value.chars()) { + Ok(Self(value)) + } else { + Err(Box::new(EvalAltResult::ErrorFunctionNotFound( + value.to_string(), + Position::none(), + ))) + } + } +} + +impl TryFrom for FnPtr { + type Error = Box; + + fn try_from(value: String) -> Result { + let s: ImmutableString = value.into(); + Self::try_from(s) + } +} + +impl TryFrom<&str> for FnPtr { + type Error = Box; + + fn try_from(value: &str) -> Result { + let s: ImmutableString = value.into(); + Self::try_from(s) } } diff --git a/src/lib.rs b/src/lib.rs index 13221e2c..768ad25a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,7 @@ mod utils; pub use any::Dynamic; pub use engine::Engine; pub use error::{ParseError, ParseErrorType}; -pub use fn_native::IteratorFn; +pub use fn_native::{FnPtr, IteratorFn}; pub use fn_register::{RegisterFn, RegisterResultFn}; pub use module::Module; pub use parser::{ImmutableString, AST, INT};