Reduce size of ChainArgument.
This commit is contained in:
parent
757eacfdde
commit
7a15071e4e
@ -368,8 +368,11 @@ enum ChainArgument {
|
|||||||
Property(Position),
|
Property(Position),
|
||||||
/// Arguments to a dot method call.
|
/// Arguments to a dot method call.
|
||||||
/// Wrapped values are the arguments plus the [position][Position] of the first argument.
|
/// Wrapped values are the arguments plus the [position][Position] of the first argument.
|
||||||
|
///
|
||||||
|
/// Since many dotted function calls have no arguments (e.g. `string.len()`), it is better to
|
||||||
|
/// reduce the size of [`ChainArgument`] by using a boxed slice.
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
MethodCallArgs(FnArgsVec<Dynamic>, Position),
|
MethodCallArgs(Option<Box<[Dynamic]>>, Position),
|
||||||
/// Index value and [position][Position].
|
/// Index value and [position][Position].
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
IndexValue(Dynamic, Position),
|
IndexValue(Dynamic, Position),
|
||||||
@ -389,13 +392,20 @@ impl ChainArgument {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Return the list of method call arguments.
|
/// Return the list of method call arguments.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the [`ChainArgument`] is not [`MethodCallArgs`][ChainArgument::MethodCallArgs].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn into_fn_call_args(self) -> Option<(FnArgsVec<Dynamic>, Position)> {
|
pub fn into_fn_call_args(self) -> (FnArgsVec<Dynamic>, Position) {
|
||||||
match self {
|
match self {
|
||||||
Self::MethodCallArgs(values, pos) => Some((values, pos)),
|
Self::MethodCallArgs(None, pos) => (FnArgsVec::new_const(), pos),
|
||||||
_ => None,
|
Self::MethodCallArgs(Some(mut values), pos) => {
|
||||||
|
(values.iter_mut().map(std::mem::take).collect(), pos)
|
||||||
|
}
|
||||||
|
_ => unreachable!("`MethodCallArgs` expected"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Return the [position][Position].
|
/// Return the [position][Position].
|
||||||
@ -412,20 +422,21 @@ impl ChainArgument {
|
|||||||
ChainArgument::IndexValue(_, pos) => *pos,
|
ChainArgument::IndexValue(_, pos) => *pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
/// Create n [`MethodCallArgs`][ChainArgument::MethodCallArgs].
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
impl From<(FnArgsVec<Dynamic>, Position)> for ChainArgument {
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from((values, pos): (FnArgsVec<Dynamic>, Position)) -> Self {
|
#[cfg(not(feature = "no_object"))]
|
||||||
Self::MethodCallArgs(values, pos)
|
#[must_use]
|
||||||
|
pub fn from_fn_call_args(values: FnArgsVec<Dynamic>, pos: Position) -> Self {
|
||||||
|
if values.is_empty() {
|
||||||
|
Self::MethodCallArgs(None, pos)
|
||||||
|
} else {
|
||||||
|
Self::MethodCallArgs(Some(values.into_vec().into()), pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Create an [`IndexValue`][ChainArgument::IndexValue].
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
impl From<(Dynamic, Position)> for ChainArgument {
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from((value, pos): (Dynamic, Position)) -> Self {
|
#[must_use]
|
||||||
|
pub const fn from_index_value(value: Dynamic, pos: Position) -> Self {
|
||||||
Self::IndexValue(value, pos)
|
Self::IndexValue(value, pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1322,7 +1333,7 @@ impl Engine {
|
|||||||
root: (&str, Position),
|
root: (&str, Position),
|
||||||
rhs: &Expr,
|
rhs: &Expr,
|
||||||
terminate_chaining: bool,
|
terminate_chaining: bool,
|
||||||
idx_values: &mut FnArgsVec<ChainArgument>,
|
idx_values: &mut StaticVec<ChainArgument>,
|
||||||
chain_type: ChainType,
|
chain_type: ChainType,
|
||||||
level: usize,
|
level: usize,
|
||||||
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
|
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
|
||||||
@ -1445,9 +1456,7 @@ impl Engine {
|
|||||||
// xxx.fn_name(arg_expr_list)
|
// xxx.fn_name(arg_expr_list)
|
||||||
Expr::FnCall(x, pos) if !x.is_qualified() && new_val.is_none() => {
|
Expr::FnCall(x, pos) if !x.is_qualified() && new_val.is_none() => {
|
||||||
let FnCallExpr { name, hashes, .. } = x.as_ref();
|
let FnCallExpr { name, hashes, .. } = x.as_ref();
|
||||||
let call_args = &mut idx_val
|
let call_args = &mut idx_val.into_fn_call_args();
|
||||||
.into_fn_call_args()
|
|
||||||
.expect("`ChainType::Dot` with `Expr::FnCallExpr`");
|
|
||||||
self.make_method_call(
|
self.make_method_call(
|
||||||
mods, state, lib, name, *hashes, target, call_args, *pos, level,
|
mods, state, lib, name, *hashes, target, call_args, *pos, level,
|
||||||
)
|
)
|
||||||
@ -1611,9 +1620,7 @@ impl Engine {
|
|||||||
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
|
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
|
||||||
Expr::FnCall(ref x, pos) if !x.is_qualified() => {
|
Expr::FnCall(ref x, pos) if !x.is_qualified() => {
|
||||||
let FnCallExpr { name, hashes, .. } = x.as_ref();
|
let FnCallExpr { name, hashes, .. } = x.as_ref();
|
||||||
let call_args = &mut idx_val.into_fn_call_args().expect(
|
let call_args = &mut idx_val.into_fn_call_args();
|
||||||
"`chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`",
|
|
||||||
);
|
|
||||||
let (val, _) = self.make_method_call(
|
let (val, _) = self.make_method_call(
|
||||||
mods, state, lib, name, *hashes, target, call_args, pos, level,
|
mods, state, lib, name, *hashes, target, call_args, pos, level,
|
||||||
)?;
|
)?;
|
||||||
@ -1736,9 +1743,7 @@ impl Engine {
|
|||||||
Expr::FnCall(ref f, pos) if !f.is_qualified() => {
|
Expr::FnCall(ref f, pos) if !f.is_qualified() => {
|
||||||
let FnCallExpr { name, hashes, .. } = f.as_ref();
|
let FnCallExpr { name, hashes, .. } = f.as_ref();
|
||||||
let rhs_chain = match_chaining_type(rhs);
|
let rhs_chain = match_chaining_type(rhs);
|
||||||
let args = &mut idx_val.into_fn_call_args().expect(
|
let args = &mut idx_val.into_fn_call_args();
|
||||||
"`chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`",
|
|
||||||
);
|
|
||||||
let (mut val, _) = self.make_method_call(
|
let (mut val, _) = self.make_method_call(
|
||||||
mods, state, lib, name, *hashes, target, args, pos, level,
|
mods, state, lib, name, *hashes, target, args, pos, level,
|
||||||
)?;
|
)?;
|
||||||
@ -1787,7 +1792,7 @@ impl Engine {
|
|||||||
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
||||||
};
|
};
|
||||||
|
|
||||||
let idx_values = &mut FnArgsVec::new_const();
|
let idx_values = &mut StaticVec::new_const();
|
||||||
|
|
||||||
self.eval_dot_index_chain_arguments(
|
self.eval_dot_index_chain_arguments(
|
||||||
scope, mods, state, lib, this_ptr, rhs, term, chain_type, idx_values, 0, level,
|
scope, mods, state, lib, this_ptr, rhs, term, chain_type, idx_values, 0, level,
|
||||||
@ -1843,7 +1848,7 @@ impl Engine {
|
|||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
terminate_chaining: bool,
|
terminate_chaining: bool,
|
||||||
parent_chain_type: ChainType,
|
parent_chain_type: ChainType,
|
||||||
idx_values: &mut FnArgsVec<ChainArgument>,
|
idx_values: &mut StaticVec<ChainArgument>,
|
||||||
size: usize,
|
size: usize,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> RhaiResultOf<()> {
|
) -> RhaiResultOf<()> {
|
||||||
@ -1873,7 +1878,7 @@ impl Engine {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
idx_values.push((values, pos).into());
|
idx_values.push(ChainArgument::from_fn_call_args(values, pos));
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => {
|
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => {
|
||||||
@ -1890,7 +1895,7 @@ impl Engine {
|
|||||||
let crate::ast::BinaryExpr { lhs, rhs, .. } = x.as_ref();
|
let crate::ast::BinaryExpr { lhs, rhs, .. } = x.as_ref();
|
||||||
|
|
||||||
// Evaluate in left-to-right order
|
// Evaluate in left-to-right order
|
||||||
let lhs_val = match lhs {
|
let lhs_arg_val = match lhs {
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Property(x) if _parent_chain_type == ChainType::Dotting => {
|
Expr::Property(x) if _parent_chain_type == ChainType::Dotting => {
|
||||||
ChainArgument::Property((x.2).1)
|
ChainArgument::Property((x.2).1)
|
||||||
@ -1905,8 +1910,7 @@ impl Engine {
|
|||||||
args, constants, ..
|
args, constants, ..
|
||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
|
|
||||||
args.iter()
|
let (values, pos) = args.iter().try_fold(
|
||||||
.try_fold(
|
|
||||||
(FnArgsVec::with_capacity(args.len()), Position::NONE),
|
(FnArgsVec::with_capacity(args.len()), Position::NONE),
|
||||||
|(mut values, mut pos), expr| -> RhaiResultOf<_> {
|
|(mut values, mut pos), expr| -> RhaiResultOf<_> {
|
||||||
let (value, arg_pos) = self.get_arg_value(
|
let (value, arg_pos) = self.get_arg_value(
|
||||||
@ -1918,8 +1922,8 @@ impl Engine {
|
|||||||
values.push(value.flatten());
|
values.push(value.flatten());
|
||||||
Ok((values, pos))
|
Ok((values, pos))
|
||||||
},
|
},
|
||||||
)?
|
)?;
|
||||||
.into()
|
ChainArgument::from_fn_call_args(values, pos)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => {
|
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dotting => {
|
||||||
@ -1932,7 +1936,7 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
_ if _parent_chain_type == ChainType::Indexing => self
|
_ if _parent_chain_type == ChainType::Indexing => self
|
||||||
.eval_expr(scope, mods, state, lib, this_ptr, lhs, level)
|
.eval_expr(scope, mods, state, lib, this_ptr, lhs, level)
|
||||||
.map(|v| (v.flatten(), lhs.position()).into())?,
|
.map(|v| ChainArgument::from_index_value(v.flatten(), lhs.position()))?,
|
||||||
expr => unreachable!("unknown chained expression: {:?}", expr),
|
expr => unreachable!("unknown chained expression: {:?}", expr),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1944,7 +1948,7 @@ impl Engine {
|
|||||||
level,
|
level,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
idx_values.push(lhs_val);
|
idx_values.push(lhs_arg_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -1954,7 +1958,7 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
_ if _parent_chain_type == ChainType::Indexing => idx_values.push(
|
_ if _parent_chain_type == ChainType::Indexing => idx_values.push(
|
||||||
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)
|
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)
|
||||||
.map(|v| (v.flatten(), expr.position()).into())?,
|
.map(|v| ChainArgument::from_index_value(v.flatten(), expr.position()))?,
|
||||||
),
|
),
|
||||||
_ => unreachable!("unknown chained expression: {:?}", expr),
|
_ => unreachable!("unknown chained expression: {:?}", expr),
|
||||||
}
|
}
|
||||||
|
@ -329,10 +329,7 @@ pub type StaticVec<T> = smallvec::SmallVec<[T; 3]>;
|
|||||||
type FnArgsVec<T> = smallvec::SmallVec<[T; 8]>;
|
type FnArgsVec<T> = smallvec::SmallVec<[T; 8]>;
|
||||||
|
|
||||||
/// Inline arguments storage for function calls.
|
/// Inline arguments storage for function calls.
|
||||||
///
|
/// This type aliases to [`StaticVec`][crate::StaticVec].
|
||||||
/// # Notes
|
|
||||||
///
|
|
||||||
/// This type aliases to [`StaticVec`][crate::StaticVec] under `no_closure`.
|
|
||||||
#[cfg(feature = "no_closure")]
|
#[cfg(feature = "no_closure")]
|
||||||
type FnArgsVec<T> = crate::StaticVec<T>;
|
type FnArgsVec<T> = crate::StaticVec<T>;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user