Optimize Fn construct.
This commit is contained in:
parent
d3cfb3c605
commit
131147c65d
@ -13,8 +13,8 @@ use crate::stdlib::{
|
||||
};
|
||||
use crate::token::is_valid_identifier;
|
||||
use crate::{
|
||||
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ImmutableString, Module, Position,
|
||||
RhaiResult, StaticVec,
|
||||
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, Identifier, ImmutableString, Module,
|
||||
Position, RhaiResult, StaticVec,
|
||||
};
|
||||
|
||||
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
||||
@ -252,20 +252,17 @@ pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
||||
/// A general function pointer, which may carry additional (i.e. curried) argument values
|
||||
/// to be passed onto a function during a call.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FnPtr(ImmutableString, StaticVec<Dynamic>);
|
||||
pub struct FnPtr(Identifier, StaticVec<Dynamic>);
|
||||
|
||||
impl FnPtr {
|
||||
/// Create a new function pointer.
|
||||
#[inline(always)]
|
||||
pub fn new(name: impl Into<ImmutableString>) -> Result<Self, Box<EvalAltResult>> {
|
||||
pub fn new(name: impl Into<Identifier>) -> Result<Self, Box<EvalAltResult>> {
|
||||
name.into().try_into()
|
||||
}
|
||||
/// Create a new function pointer without checking its parameters.
|
||||
#[inline(always)]
|
||||
pub(crate) fn new_unchecked(
|
||||
name: impl Into<ImmutableString>,
|
||||
curry: StaticVec<Dynamic>,
|
||||
) -> Self {
|
||||
pub(crate) fn new_unchecked(name: impl Into<Identifier>, curry: StaticVec<Dynamic>) -> Self {
|
||||
Self(name.into(), curry)
|
||||
}
|
||||
/// Get the name of the function.
|
||||
@ -275,12 +272,12 @@ impl FnPtr {
|
||||
}
|
||||
/// Get the name of the function.
|
||||
#[inline(always)]
|
||||
pub(crate) fn get_fn_name(&self) -> &ImmutableString {
|
||||
pub(crate) fn get_fn_name(&self) -> &Identifier {
|
||||
&self.0
|
||||
}
|
||||
/// Get the underlying data of the function pointer.
|
||||
#[inline(always)]
|
||||
pub(crate) fn take_data(self) -> (ImmutableString, StaticVec<Dynamic>) {
|
||||
pub(crate) fn take_data(self) -> (Identifier, StaticVec<Dynamic>) {
|
||||
(self.0, self.1)
|
||||
}
|
||||
/// Get the curried arguments.
|
||||
@ -362,11 +359,11 @@ impl fmt::Display for FnPtr {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ImmutableString> for FnPtr {
|
||||
impl TryFrom<Identifier> for FnPtr {
|
||||
type Error = Box<EvalAltResult>;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_from(value: ImmutableString) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: Identifier) -> Result<Self, Self::Error> {
|
||||
if is_valid_identifier(value.chars()) {
|
||||
Ok(Self(value, Default::default()))
|
||||
} else {
|
||||
@ -375,12 +372,22 @@ impl TryFrom<ImmutableString> for FnPtr {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ImmutableString> for FnPtr {
|
||||
type Error = Box<EvalAltResult>;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_from(value: ImmutableString) -> Result<Self, Self::Error> {
|
||||
let s: Identifier = value.into();
|
||||
Self::try_from(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for FnPtr {
|
||||
type Error = Box<EvalAltResult>;
|
||||
|
||||
#[inline(always)]
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
let s: ImmutableString = value.into();
|
||||
let s: Identifier = value.into();
|
||||
Self::try_from(s)
|
||||
}
|
||||
}
|
||||
@ -390,7 +397,7 @@ impl TryFrom<&str> for FnPtr {
|
||||
|
||||
#[inline(always)]
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
let s: ImmutableString = value.into();
|
||||
let s: Identifier = value.into();
|
||||
Self::try_from(s)
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::ast::{Expr, Stmt, StmtBlock};
|
||||
use crate::dynamic::AccessMode;
|
||||
use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_PRINT, KEYWORD_TYPE_OF};
|
||||
use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT, KEYWORD_TYPE_OF};
|
||||
use crate::fn_builtin::get_builtin_binary_op_fn;
|
||||
use crate::parser::map_dynamic_to_expr;
|
||||
use crate::stdlib::{
|
||||
@ -794,6 +794,22 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
||||
Expr::FnCall(x, _) if x.name == KEYWORD_EVAL => {
|
||||
state.propagate_constants = false;
|
||||
}
|
||||
// Fn
|
||||
Expr::FnCall(x, pos)
|
||||
if x.namespace.is_none() // Non-qualified
|
||||
&& state.optimization_level == OptimizationLevel::Simple // simple optimizations
|
||||
&& x.num_args() == 1
|
||||
&& matches!(x.args[0], Expr::StringConstant(_, _))
|
||||
&& x.name == KEYWORD_FN_PTR
|
||||
=> {
|
||||
if let Expr::StringConstant(s, _) = mem::take(&mut x.args[0]) {
|
||||
state.set_dirty();
|
||||
*expr = Expr::FnPointer(s, *pos);
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
// Do not call some special keywords
|
||||
Expr::FnCall(x, _) if DONT_EVAL_KEYWORDS.contains(&x.name.as_ref()) => {
|
||||
x.args.iter_mut().for_each(|a| optimize_expr(a, state));
|
||||
|
Loading…
Reference in New Issue
Block a user