Eliminate unnecessary data structures.
This commit is contained in:
parent
a5d4a0abb9
commit
b091113334
@ -2,8 +2,8 @@
|
|||||||
name = "rhai_codegen"
|
name = "rhai_codegen"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["jhwgh1968"]
|
authors = ["jhwgh1968", "Stephen Chung"]
|
||||||
description = "Procedural macro support package for Rhai, a scripting language for Rust"
|
description = "Procedural macros support package for Rhai, a scripting language and engine for Rust"
|
||||||
homepage = "https://rhai.rs/book/plugins/index.html"
|
homepage = "https://rhai.rs/book/plugins/index.html"
|
||||||
repository = "https://github.com/rhaiscript/rhai"
|
repository = "https://github.com/rhaiscript/rhai"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
156
src/engine.rs
156
src/engine.rs
@ -51,35 +51,42 @@ pub type Precedence = NonZeroU8;
|
|||||||
// We cannot use Cow<str> here because `eval` may load a [module][Module] and
|
// We cannot use Cow<str> here because `eval` may load a [module][Module] and
|
||||||
// the module name will live beyond the AST of the eval script text.
|
// the module name will live beyond the AST of the eval script text.
|
||||||
// The best we can do is a shared reference.
|
// The best we can do is a shared reference.
|
||||||
|
//
|
||||||
|
// This implementation splits the module names from the shared modules to improve data locality.
|
||||||
|
// Most usage will be looking up a particular key from the list and then getting the module that
|
||||||
|
// corresponds to that key.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Imports(StaticVec<Identifier>, StaticVec<Shared<Module>>);
|
pub struct Imports {
|
||||||
|
keys: StaticVec<Identifier>,
|
||||||
|
modules: StaticVec<Shared<Module>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Imports {
|
impl Imports {
|
||||||
/// Get the length of this stack of imported [modules][Module].
|
/// Get the length of this stack of imported [modules][Module].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.len()
|
self.keys.len()
|
||||||
}
|
}
|
||||||
/// Is this stack of imported [modules][Module] empty?
|
/// Is this stack of imported [modules][Module] empty?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.is_empty()
|
self.keys.is_empty()
|
||||||
}
|
}
|
||||||
/// Get the imported [modules][Module] at a particular index.
|
/// Get the imported [modules][Module] at a particular index.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get(&self, index: usize) -> Option<Shared<Module>> {
|
pub fn get(&self, index: usize) -> Option<Shared<Module>> {
|
||||||
self.1.get(index).cloned()
|
self.modules.get(index).cloned()
|
||||||
}
|
}
|
||||||
/// Get the imported [modules][Module] at a particular index.
|
/// Get the imported [modules][Module] at a particular index.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut Shared<Module>> {
|
pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut Shared<Module>> {
|
||||||
self.1.get_mut(index)
|
self.modules.get_mut(index)
|
||||||
}
|
}
|
||||||
/// Get the index of an imported [modules][Module] by name.
|
/// Get the index of an imported [modules][Module] by name.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn find(&self, name: &str) -> Option<usize> {
|
pub fn find(&self, name: &str) -> Option<usize> {
|
||||||
self.0
|
self.keys
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev()
|
.rev()
|
||||||
@ -88,22 +95,22 @@ impl Imports {
|
|||||||
/// Push an imported [modules][Module] onto the stack.
|
/// Push an imported [modules][Module] onto the stack.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push(&mut self, name: impl Into<Identifier>, module: impl Into<Shared<Module>>) {
|
pub fn push(&mut self, name: impl Into<Identifier>, module: impl Into<Shared<Module>>) {
|
||||||
self.0.push(name.into());
|
self.keys.push(name.into());
|
||||||
self.1.push(module.into());
|
self.modules.push(module.into());
|
||||||
}
|
}
|
||||||
/// Truncate the stack of imported [modules][Module] to a particular length.
|
/// Truncate the stack of imported [modules][Module] to a particular length.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn truncate(&mut self, size: usize) {
|
pub fn truncate(&mut self, size: usize) {
|
||||||
self.0.truncate(size);
|
self.keys.truncate(size);
|
||||||
self.1.truncate(size);
|
self.modules.truncate(size);
|
||||||
}
|
}
|
||||||
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
|
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter(&self) -> impl Iterator<Item = (&str, &Module)> {
|
pub fn iter(&self) -> impl Iterator<Item = (&str, &Module)> {
|
||||||
self.0
|
self.keys
|
||||||
.iter()
|
.iter()
|
||||||
.zip(self.1.iter())
|
.zip(self.modules.iter())
|
||||||
.rev()
|
.rev()
|
||||||
.map(|(name, module)| (name.as_str(), module.as_ref()))
|
.map(|(name, module)| (name.as_str(), module.as_ref()))
|
||||||
}
|
}
|
||||||
@ -111,29 +118,32 @@ impl Imports {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn iter_raw(&self) -> impl Iterator<Item = (&Identifier, &Shared<Module>)> {
|
pub(crate) fn iter_raw(&self) -> impl Iterator<Item = (&Identifier, &Shared<Module>)> {
|
||||||
self.0.iter().rev().zip(self.1.iter().rev())
|
self.keys.iter().rev().zip(self.modules.iter().rev())
|
||||||
}
|
}
|
||||||
/// Get an iterator to this stack of imported [modules][Module] in forward order.
|
/// Get an iterator to this stack of imported [modules][Module] in forward order.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn scan_raw(&self) -> impl Iterator<Item = (&Identifier, &Shared<Module>)> {
|
pub(crate) fn scan_raw(&self) -> impl Iterator<Item = (&Identifier, &Shared<Module>)> {
|
||||||
self.0.iter().zip(self.1.iter())
|
self.keys.iter().zip(self.modules.iter())
|
||||||
}
|
}
|
||||||
/// Get a consuming iterator to this stack of imported [modules][Module] in reverse order.
|
/// Get a consuming iterator to this stack of imported [modules][Module] in reverse order.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn into_iter(self) -> impl Iterator<Item = (Identifier, Shared<Module>)> {
|
pub fn into_iter(self) -> impl Iterator<Item = (Identifier, Shared<Module>)> {
|
||||||
self.0.into_iter().rev().zip(self.1.into_iter().rev())
|
self.keys
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.zip(self.modules.into_iter().rev())
|
||||||
}
|
}
|
||||||
/// Does the specified function hash key exist in this stack of imported [modules][Module]?
|
/// Does the specified function hash key exist in this stack of imported [modules][Module]?
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn contains_fn(&self, hash: u64) -> bool {
|
pub fn contains_fn(&self, hash: u64) -> bool {
|
||||||
self.1.iter().any(|m| m.contains_qualified_fn(hash))
|
self.modules.iter().any(|m| m.contains_qualified_fn(hash))
|
||||||
}
|
}
|
||||||
/// Get specified function via its hash key.
|
/// Get specified function via its hash key.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&Identifier>)> {
|
pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&Identifier>)> {
|
||||||
self.1
|
self.modules
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
|
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
|
||||||
@ -143,12 +153,15 @@ impl Imports {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn contains_iter(&self, id: TypeId) -> bool {
|
pub fn contains_iter(&self, id: TypeId) -> bool {
|
||||||
self.1.iter().any(|m| m.contains_qualified_iter(id))
|
self.modules.iter().any(|m| m.contains_qualified_iter(id))
|
||||||
}
|
}
|
||||||
/// Get the specified [`TypeId`][std::any::TypeId] iterator.
|
/// Get the specified [`TypeId`][std::any::TypeId] iterator.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
|
pub fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
|
||||||
self.1.iter().rev().find_map(|m| m.get_qualified_iter(id))
|
self.modules
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.find_map(|m| m.get_qualified_iter(id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +173,7 @@ impl fmt::Debug for Imports {
|
|||||||
f.debug_map().finish()
|
f.debug_map().finish()
|
||||||
} else {
|
} else {
|
||||||
f.debug_map()
|
f.debug_map()
|
||||||
.entries(self.0.iter().zip(self.1.iter()))
|
.entries(self.keys.iter().zip(self.modules.iter()))
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,24 +245,27 @@ pub const TOKEN_OP_CONCAT: Token = Token::PlusAssign;
|
|||||||
/// Method of chaining.
|
/// Method of chaining.
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum ChainType {
|
enum ChainType {
|
||||||
/// Not a chaining type.
|
|
||||||
NonChaining,
|
|
||||||
/// Indexing.
|
/// Indexing.
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
Index,
|
Index,
|
||||||
/// Dotting.
|
/// Dotting.
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
Dot,
|
Dot,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Value of a chaining argument.
|
/// Value of a chaining argument.
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum ChainArgument {
|
enum ChainArgument {
|
||||||
/// Dot-property access.
|
/// Dot-property access.
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
Property(Position),
|
Property(Position),
|
||||||
/// Arguments to a dot-function call.
|
/// Arguments to a dot method call.
|
||||||
FnCallArgs(StaticVec<Dynamic>, StaticVec<Position>),
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
MethodCallArgs(StaticVec<Dynamic>, StaticVec<Position>),
|
||||||
/// Index value.
|
/// Index value.
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
IndexValue(Dynamic, Position),
|
IndexValue(Dynamic, Position),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +280,8 @@ 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(_, _) => {
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
Self::Property(_) | Self::MethodCallArgs(_, _) => {
|
||||||
panic!("expecting ChainArgument::IndexValue")
|
panic!("expecting ChainArgument::IndexValue")
|
||||||
}
|
}
|
||||||
Self::IndexValue(value, _) => value,
|
Self::IndexValue(value, _) => value,
|
||||||
@ -274,28 +291,32 @@ impl ChainArgument {
|
|||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if not `ChainArgument::FnCallArgs`.
|
/// Panics if not `ChainArgument::MethodCallArgs`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub fn as_fn_call_args(self) -> (StaticVec<Dynamic>, StaticVec<Position>) {
|
pub fn as_fn_call_args(self) -> (StaticVec<Dynamic>, StaticVec<Position>) {
|
||||||
match self {
|
match self {
|
||||||
Self::Property(_) | Self::IndexValue(_, _) => {
|
Self::Property(_) => {
|
||||||
panic!("expecting ChainArgument::FnCallArgs")
|
panic!("expecting ChainArgument::MethodCallArgs")
|
||||||
}
|
}
|
||||||
Self::FnCallArgs(values, positions) => (values, positions),
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
Self::IndexValue(_, _) => {
|
||||||
|
panic!("expecting ChainArgument::MethodCallArgs")
|
||||||
|
}
|
||||||
|
Self::MethodCallArgs(values, positions) => (values, positions),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
impl From<(StaticVec<Dynamic>, StaticVec<Position>)> for ChainArgument {
|
impl From<(StaticVec<Dynamic>, StaticVec<Position>)> for ChainArgument {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from((values, positions): (StaticVec<Dynamic>, StaticVec<Position>)) -> Self {
|
fn from((values, positions): (StaticVec<Dynamic>, StaticVec<Position>)) -> Self {
|
||||||
Self::FnCallArgs(values, positions)
|
Self::MethodCallArgs(values, positions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
impl From<(Dynamic, Position)> for ChainArgument {
|
impl From<(Dynamic, Position)> for ChainArgument {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from((value, pos): (Dynamic, Position)) -> Self {
|
fn from((value, pos): (Dynamic, Position)) -> Self {
|
||||||
@ -1129,14 +1150,14 @@ impl Engine {
|
|||||||
level: usize,
|
level: usize,
|
||||||
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
|
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
assert!(chain_type != ChainType::NonChaining);
|
|
||||||
|
|
||||||
let is_ref = target.is_ref();
|
let is_ref = target.is_ref();
|
||||||
|
|
||||||
let next_chain = match rhs {
|
let rhs_chain = match rhs {
|
||||||
Expr::Index(_, _) => ChainType::Index,
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Dot(_, _) => ChainType::Dot,
|
Expr::Index(_, _) => Some(ChainType::Index),
|
||||||
_ => ChainType::NonChaining,
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
Expr::Dot(_, _) => Some(ChainType::Dot),
|
||||||
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pop the last index value
|
// Pop the last index value
|
||||||
@ -1155,9 +1176,10 @@ impl Engine {
|
|||||||
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, is_ref, true, level,
|
mods, state, lib, target, idx_val, idx_pos, false, is_ref, true, level,
|
||||||
)?;
|
)?;
|
||||||
|
let rhs_chain = rhs_chain.unwrap();
|
||||||
|
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
mods, state, lib, this_ptr, obj_ptr, &x.rhs, idx_values, next_chain,
|
mods, state, lib, this_ptr, obj_ptr, &x.rhs, idx_values, rhs_chain,
|
||||||
level, new_val,
|
level, new_val,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*x_pos))
|
.map_err(|err| err.fill_position(*x_pos))
|
||||||
@ -1340,9 +1362,10 @@ impl Engine {
|
|||||||
// Others - syntax error
|
// Others - syntax error
|
||||||
expr => unreachable!("invalid dot expression: {:?}", expr),
|
expr => unreachable!("invalid dot expression: {:?}", expr),
|
||||||
};
|
};
|
||||||
|
let rhs_chain = rhs_chain.unwrap();
|
||||||
|
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
mods, state, lib, this_ptr, &mut val, &x.rhs, idx_values, next_chain,
|
mods, state, lib, this_ptr, &mut val, &x.rhs, idx_values, rhs_chain,
|
||||||
level, new_val,
|
level, new_val,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*x_pos))
|
.map_err(|err| err.fill_position(*x_pos))
|
||||||
@ -1354,6 +1377,7 @@ impl Engine {
|
|||||||
Expr::Property(p) => {
|
Expr::Property(p) => {
|
||||||
let ((getter, hash_get), (setter, hash_set), Ident { pos, .. }) =
|
let ((getter, hash_get), (setter, hash_set), Ident { pos, .. }) =
|
||||||
p.as_ref();
|
p.as_ref();
|
||||||
|
let rhs_chain = rhs_chain.unwrap();
|
||||||
let hash_get = FnCallHashes::from_native(*hash_get);
|
let hash_get = FnCallHashes::from_native(*hash_get);
|
||||||
let hash_set = FnCallHashes::from_native(*hash_set);
|
let hash_set = FnCallHashes::from_native(*hash_set);
|
||||||
let arg_values = &mut [target.as_mut(), &mut Default::default()];
|
let arg_values = &mut [target.as_mut(), &mut Default::default()];
|
||||||
@ -1374,7 +1398,7 @@ impl Engine {
|
|||||||
&mut val.into(),
|
&mut val.into(),
|
||||||
&x.rhs,
|
&x.rhs,
|
||||||
idx_values,
|
idx_values,
|
||||||
next_chain,
|
rhs_chain,
|
||||||
level,
|
level,
|
||||||
new_val,
|
new_val,
|
||||||
)
|
)
|
||||||
@ -1405,6 +1429,7 @@ impl Engine {
|
|||||||
// xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr
|
// xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr
|
||||||
Expr::FnCall(f, pos) if !f.is_qualified() => {
|
Expr::FnCall(f, pos) if !f.is_qualified() => {
|
||||||
let FnCallExpr { name, hashes, .. } = f.as_ref();
|
let FnCallExpr { name, hashes, .. } = f.as_ref();
|
||||||
|
let rhs_chain = rhs_chain.unwrap();
|
||||||
let mut args = idx_val.as_fn_call_args();
|
let mut args = idx_val.as_fn_call_args();
|
||||||
let (mut val, _) = self.make_method_call(
|
let (mut val, _) = self.make_method_call(
|
||||||
mods, state, lib, name, *hashes, target, &mut args, *pos, level,
|
mods, state, lib, name, *hashes, target, &mut args, *pos, level,
|
||||||
@ -1414,7 +1439,7 @@ impl Engine {
|
|||||||
|
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
mods, state, lib, this_ptr, target, &x.rhs, idx_values,
|
mods, state, lib, this_ptr, target, &x.rhs, idx_values,
|
||||||
next_chain, level, new_val,
|
rhs_chain, level, new_val,
|
||||||
)
|
)
|
||||||
.map_err(|err| err.fill_position(*pos))
|
.map_err(|err| err.fill_position(*pos))
|
||||||
}
|
}
|
||||||
@ -1430,8 +1455,6 @@ impl Engine {
|
|||||||
_ => EvalAltResult::ErrorDotExpr("".into(), rhs.position()).into(),
|
_ => EvalAltResult::ErrorDotExpr("".into(), rhs.position()).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chain_type => unreachable!("invalid ChainType: {:?}", chain_type),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1449,7 +1472,9 @@ impl Engine {
|
|||||||
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
|
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let (crate::ast::BinaryExpr { lhs, rhs }, chain_type, op_pos) = match expr {
|
let (crate::ast::BinaryExpr { lhs, rhs }, chain_type, op_pos) = match expr {
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Index(x, pos) => (x.as_ref(), ChainType::Index, *pos),
|
Expr::Index(x, pos) => (x.as_ref(), ChainType::Index, *pos),
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Dot(x, pos) => (x.as_ref(), ChainType::Dot, *pos),
|
Expr::Dot(x, pos) => (x.as_ref(), ChainType::Dot, *pos),
|
||||||
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
||||||
};
|
};
|
||||||
@ -1510,7 +1535,7 @@ impl Engine {
|
|||||||
lib: &[&Module],
|
lib: &[&Module],
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
parent_chain_type: ChainType,
|
_parent_chain_type: ChainType,
|
||||||
idx_values: &mut StaticVec<ChainArgument>,
|
idx_values: &mut StaticVec<ChainArgument>,
|
||||||
size: usize,
|
size: usize,
|
||||||
level: usize,
|
level: usize,
|
||||||
@ -1519,7 +1544,8 @@ impl Engine {
|
|||||||
self.inc_operations(state, expr.position())?;
|
self.inc_operations(state, expr.position())?;
|
||||||
|
|
||||||
match expr {
|
match expr {
|
||||||
Expr::FnCall(x, _) if parent_chain_type == ChainType::Dot && !x.is_qualified() => {
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
Expr::FnCall(x, _) if _parent_chain_type == ChainType::Dot && !x.is_qualified() => {
|
||||||
let mut arg_positions: StaticVec<_> = Default::default();
|
let mut arg_positions: StaticVec<_> = Default::default();
|
||||||
|
|
||||||
let mut arg_values = x
|
let mut arg_values = x
|
||||||
@ -1539,11 +1565,13 @@ impl Engine {
|
|||||||
|
|
||||||
idx_values.push((arg_values, arg_positions).into());
|
idx_values.push((arg_values, arg_positions).into());
|
||||||
}
|
}
|
||||||
Expr::FnCall(_, _) if parent_chain_type == ChainType::Dot => {
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Property(x) if parent_chain_type == ChainType::Dot => {
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
Expr::Property(x) if _parent_chain_type == ChainType::Dot => {
|
||||||
idx_values.push(ChainArgument::Property(x.2.pos))
|
idx_values.push(ChainArgument::Property(x.2.pos))
|
||||||
}
|
}
|
||||||
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
|
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
|
||||||
@ -1553,12 +1581,15 @@ impl Engine {
|
|||||||
|
|
||||||
// Evaluate in left-to-right order
|
// Evaluate in left-to-right order
|
||||||
let lhs_val = match lhs {
|
let lhs_val = match lhs {
|
||||||
Expr::Property(x) if parent_chain_type == ChainType::Dot => {
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
Expr::Property(x) if _parent_chain_type == ChainType::Dot => {
|
||||||
ChainArgument::Property(x.2.pos)
|
ChainArgument::Property(x.2.pos)
|
||||||
}
|
}
|
||||||
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
|
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::FnCall(x, _)
|
Expr::FnCall(x, _)
|
||||||
if parent_chain_type == ChainType::Dot && !x.is_qualified() =>
|
if _parent_chain_type == ChainType::Dot && !x.is_qualified() =>
|
||||||
{
|
{
|
||||||
let mut arg_positions: StaticVec<_> = Default::default();
|
let mut arg_positions: StaticVec<_> = Default::default();
|
||||||
|
|
||||||
@ -1579,17 +1610,26 @@ impl Engine {
|
|||||||
|
|
||||||
(arg_values, arg_positions).into()
|
(arg_values, arg_positions).into()
|
||||||
}
|
}
|
||||||
Expr::FnCall(_, _) if parent_chain_type == ChainType::Dot => {
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
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")
|
||||||
}
|
}
|
||||||
_ => self
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
expr if _parent_chain_type == ChainType::Dot => {
|
||||||
|
unreachable!("invalid dot expression: {:?}", expr);
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
_ if _parent_chain_type == ChainType::Index => 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| (v.flatten(), lhs.position()).into())?,
|
||||||
|
expr => unreachable!("unknown chained expression: {:?}", expr),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Push in reverse order
|
// Push in reverse order
|
||||||
let chain_type = match expr {
|
let chain_type = match expr {
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Index(_, _) => ChainType::Index,
|
Expr::Index(_, _) => ChainType::Index,
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Dot(_, _) => ChainType::Dot,
|
Expr::Dot(_, _) => ChainType::Dot,
|
||||||
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
||||||
};
|
};
|
||||||
@ -1600,10 +1640,16 @@ impl Engine {
|
|||||||
idx_values.push(lhs_val);
|
idx_values.push(lhs_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => idx_values.push(
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
_ if _parent_chain_type == ChainType::Dot => {
|
||||||
|
unreachable!("invalid dot expression: {:?}", expr);
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
_ if _parent_chain_type == ChainType::Index => 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| (v.flatten(), expr.position()).into())?,
|
||||||
),
|
),
|
||||||
|
_ => unreachable!("unknown chained expression: {:?}", expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -187,10 +187,10 @@ impl Position {
|
|||||||
}
|
}
|
||||||
/// Print this [`Position`] for debug purposes.
|
/// Print this [`Position`] for debug purposes.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn debug_print(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
pub(crate) fn debug_print(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(not(feature = "no_position"))]
|
#[cfg(not(feature = "no_position"))]
|
||||||
if !self.is_none() {
|
if !self.is_none() {
|
||||||
write!(f, " @ {:?}", self)?;
|
write!(_f, " @ {:?}", self)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user