Expose FnPtr and move name checking into

This commit is contained in:
Stephen Chung 2020-07-06 21:30:35 +08:00
parent 46cdec1280
commit d0711394f0
4 changed files with 46 additions and 18 deletions

2
.gitignore vendored
View File

@ -3,3 +3,5 @@ Cargo.lock
.vscode/ .vscode/
.cargo/ .cargo/
doc/book/ doc/book/
before
after

View File

@ -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::r#unsafe::unsafe_cast_var_name_to_lifetime;
use crate::result::EvalAltResult; use crate::result::EvalAltResult;
use crate::scope::{EntryType as ScopeEntryType, Scope}; use crate::scope::{EntryType as ScopeEntryType, Scope};
use crate::token::{is_valid_identifier, Position}; use crate::token::Position;
use crate::utils::StaticVec; use crate::utils::StaticVec;
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
@ -22,6 +22,7 @@ use crate::stdlib::{
borrow::Cow, borrow::Cow,
boxed::Box, boxed::Box,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
convert::TryFrom,
format, format,
iter::{empty, once}, iter::{empty, once},
mem, mem,
@ -1735,6 +1736,7 @@ impl Engine {
let expr = args_expr.get(0); let expr = args_expr.get(0);
let arg_value = let arg_value =
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?; self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
return arg_value return arg_value
.take_immutable_string() .take_immutable_string()
.map_err(|typ| { .map_err(|typ| {
@ -1744,17 +1746,9 @@ impl Engine {
expr.position(), expr.position(),
)) ))
}) })
.and_then(|s| { .and_then(|s| FnPtr::try_from(s))
if is_valid_identifier(s.chars()) { .map(Into::<Dynamic>::into)
Ok(s) .map_err(|err| err.new_position(*pos));
} else {
Err(Box::new(EvalAltResult::ErrorFunctionNotFound(
s.to_string(),
expr.position(),
)))
}
})
.map(|s| FnPtr::from(s).into());
} }
} }

View File

@ -3,9 +3,10 @@ use crate::engine::Engine;
use crate::module::Module; use crate::module::Module;
use crate::parser::ScriptFnDef; use crate::parser::ScriptFnDef;
use crate::result::EvalAltResult; use crate::result::EvalAltResult;
use crate::token::{is_valid_identifier, Position};
use crate::utils::ImmutableString; 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. /// Trait that maps to `Send + Sync` only under the `sync` feature.
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
@ -52,6 +53,10 @@ pub type FnCallArgs<'a> = [&'a mut Dynamic];
pub struct FnPtr(ImmutableString); pub struct FnPtr(ImmutableString);
impl FnPtr { impl FnPtr {
/// Create a new function pointer.
pub(crate) fn new<S: Into<ImmutableString>>(name: S) -> Self {
Self(name.into())
}
/// Get the name of the function. /// Get the name of the function.
pub fn fn_name(&self) -> &str { pub fn fn_name(&self) -> &str {
self.get_fn_name().as_ref() self.get_fn_name().as_ref()
@ -72,9 +77,36 @@ impl fmt::Display for FnPtr {
} }
} }
impl<S: Into<ImmutableString>> From<S> for FnPtr { impl TryFrom<ImmutableString> for FnPtr {
fn from(value: S) -> Self { type Error = Box<EvalAltResult>;
Self(value.into())
fn try_from(value: ImmutableString) -> Result<Self, Self::Error> {
if is_valid_identifier(value.chars()) {
Ok(Self(value))
} else {
Err(Box::new(EvalAltResult::ErrorFunctionNotFound(
value.to_string(),
Position::none(),
)))
}
}
}
impl TryFrom<String> for FnPtr {
type Error = Box<EvalAltResult>;
fn try_from(value: String) -> Result<Self, Self::Error> {
let s: ImmutableString = value.into();
Self::try_from(s)
}
}
impl TryFrom<&str> for FnPtr {
type Error = Box<EvalAltResult>;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let s: ImmutableString = value.into();
Self::try_from(s)
} }
} }

View File

@ -98,7 +98,7 @@ 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::IteratorFn; pub use fn_native::{FnPtr, IteratorFn};
pub use fn_register::{RegisterFn, RegisterResultFn}; pub use fn_register::{RegisterFn, RegisterResultFn};
pub use module::Module; pub use module::Module;
pub use parser::{ImmutableString, AST, INT}; pub use parser::{ImmutableString, AST, INT};