Refine ChainArgument.
This commit is contained in:
parent
c87645ba77
commit
fc0256aff9
@ -274,50 +274,34 @@ enum ChainArgument {
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
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.
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
MethodCallArgs(StaticVec<Dynamic>, Position),
|
MethodCallArgs(StaticVec<Dynamic>, Position),
|
||||||
/// Index value.
|
/// Index value and [position][Position].
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
IndexValue(Dynamic, Position),
|
IndexValue(Dynamic, Position),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
impl ChainArgument {
|
impl ChainArgument {
|
||||||
/// Return the `Dynamic` value.
|
/// Return the index value.
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if not `ChainArgument::IndexValue`.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn as_index_value(self) -> Dynamic {
|
pub fn as_index_value(self) -> Option<Dynamic> {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(not(feature = "no_object"))]
|
Self::IndexValue(value, _) => Some(value),
|
||||||
Self::Property(_) | Self::MethodCallArgs(_, _) => {
|
_ => None,
|
||||||
panic!("expecting ChainArgument::IndexValue")
|
|
||||||
}
|
|
||||||
Self::IndexValue(value, _) => value,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Return the `StaticVec<Dynamic>` value.
|
/// Return the list of method call arguments.
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if not `ChainArgument::MethodCallArgs`.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn as_fn_call_args(self) -> (StaticVec<Dynamic>, Position) {
|
pub fn as_fn_call_args(self) -> Option<(StaticVec<Dynamic>, Position)> {
|
||||||
match self {
|
match self {
|
||||||
Self::Property(_) => {
|
Self::MethodCallArgs(values, pos) => Some((values, pos)),
|
||||||
panic!("expecting ChainArgument::MethodCallArgs")
|
_ => None,
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Self::IndexValue(_, _) => {
|
|
||||||
panic!("expecting ChainArgument::MethodCallArgs")
|
|
||||||
}
|
|
||||||
Self::MethodCallArgs(values, pos) => (values, pos),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1208,12 +1192,14 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
ChainType::Index => {
|
ChainType::Index => {
|
||||||
let pos = rhs.position();
|
let pos = rhs.position();
|
||||||
|
let idx_val = idx_val
|
||||||
|
.as_index_value()
|
||||||
|
.expect("never fails because `chain_type` is `ChainType::Index`");
|
||||||
|
|
||||||
match rhs {
|
match rhs {
|
||||||
// xxx[idx].expr... | xxx[idx][expr]...
|
// xxx[idx].expr... | xxx[idx][expr]...
|
||||||
Expr::Dot(x, x_pos) | Expr::Index(x, x_pos) => {
|
Expr::Dot(x, x_pos) | Expr::Index(x, x_pos) => {
|
||||||
let idx_pos = x.lhs.position();
|
let idx_pos = x.lhs.position();
|
||||||
let idx_val = idx_val.as_index_value();
|
|
||||||
let obj_ptr = &mut self.get_indexed_mut(
|
let obj_ptr = &mut self.get_indexed_mut(
|
||||||
mods, state, lib, target, idx_val, idx_pos, false, true, level,
|
mods, state, lib, target, idx_val, idx_pos, false, true, level,
|
||||||
)?;
|
)?;
|
||||||
@ -1229,7 +1215,6 @@ impl Engine {
|
|||||||
_ if new_val.is_some() => {
|
_ if new_val.is_some() => {
|
||||||
let ((new_val, new_pos), (op_info, op_pos)) =
|
let ((new_val, new_pos), (op_info, op_pos)) =
|
||||||
new_val.expect("never fails because `new_val` is `Some`");
|
new_val.expect("never fails because `new_val` is `Some`");
|
||||||
let idx_val = idx_val.as_index_value();
|
|
||||||
let mut idx_val_for_setter = idx_val.clone();
|
let mut idx_val_for_setter = idx_val.clone();
|
||||||
|
|
||||||
let try_setter = match self.get_indexed_mut(
|
let try_setter = match self.get_indexed_mut(
|
||||||
@ -1271,13 +1256,9 @@ impl Engine {
|
|||||||
Ok((Dynamic::UNIT, true))
|
Ok((Dynamic::UNIT, true))
|
||||||
}
|
}
|
||||||
// xxx[rhs]
|
// xxx[rhs]
|
||||||
_ => {
|
_ => self
|
||||||
let idx_val = idx_val.as_index_value();
|
.get_indexed_mut(mods, state, lib, target, idx_val, pos, false, true, level)
|
||||||
self.get_indexed_mut(
|
.map(|v| (v.take_or_clone(), false)),
|
||||||
mods, state, lib, target, idx_val, pos, false, true, level,
|
|
||||||
)
|
|
||||||
.map(|v| (v.take_or_clone(), false))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1287,9 +1268,11 @@ 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 args = &mut idx_val.as_fn_call_args();
|
let call_args = &mut idx_val
|
||||||
|
.as_fn_call_args()
|
||||||
|
.expect("never fails because `chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`");
|
||||||
self.make_method_call(
|
self.make_method_call(
|
||||||
mods, state, lib, name, *hashes, target, args, *pos, level,
|
mods, state, lib, name, *hashes, target, call_args, *pos, level,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// xxx.fn_name(...) = ???
|
// xxx.fn_name(...) = ???
|
||||||
@ -1450,9 +1433,11 @@ 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 args = &mut idx_val.as_fn_call_args();
|
let call_args = &mut idx_val
|
||||||
|
.as_fn_call_args()
|
||||||
|
.expect("never fails because `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, args, pos, level,
|
mods, state, lib, name, *hashes, target, call_args, pos, level,
|
||||||
)?;
|
)?;
|
||||||
val.into()
|
val.into()
|
||||||
}
|
}
|
||||||
@ -1569,7 +1554,9 @@ 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_chain_type(rhs);
|
let rhs_chain = match_chain_type(rhs);
|
||||||
let args = &mut idx_val.as_fn_call_args();
|
let args = &mut idx_val
|
||||||
|
.as_fn_call_args()
|
||||||
|
.expect("never fails because `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,
|
||||||
)?;
|
)?;
|
||||||
@ -1688,17 +1675,19 @@ impl Engine {
|
|||||||
args, constants, ..
|
args, constants, ..
|
||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
let mut arg_values = StaticVec::with_capacity(args.len());
|
let mut arg_values = StaticVec::with_capacity(args.len());
|
||||||
|
let mut first_arg_pos = Position::NONE;
|
||||||
|
|
||||||
for index in 0..args.len() {
|
for index in 0..args.len() {
|
||||||
let (value, _) = self.get_arg_value(
|
let (value, pos) = self.get_arg_value(
|
||||||
scope, mods, state, lib, this_ptr, level, args, constants, index,
|
scope, mods, state, lib, this_ptr, level, args, constants, index,
|
||||||
)?;
|
)?;
|
||||||
arg_values.push(value.flatten());
|
arg_values.push(value.flatten());
|
||||||
|
if index == 0 {
|
||||||
|
first_arg_pos = pos
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos = x.args.get(0).map(Expr::position).unwrap_or_default();
|
idx_values.push((arg_values, first_arg_pos).into());
|
||||||
|
|
||||||
idx_values.push((arg_values, pos).into());
|
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dot => {
|
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dot => {
|
||||||
@ -1730,17 +1719,19 @@ impl Engine {
|
|||||||
args, constants, ..
|
args, constants, ..
|
||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
let mut arg_values = StaticVec::with_capacity(args.len());
|
let mut arg_values = StaticVec::with_capacity(args.len());
|
||||||
|
let mut first_arg_pos = Position::NONE;
|
||||||
|
|
||||||
for index in 0..args.len() {
|
for index in 0..args.len() {
|
||||||
let (value, _) = self.get_arg_value(
|
let (value, pos) = self.get_arg_value(
|
||||||
scope, mods, state, lib, this_ptr, level, args, constants, index,
|
scope, mods, state, lib, this_ptr, level, args, constants, index,
|
||||||
)?;
|
)?;
|
||||||
arg_values.push(value.flatten());
|
arg_values.push(value.flatten());
|
||||||
|
if index == 0 {
|
||||||
|
first_arg_pos = pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos = x.args.get(0).map(Expr::position).unwrap_or_default();
|
(arg_values, first_arg_pos).into()
|
||||||
|
|
||||||
(arg_values, pos).into()
|
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dot => {
|
Expr::FnCall(_, _) if _parent_chain_type == ChainType::Dot => {
|
||||||
|
Loading…
Reference in New Issue
Block a user