Pack method call args more tightly.

This commit is contained in:
Stephen Chung 2021-03-09 18:11:43 +08:00
parent bc2b9bfbfd
commit 9daa894e25
3 changed files with 35 additions and 22 deletions

View File

@ -29,6 +29,7 @@ Breaking changes
* `is_def_var` and `is_def_fn` are now reserved keywords. * `is_def_var` and `is_def_fn` are now reserved keywords.
* `Engine::id` field is removed. * `Engine::id` field is removed.
* `num-traits` is now a required dependency. * `num-traits` is now a required dependency.
* The `in` operator is now implemented on top of the `contains` function and is no longer restricted to a few specific types.
Enhancements Enhancements
------------ ------------

View File

@ -230,7 +230,7 @@ pub enum ChainArgument {
/// Dot-property access. /// Dot-property access.
Property(Position), Property(Position),
/// Arguments to a dot-function call. /// Arguments to a dot-function call.
FnCallArgs(StaticVec<(Dynamic, Position)>), FnCallArgs(StaticVec<Dynamic>, StaticVec<Position>),
/// Index value. /// Index value.
IndexValue(Dynamic, Position), IndexValue(Dynamic, Position),
} }
@ -246,7 +246,7 @@ impl ChainArgument {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
pub fn as_index_value(self) -> Dynamic { pub fn as_index_value(self) -> Dynamic {
match self { match self {
Self::Property(_) | Self::FnCallArgs(_) => { Self::Property(_) | Self::FnCallArgs(_, _) => {
panic!("expecting ChainArgument::IndexValue") panic!("expecting ChainArgument::IndexValue")
} }
Self::IndexValue(value, _) => value, Self::IndexValue(value, _) => value,
@ -259,21 +259,21 @@ impl ChainArgument {
/// Panics if not `ChainArgument::FnCallArgs`. /// Panics if not `ChainArgument::FnCallArgs`.
#[inline(always)] #[inline(always)]
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
pub fn as_fn_call_args(self) -> StaticVec<(Dynamic, Position)> { pub fn as_fn_call_args(self) -> (StaticVec<Dynamic>, StaticVec<Position>) {
match self { match self {
Self::Property(_) | Self::IndexValue(_, _) => { Self::Property(_) | Self::IndexValue(_, _) => {
panic!("expecting ChainArgument::FnCallArgs") panic!("expecting ChainArgument::FnCallArgs")
} }
Self::FnCallArgs(value) => value, Self::FnCallArgs(values, positions) => (values, positions),
} }
} }
} }
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
impl From<StaticVec<(Dynamic, Position)>> for ChainArgument { impl From<(StaticVec<Dynamic>, StaticVec<Position>)> for ChainArgument {
#[inline(always)] #[inline(always)]
fn from(value: StaticVec<(Dynamic, Position)>) -> Self { fn from((values, positions): (StaticVec<Dynamic>, StaticVec<Position>)) -> Self {
Self::FnCallArgs(value) Self::FnCallArgs(values, positions)
} }
} }
@ -1436,16 +1436,19 @@ impl Engine {
match expr { match expr {
Expr::FnCall(x, _) if parent_chain_type == ChainType::Dot && x.namespace.is_none() => { Expr::FnCall(x, _) if parent_chain_type == ChainType::Dot && x.namespace.is_none() => {
let mut arg_positions: StaticVec<_> = Default::default();
let arg_values = x let arg_values = x
.args .args
.iter() .iter()
.map(|arg_expr| { .map(|arg_expr| {
arg_positions.push(arg_expr.position());
self.eval_expr(scope, mods, state, lib, this_ptr, arg_expr, level) self.eval_expr(scope, mods, state, lib, this_ptr, arg_expr, level)
.map(|v| (v.flatten(), arg_expr.position())) .map(Dynamic::flatten)
}) })
.collect::<Result<StaticVec<_>, _>>()?; .collect::<Result<StaticVec<_>, _>>()?;
idx_values.push(arg_values.into()); idx_values.push((arg_values, arg_positions).into());
} }
Expr::FnCall(_, _) if parent_chain_type == ChainType::Dot => { Expr::FnCall(_, _) if parent_chain_type == ChainType::Dot => {
unreachable!("function call in dot chain should not be namespace-qualified") unreachable!("function call in dot chain should not be namespace-qualified")
@ -1468,14 +1471,19 @@ impl Engine {
Expr::FnCall(x, _) Expr::FnCall(x, _)
if parent_chain_type == ChainType::Dot && x.namespace.is_none() => if parent_chain_type == ChainType::Dot && x.namespace.is_none() =>
{ {
x.args let mut arg_positions: StaticVec<_> = Default::default();
let arg_values = x
.args
.iter() .iter()
.map(|arg_expr| { .map(|arg_expr| {
arg_positions.push(arg_expr.position());
self.eval_expr(scope, mods, state, lib, this_ptr, arg_expr, level) self.eval_expr(scope, mods, state, lib, this_ptr, arg_expr, level)
.map(|v| (v.flatten(), arg_expr.position())) .map(Dynamic::flatten)
}) })
.collect::<Result<StaticVec<_>, _>>()? .collect::<Result<StaticVec<_>, _>>()?;
.into()
(arg_values, arg_positions).into()
} }
Expr::FnCall(_, _) if parent_chain_type == ChainType::Dot => { Expr::FnCall(_, _) if parent_chain_type == ChainType::Dot => {
unreachable!("function call in dot chain should not be namespace-qualified") unreachable!("function call in dot chain should not be namespace-qualified")

View File

@ -885,7 +885,7 @@ impl Engine {
fn_name: &str, fn_name: &str,
mut hash: FnHash, mut hash: FnHash,
target: &mut crate::engine::Target, target: &mut crate::engine::Target,
call_args: &mut StaticVec<(Dynamic, Position)>, (call_args, call_arg_positions): &mut (StaticVec<Dynamic>, StaticVec<Position>),
pos: Position, pos: Position,
level: usize, level: usize,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> { ) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
@ -908,7 +908,7 @@ impl Engine {
let mut curry = fn_ptr.curry().iter().cloned().collect::<StaticVec<_>>(); let mut curry = fn_ptr.curry().iter().cloned().collect::<StaticVec<_>>();
let mut arg_values = curry let mut arg_values = curry
.iter_mut() .iter_mut()
.chain(call_args.iter_mut().map(|v| &mut v.0)) .chain(call_args.iter_mut())
.collect::<StaticVec<_>>(); .collect::<StaticVec<_>>();
let args = arg_values.as_mut(); let args = arg_values.as_mut();
@ -919,10 +919,10 @@ impl Engine {
} }
KEYWORD_FN_PTR_CALL => { KEYWORD_FN_PTR_CALL => {
if call_args.len() > 0 { if call_args.len() > 0 {
if !call_args[0].0.is::<FnPtr>() { if !call_args[0].is::<FnPtr>() {
return Err(self.make_type_mismatch_err::<FnPtr>( return Err(self.make_type_mismatch_err::<FnPtr>(
self.map_type_name(obj.type_name()), self.map_type_name(obj.type_name()),
call_args[0].1, call_arg_positions[0],
)); ));
} }
} else { } else {
@ -933,7 +933,8 @@ impl Engine {
} }
// FnPtr call on object // FnPtr call on object
let fn_ptr = call_args.remove(0).0.cast::<FnPtr>(); let fn_ptr = call_args.remove(0).cast::<FnPtr>();
call_arg_positions.remove(0);
// Redirect function name // Redirect function name
let fn_name = fn_ptr.fn_name(); let fn_name = fn_ptr.fn_name();
let args_len = call_args.len() + fn_ptr.curry().len(); let args_len = call_args.len() + fn_ptr.curry().len();
@ -946,7 +947,7 @@ impl Engine {
let mut curry = fn_ptr.curry().iter().cloned().collect::<StaticVec<_>>(); let mut curry = fn_ptr.curry().iter().cloned().collect::<StaticVec<_>>();
let mut arg_values = once(obj) let mut arg_values = once(obj)
.chain(curry.iter_mut()) .chain(curry.iter_mut())
.chain(call_args.iter_mut().map(|v| &mut v.0)) .chain(call_args.iter_mut())
.collect::<StaticVec<_>>(); .collect::<StaticVec<_>>();
let args = arg_values.as_mut(); let args = arg_values.as_mut();
@ -976,7 +977,7 @@ impl Engine {
.curry() .curry()
.iter() .iter()
.cloned() .cloned()
.chain(call_args.iter_mut().map(|v| mem::take(v).0)) .chain(call_args.iter_mut().map(|v| mem::take(v)))
.collect(), .collect(),
) )
} }
@ -1008,7 +1009,10 @@ impl Engine {
.iter() .iter()
.cloned() .cloned()
.enumerate() .enumerate()
.for_each(|(i, v)| call_args.insert(i, (v, Position::NONE))); .for_each(|(i, v)| {
call_args.insert(i, v);
call_arg_positions.insert(i, Position::NONE);
});
// Recalculate the hash based on the new function name and new arguments // Recalculate the hash based on the new function name and new arguments
hash = FnHash::from_script_and_native( hash = FnHash::from_script_and_native(
calc_fn_hash(empty(), fn_name, call_args.len()), calc_fn_hash(empty(), fn_name, call_args.len()),
@ -1020,7 +1024,7 @@ impl Engine {
// Attached object pointer in front of the arguments // Attached object pointer in front of the arguments
let mut arg_values = once(obj) let mut arg_values = once(obj)
.chain(call_args.iter_mut().map(|v| &mut v.0)) .chain(call_args.iter_mut())
.collect::<StaticVec<_>>(); .collect::<StaticVec<_>>();
let args = arg_values.as_mut(); let args = arg_values.as_mut();