Optimize functions calling.
This commit is contained in:
parent
b141e8d0e1
commit
fde8483f54
@ -69,7 +69,7 @@ impl fmt::Debug for AST {
|
|||||||
impl AST {
|
impl AST {
|
||||||
/// Create a new [`AST`].
|
/// Create a new [`AST`].
|
||||||
#[cfg(not(feature = "internals"))]
|
#[cfg(not(feature = "internals"))]
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
statements: impl IntoIterator<Item = Stmt>,
|
statements: impl IntoIterator<Item = Stmt>,
|
||||||
@ -89,7 +89,7 @@ impl AST {
|
|||||||
/// _(internals)_ Create a new [`AST`].
|
/// _(internals)_ Create a new [`AST`].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
statements: impl IntoIterator<Item = Stmt>,
|
statements: impl IntoIterator<Item = Stmt>,
|
||||||
@ -108,7 +108,7 @@ impl AST {
|
|||||||
}
|
}
|
||||||
/// Create a new [`AST`] with a source name.
|
/// Create a new [`AST`] with a source name.
|
||||||
#[cfg(not(feature = "internals"))]
|
#[cfg(not(feature = "internals"))]
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) fn new_with_source(
|
pub(crate) fn new_with_source(
|
||||||
statements: impl IntoIterator<Item = Stmt>,
|
statements: impl IntoIterator<Item = Stmt>,
|
||||||
@ -126,7 +126,7 @@ impl AST {
|
|||||||
/// _(internals)_ Create a new [`AST`] with a source name.
|
/// _(internals)_ Create a new [`AST`] with a source name.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_with_source(
|
pub fn new_with_source(
|
||||||
statements: impl IntoIterator<Item = Stmt>,
|
statements: impl IntoIterator<Item = Stmt>,
|
||||||
@ -157,7 +157,7 @@ impl AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the source, if any.
|
/// Get the source, if any.
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn source(&self) -> Option<&str> {
|
pub fn source(&self) -> Option<&str> {
|
||||||
if self.source.is_empty() {
|
if self.source.is_empty() {
|
||||||
@ -664,7 +664,6 @@ impl AST {
|
|||||||
self.combine_filtered_impl(other, filter)
|
self.combine_filtered_impl(other, filter)
|
||||||
}
|
}
|
||||||
/// Combine one [`AST`] with another. The second [`AST`] is consumed.
|
/// Combine one [`AST`] with another. The second [`AST`] is consumed.
|
||||||
#[inline]
|
|
||||||
fn combine_filtered_impl(
|
fn combine_filtered_impl(
|
||||||
&mut self,
|
&mut self,
|
||||||
other: Self,
|
other: Self,
|
||||||
@ -957,19 +956,21 @@ pub enum ASTNode<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Stmt> for ASTNode<'a> {
|
impl<'a> From<&'a Stmt> for ASTNode<'a> {
|
||||||
|
#[inline(always)]
|
||||||
fn from(stmt: &'a Stmt) -> Self {
|
fn from(stmt: &'a Stmt) -> Self {
|
||||||
Self::Stmt(stmt)
|
Self::Stmt(stmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Expr> for ASTNode<'a> {
|
impl<'a> From<&'a Expr> for ASTNode<'a> {
|
||||||
|
#[inline(always)]
|
||||||
fn from(expr: &'a Expr) -> Self {
|
fn from(expr: &'a Expr) -> Self {
|
||||||
Self::Expr(expr)
|
Self::Expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for ASTNode<'_> {
|
impl PartialEq for ASTNode<'_> {
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Self::Stmt(x), Self::Stmt(y)) => ptr::eq(*x, *y),
|
(Self::Stmt(x), Self::Stmt(y)) => ptr::eq(*x, *y),
|
||||||
@ -986,8 +987,8 @@ impl ASTNode<'_> {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn position(&self) -> Position {
|
pub fn position(&self) -> Position {
|
||||||
match self {
|
match self {
|
||||||
ASTNode::Stmt(stmt) => stmt.position(),
|
Self::Stmt(stmt) => stmt.position(),
|
||||||
ASTNode::Expr(expr) => expr.position(),
|
Self::Expr(expr) => expr.position(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ impl fmt::Debug for FnCallHashes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<u64> for FnCallHashes {
|
impl From<u64> for FnCallHashes {
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
fn from(hash: u64) -> Self {
|
fn from(hash: u64) -> Self {
|
||||||
let hash = if hash == 0 { ALT_ZERO_HASH } else { hash };
|
let hash = if hash == 0 { ALT_ZERO_HASH } else { hash };
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ impl From<u64> for FnCallHashes {
|
|||||||
|
|
||||||
impl FnCallHashes {
|
impl FnCallHashes {
|
||||||
/// Create a [`FnCallHashes`] with only the native Rust hash.
|
/// Create a [`FnCallHashes`] with only the native Rust hash.
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn from_native(hash: u64) -> Self {
|
pub const fn from_native(hash: u64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -158,7 +158,7 @@ impl FnCallHashes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Create a [`FnCallHashes`] with both native Rust and script function hashes.
|
/// Create a [`FnCallHashes`] with both native Rust and script function hashes.
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn from_all(#[cfg(not(feature = "no_function"))] script: u64, native: u64) -> Self {
|
pub const fn from_all(#[cfg(not(feature = "no_function"))] script: u64, native: u64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -252,7 +252,7 @@ pub struct FloatWrapper<F>(F);
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl Hash for FloatWrapper<crate::FLOAT> {
|
impl Hash for FloatWrapper<crate::FLOAT> {
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.0.to_ne_bytes().hash(state);
|
self.0.to_ne_bytes().hash(state);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ pub enum FnAccess {
|
|||||||
|
|
||||||
impl FnAccess {
|
impl FnAccess {
|
||||||
/// Is this function private?
|
/// Is this function private?
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn is_private(self) -> bool {
|
pub const fn is_private(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
@ -27,7 +27,7 @@ impl FnAccess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Is this function public?
|
/// Is this function public?
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn is_public(self) -> bool {
|
pub const fn is_public(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
@ -87,7 +87,7 @@ impl DerefMut for Namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Ident>> for Namespace {
|
impl From<Vec<Ident>> for Namespace {
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
fn from(mut path: Vec<Ident>) -> Self {
|
fn from(mut path: Vec<Ident>) -> Self {
|
||||||
path.shrink_to_fit();
|
path.shrink_to_fit();
|
||||||
Self {
|
Self {
|
||||||
@ -98,7 +98,7 @@ impl From<Vec<Ident>> for Namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<StaticVec<Ident>> for Namespace {
|
impl From<StaticVec<Ident>> for Namespace {
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
fn from(mut path: StaticVec<Ident>) -> Self {
|
fn from(mut path: StaticVec<Ident>) -> Self {
|
||||||
path.shrink_to_fit();
|
path.shrink_to_fit();
|
||||||
Self { index: None, path }
|
Self { index: None, path }
|
||||||
|
@ -50,7 +50,7 @@ impl Engine {
|
|||||||
idx_values: &mut FnArgsVec<Dynamic>,
|
idx_values: &mut FnArgsVec<Dynamic>,
|
||||||
chain_type: ChainType,
|
chain_type: ChainType,
|
||||||
level: usize,
|
level: usize,
|
||||||
new_val: Option<(Dynamic, &OpAssignment)>,
|
new_val: &mut Option<(Dynamic, &OpAssignment)>,
|
||||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
) -> RhaiResultOf<(Dynamic, bool)> {
|
||||||
let is_ref_mut = target.is_ref();
|
let is_ref_mut = target.is_ref();
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(scope, global, lib, this_ptr, _parent, level)?;
|
self.run_debugger(scope, global, lib, this_ptr, _parent, level)?;
|
||||||
|
|
||||||
let idx_val = idx_values.pop().unwrap();
|
let idx_val = &mut idx_values.pop().unwrap();
|
||||||
let mut idx_val_for_setter = idx_val.clone();
|
let mut idx_val_for_setter = idx_val.clone();
|
||||||
let idx_pos = x.lhs.start_position();
|
let idx_pos = x.lhs.start_position();
|
||||||
let rhs_chain = rhs.into();
|
let rhs_chain = rhs.into();
|
||||||
@ -119,12 +119,12 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(scope, global, lib, this_ptr, _parent, level)?;
|
self.run_debugger(scope, global, lib, this_ptr, _parent, level)?;
|
||||||
|
|
||||||
let (new_val, op_info) = new_val.expect("`Some`");
|
let (new_val, op_info) = new_val.take().expect("`Some`");
|
||||||
let idx_val = idx_values.pop().unwrap();
|
let idx_val = &mut idx_values.pop().unwrap();
|
||||||
let mut idx_val2 = idx_val.clone();
|
let idx = &mut idx_val.clone();
|
||||||
|
|
||||||
let try_setter = match self.get_indexed_mut(
|
let try_setter = match self.get_indexed_mut(
|
||||||
global, caches, lib, target, idx_val, pos, true, false, level,
|
global, caches, lib, target, idx, pos, true, false, level,
|
||||||
) {
|
) {
|
||||||
// Indexed value is not a temp value - update directly
|
// Indexed value is not a temp value - update directly
|
||||||
Ok(ref mut obj_ptr) => {
|
Ok(ref mut obj_ptr) => {
|
||||||
@ -143,11 +143,10 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(mut new_val) = try_setter {
|
if let Some(mut new_val) = try_setter {
|
||||||
let idx = &mut idx_val2;
|
|
||||||
|
|
||||||
// Is this an op-assignment?
|
// Is this an op-assignment?
|
||||||
if op_info.is_op_assignment() {
|
if op_info.is_op_assignment() {
|
||||||
let idx = &mut idx.clone();
|
let idx = &mut idx_val.clone();
|
||||||
|
|
||||||
// Call the index getter to get the current value
|
// Call the index getter to get the current value
|
||||||
if let Ok(val) =
|
if let Ok(val) =
|
||||||
self.call_indexer_get(global, caches, lib, target, idx, level)
|
self.call_indexer_get(global, caches, lib, target, idx, level)
|
||||||
@ -167,8 +166,9 @@ impl Engine {
|
|||||||
|
|
||||||
// Try to call index setter
|
// Try to call index setter
|
||||||
let new_val = &mut new_val;
|
let new_val = &mut new_val;
|
||||||
|
|
||||||
self.call_indexer_set(
|
self.call_indexer_set(
|
||||||
global, caches, lib, target, idx, new_val, is_ref_mut, level,
|
global, caches, lib, target, idx_val, new_val, is_ref_mut, level,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(scope, global, lib, this_ptr, _parent, level)?;
|
self.run_debugger(scope, global, lib, this_ptr, _parent, level)?;
|
||||||
|
|
||||||
let idx_val = idx_values.pop().unwrap();
|
let idx_val = &mut idx_values.pop().unwrap();
|
||||||
|
|
||||||
self.get_indexed_mut(
|
self.get_indexed_mut(
|
||||||
global, caches, lib, target, idx_val, pos, false, true, level,
|
global, caches, lib, target, idx_val, pos, false, true, level,
|
||||||
@ -236,8 +236,8 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(scope, global, lib, this_ptr, rhs, level)?;
|
self.run_debugger(scope, global, lib, this_ptr, rhs, level)?;
|
||||||
|
|
||||||
let index = x.2.clone().into();
|
let index = &mut x.2.clone().into();
|
||||||
let (new_val, op_info) = new_val.expect("`Some`");
|
let (new_val, op_info) = new_val.take().expect("`Some`");
|
||||||
{
|
{
|
||||||
let val_target = &mut self.get_indexed_mut(
|
let val_target = &mut self.get_indexed_mut(
|
||||||
global, caches, lib, target, index, *pos, true, false, level,
|
global, caches, lib, target, index, *pos, true, false, level,
|
||||||
@ -255,7 +255,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(scope, global, lib, this_ptr, rhs, level)?;
|
self.run_debugger(scope, global, lib, this_ptr, rhs, level)?;
|
||||||
|
|
||||||
let index = x.2.clone().into();
|
let index = &mut x.2.clone().into();
|
||||||
let val = self.get_indexed_mut(
|
let val = self.get_indexed_mut(
|
||||||
global, caches, lib, target, index, *pos, false, false, level,
|
global, caches, lib, target, index, *pos, false, false, level,
|
||||||
)?;
|
)?;
|
||||||
@ -267,7 +267,7 @@ impl Engine {
|
|||||||
self.run_debugger(scope, global, lib, this_ptr, rhs, level)?;
|
self.run_debugger(scope, global, lib, this_ptr, rhs, level)?;
|
||||||
|
|
||||||
let ((getter, hash_get), (setter, hash_set), name) = &**x;
|
let ((getter, hash_get), (setter, hash_set), name) = &**x;
|
||||||
let (mut new_val, op_info) = new_val.expect("`Some`");
|
let (mut new_val, op_info) = new_val.take().expect("`Some`");
|
||||||
|
|
||||||
if op_info.is_op_assignment() {
|
if op_info.is_op_assignment() {
|
||||||
let args = &mut [target.as_mut()];
|
let args = &mut [target.as_mut()];
|
||||||
@ -368,7 +368,7 @@ impl Engine {
|
|||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
self.run_debugger(scope, global, lib, this_ptr, _node, level)?;
|
self.run_debugger(scope, global, lib, this_ptr, _node, level)?;
|
||||||
|
|
||||||
let index = p.2.clone().into();
|
let index = &mut p.2.clone().into();
|
||||||
self.get_indexed_mut(
|
self.get_indexed_mut(
|
||||||
global, caches, lib, target, index, pos, false, true, level,
|
global, caches, lib, target, index, pos, false, true, level,
|
||||||
)?
|
)?
|
||||||
@ -558,7 +558,7 @@ impl Engine {
|
|||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
level: usize,
|
level: usize,
|
||||||
new_val: Option<(Dynamic, &OpAssignment)>,
|
new_val: &mut Option<(Dynamic, &OpAssignment)>,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let chain_type = ChainType::from(expr);
|
let chain_type = ChainType::from(expr);
|
||||||
let (crate::ast::BinaryExpr { lhs, rhs }, options, op_pos) = match expr {
|
let (crate::ast::BinaryExpr { lhs, rhs }, options, op_pos) = match expr {
|
||||||
@ -595,7 +595,7 @@ impl Engine {
|
|||||||
// All other patterns - evaluate the arguments chain
|
// All other patterns - evaluate the arguments chain
|
||||||
_ => {
|
_ => {
|
||||||
self.eval_dot_index_chain_arguments(
|
self.eval_dot_index_chain_arguments(
|
||||||
scope, global, caches, lib, this_ptr, rhs, options, chain_type, idx_values, 0,
|
scope, global, caches, lib, this_ptr, rhs, options, chain_type, idx_values,
|
||||||
level,
|
level,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@ -653,7 +653,6 @@ impl Engine {
|
|||||||
parent_options: ASTFlags,
|
parent_options: ASTFlags,
|
||||||
_parent_chain_type: ChainType,
|
_parent_chain_type: ChainType,
|
||||||
idx_values: &mut FnArgsVec<Dynamic>,
|
idx_values: &mut FnArgsVec<Dynamic>,
|
||||||
size: usize,
|
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> RhaiResultOf<()> {
|
) -> RhaiResultOf<()> {
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
@ -731,7 +730,7 @@ impl Engine {
|
|||||||
|
|
||||||
self.eval_dot_index_chain_arguments(
|
self.eval_dot_index_chain_arguments(
|
||||||
scope, global, caches, lib, this_ptr, rhs, *options, chain_type, idx_values,
|
scope, global, caches, lib, this_ptr, rhs, *options, chain_type, idx_values,
|
||||||
size, level,
|
level,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if !_arg_values.is_empty() {
|
if !_arg_values.is_empty() {
|
||||||
@ -809,7 +808,7 @@ impl Engine {
|
|||||||
caches: &mut Caches,
|
caches: &mut Caches,
|
||||||
lib: &[&Module],
|
lib: &[&Module],
|
||||||
target: &'t mut Dynamic,
|
target: &'t mut Dynamic,
|
||||||
mut idx: Dynamic,
|
idx: &mut Dynamic,
|
||||||
idx_pos: Position,
|
idx_pos: Position,
|
||||||
_add_if_not_found: bool,
|
_add_if_not_found: bool,
|
||||||
use_indexers: bool,
|
use_indexers: bool,
|
||||||
@ -1018,7 +1017,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ if use_indexers => self
|
_ if use_indexers => self
|
||||||
.call_indexer_get(global, caches, lib, target, &mut idx, level)
|
.call_indexer_get(global, caches, lib, target, idx, level)
|
||||||
.map(Into::into),
|
.map(Into::into),
|
||||||
|
|
||||||
_ => Err(ERR::ErrorIndexingType(
|
_ => Err(ERR::ErrorIndexingType(
|
||||||
|
@ -561,14 +561,12 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Index(..) => {
|
Expr::Index(..) => self
|
||||||
self.eval_dot_index_chain(scope, global, caches, lib, this_ptr, expr, level, None)
|
.eval_dot_index_chain(scope, global, caches, lib, this_ptr, expr, level, &mut None),
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Dot(..) => {
|
Expr::Dot(..) => self
|
||||||
self.eval_dot_index_chain(scope, global, caches, lib, this_ptr, expr, level, None)
|
.eval_dot_index_chain(scope, global, caches, lib, this_ptr, expr, level, &mut None),
|
||||||
}
|
|
||||||
|
|
||||||
_ => unreachable!("expression cannot be evaluated: {:?}", expr),
|
_ => unreachable!("expression cannot be evaluated: {:?}", expr),
|
||||||
};
|
};
|
||||||
|
@ -187,15 +187,6 @@ impl Engine {
|
|||||||
*target.write_lock::<Dynamic>().unwrap() = new_val;
|
*target.write_lock::<Dynamic>().unwrap() = new_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if let Some(mut guard) = target.write_lock::<Dynamic>() {
|
|
||||||
if guard.is::<ImmutableString>() {
|
|
||||||
let s = std::mem::take(&mut *guard).cast::<ImmutableString>();
|
|
||||||
*guard = self.get_interned_string(s).into();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
target.propagate_changed_value(op_info.pos)
|
target.propagate_changed_value(op_info.pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,19 +286,25 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
let (op_info, BinaryExpr { lhs, rhs }) = &**x;
|
let (op_info, BinaryExpr { lhs, rhs }) = &**x;
|
||||||
|
|
||||||
let rhs_result = self
|
let rhs_result = self.eval_expr(scope, global, caches, lib, this_ptr, rhs, level);
|
||||||
.eval_expr(scope, global, caches, lib, this_ptr, rhs, level)
|
|
||||||
.map(Dynamic::flatten);
|
|
||||||
|
|
||||||
if let Ok(rhs_val) = rhs_result {
|
if let Ok(rhs_val) = rhs_result {
|
||||||
let rhs_val = if rhs_val.is::<ImmutableString>() {
|
// Check if the result is a string. If so, intern it.
|
||||||
self.get_interned_string(rhs_val.cast::<ImmutableString>())
|
#[cfg(not(feature = "no_closure"))]
|
||||||
.into()
|
let is_string = !rhs_val.is_shared() && rhs_val.is::<ImmutableString>();
|
||||||
|
#[cfg(feature = "no_closure")]
|
||||||
|
let is_string = rhs_val.is::<ImmutableString>();
|
||||||
|
|
||||||
|
let rhs_val = if is_string {
|
||||||
|
self.get_interned_string(
|
||||||
|
rhs_val.into_immutable_string().expect("`ImmutableString`"),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
} else {
|
} else {
|
||||||
rhs_val
|
rhs_val.flatten()
|
||||||
};
|
};
|
||||||
|
|
||||||
let _new_val = Some((rhs_val, op_info));
|
let _new_val = &mut Some((rhs_val, op_info));
|
||||||
|
|
||||||
// Must be either `var[index] op= val` or `var.prop op= val`
|
// Must be either `var[index] op= val` or `var.prop op= val`
|
||||||
match lhs {
|
match lhs {
|
||||||
@ -317,20 +314,17 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// idx_lhs[idx_expr] op= rhs
|
// idx_lhs[idx_expr] op= rhs
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Index(..) => self
|
Expr::Index(..) => self.eval_dot_index_chain(
|
||||||
.eval_dot_index_chain(
|
scope, global, caches, lib, this_ptr, lhs, level, _new_val,
|
||||||
scope, global, caches, lib, this_ptr, lhs, level, _new_val,
|
),
|
||||||
)
|
|
||||||
.map(|_| Dynamic::UNIT),
|
|
||||||
// dot_lhs.dot_rhs op= rhs
|
// dot_lhs.dot_rhs op= rhs
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Dot(..) => self
|
Expr::Dot(..) => self.eval_dot_index_chain(
|
||||||
.eval_dot_index_chain(
|
scope, global, caches, lib, this_ptr, lhs, level, _new_val,
|
||||||
scope, global, caches, lib, this_ptr, lhs, level, _new_val,
|
),
|
||||||
)
|
|
||||||
.map(|_| Dynamic::UNIT),
|
|
||||||
_ => unreachable!("cannot assign to expression: {:?}", lhs),
|
_ => unreachable!("cannot assign to expression: {:?}", lhs),
|
||||||
}
|
}
|
||||||
|
.map(|_| Dynamic::UNIT)
|
||||||
} else {
|
} else {
|
||||||
rhs_result
|
rhs_result
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user