Code cleanup and refactor.

This commit is contained in:
Stephen Chung
2022-11-28 23:24:22 +08:00
parent 29a397b216
commit 0c85f0c796
26 changed files with 762 additions and 704 deletions

View File

@@ -5,7 +5,7 @@ use super::{Caches, GlobalRuntimeState, Target};
use crate::ast::{ASTFlags, Expr, OpAssignment};
use crate::config::hashing::SusLock;
use crate::engine::{FN_IDX_GET, FN_IDX_SET};
use crate::tokenizer::Token;
use crate::tokenizer::NO_TOKEN;
use crate::types::{dynamic::Union, RestoreOnDrop};
use crate::{
calc_fn_hash, Dynamic, Engine, FnArgsVec, Position, RhaiResult, RhaiResultOf, Scope, ERR,
@@ -72,17 +72,11 @@ impl Engine {
global.level += 1;
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
self.exec_native_fn_call(
global,
caches,
FN_IDX_GET,
Token::NonToken,
hash_idx().0,
&mut [target, idx],
true,
pos,
)
.map(|(r, ..)| r)
let hash = hash_idx().0;
let args = &mut [target, idx];
self.exec_native_fn_call(global, caches, FN_IDX_GET, NO_TOKEN, hash, args, true, pos)
.map(|(r, ..)| r)
}
/// Call a set indexer.
@@ -101,15 +95,11 @@ impl Engine {
global.level += 1;
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
let hash = hash_idx().1;
let args = &mut [target, idx, new_val];
self.exec_native_fn_call(
global,
caches,
FN_IDX_SET,
Token::NonToken,
hash_idx().1,
&mut [target, idx, new_val],
is_ref_mut,
pos,
global, caches, FN_IDX_SET, NO_TOKEN, hash, args, is_ref_mut, pos,
)
}
@@ -766,15 +756,10 @@ impl Engine {
if op_info.is_op_assignment() {
let args = &mut [target.as_mut()];
let (mut orig_val, ..) = self
.exec_native_fn_call(
global,
caches,
getter,
Token::NonToken,
*hash_get,
args,
is_ref_mut,
global, caches, getter, NO_TOKEN, *hash_get, args, is_ref_mut,
*pos,
)
.or_else(|err| match *err {
@@ -807,15 +792,9 @@ impl Engine {
}
let args = &mut [target.as_mut(), &mut new_val];
self.exec_native_fn_call(
global,
caches,
setter,
Token::NonToken,
*hash_set,
args,
is_ref_mut,
*pos,
global, caches, setter, NO_TOKEN, *hash_set, args, is_ref_mut, *pos,
)
.or_else(|err| match *err {
// Try an indexer if property does not exist
@@ -840,15 +819,9 @@ impl Engine {
let ((getter, hash_get), _, name) = &**x;
let args = &mut [target.as_mut()];
self.exec_native_fn_call(
global,
caches,
getter,
Token::NonToken,
*hash_get,
args,
is_ref_mut,
*pos,
global, caches, getter, NO_TOKEN, *hash_get, args, is_ref_mut, *pos,
)
.map_or_else(
|err| match *err {
@@ -938,20 +911,13 @@ impl Engine {
self.run_debugger(global, caches, scope, this_ptr, _node)?;
let ((getter, hash_get), (setter, hash_set), name) = &**p;
let mut arg_values = [target.as_mut(), &mut Dynamic::UNIT.clone()];
let args = &mut arg_values[..1];
let args = &mut [target.as_mut()];
// Assume getters are always pure
let (mut val, ..) = self
.exec_native_fn_call(
global,
caches,
getter,
Token::NonToken,
*hash_get,
args,
is_ref_mut,
pos,
global, caches, getter, NO_TOKEN, *hash_get, args,
is_ref_mut, pos,
)
.or_else(|err| match *err {
// Try an indexer if property does not exist
@@ -981,19 +947,13 @@ impl Engine {
// Feed the value back via a setter just in case it has been updated
if may_be_changed {
// Re-use args because the first &mut parameter will not be consumed
let mut arg_values = [target.as_mut(), val.as_mut()];
let args = &mut arg_values;
let args = &mut [target.as_mut(), val.as_mut()];
// The return value is thrown away and not used.
let _ = self
.exec_native_fn_call(
global,
caches,
setter,
Token::NonToken,
*hash_set,
args,
is_ref_mut,
pos,
global, caches, setter, NO_TOKEN, *hash_set, args,
is_ref_mut, pos,
)
.or_else(|err| match *err {
// Try an indexer if property does not exist

View File

@@ -508,11 +508,10 @@ impl Engine {
node: ASTNode<'a>,
event: DebuggerEvent,
) -> Result<Option<DebuggerStatus>, Box<crate::EvalAltResult>> {
let src = global.source_raw().cloned();
let src = src.as_ref().map(|s| s.as_str());
let context = crate::EvalContext::new(self, global, caches, scope, this_ptr);
if let Some(ref x) = self.debugger_interface {
let src = global.source_raw().cloned();
let src = src.as_ref().map(|s| s.as_str());
let context = EvalContext::new(self, global, caches, scope, this_ptr);
let (.., ref on_debugger) = **x;
let command = on_debugger(context, event, node, src, node.position())?;

View File

@@ -7,7 +7,6 @@ use std::prelude::v1::*;
/// Context of a script evaluation process.
#[derive(Debug)]
#[allow(dead_code)]
pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
/// The current [`Engine`].
engine: &'a Engine,

View File

@@ -6,13 +6,26 @@ use crate::ast::{
ASTFlags, BinaryExpr, Expr, Ident, OpAssignment, Stmt, SwitchCasesCollection, TryCatchBlock,
};
use crate::func::{get_builtin_op_assignment_fn, get_hasher};
use crate::types::dynamic::AccessMode;
use crate::types::dynamic::{AccessMode, Union};
use crate::types::RestoreOnDrop;
use crate::{Dynamic, Engine, RhaiResult, RhaiResultOf, Scope, ERR, INT};
use std::hash::{Hash, Hasher};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
impl Dynamic {
/// If the value is a string, intern it.
#[inline(always)]
fn intern_string(self, engine: &Engine) -> Self {
match self.0 {
Union::Str(..) => engine
.get_interned_string(self.into_immutable_string().expect("`ImmutableString`"))
.into(),
_ => self,
}
}
}
impl Engine {
/// Evaluate a statements block.
pub(crate) fn eval_stmt_block(
@@ -169,14 +182,13 @@ impl Engine {
self.check_data_size(&*args[0], root.position())?;
} else {
// Normal assignment
// If value is a string, intern it
if new_val.is_string() {
let value = new_val.into_immutable_string().expect("`ImmutableString`");
new_val = self.get_interned_string(value).into();
match target {
// Lock it again just in case it is shared
Target::RefMut(_) | Target::TempValue(_) => {
*target.write_lock::<Dynamic>().unwrap() = new_val
}
_ => **target = new_val,
}
*target.write_lock::<Dynamic>().unwrap() = new_val;
}
target.propagate_changed_value(op_info.pos)
@@ -224,14 +236,13 @@ impl Engine {
let mut target = self.search_namespace(global, caches, scope, this_ptr, lhs)?;
let is_temp_result = !target.is_ref();
let var_name = x.3.as_str();
#[cfg(not(feature = "no_closure"))]
// Also handle case where target is a `Dynamic` shared value
// (returned by a variable resolver, for example)
let is_temp_result = !target.is_ref() && !target.is_shared();
#[cfg(feature = "no_closure")]
let is_temp_result = !target.is_ref();
let is_temp_result = is_temp_result && !target.is_shared();
// Cannot assign to temp result from expression
if is_temp_result {
@@ -251,36 +262,31 @@ impl Engine {
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
{
let mut rhs_val = self
let rhs_val = self
.eval_expr(global, caches, scope, this_ptr, rhs)?
.flatten();
// If value is a string, intern it
if rhs_val.is_string() {
let value = rhs_val.into_immutable_string().expect("`ImmutableString`");
rhs_val = self.get_interned_string(value).into();
}
.flatten()
.intern_string(self);
let _new_val = Some((rhs_val, op_info));
// Must be either `var[index] op= val` or `var.prop op= val`
match lhs {
// name op= rhs (handled above)
Expr::Variable(..) => {
unreachable!("Expr::Variable case is already handled")
}
// idx_lhs[idx_expr] op= rhs
#[cfg(not(feature = "no_index"))]
Expr::Index(..) => {
self.eval_dot_index_chain(global, caches, scope, this_ptr, lhs, _new_val)
}
// dot_lhs.dot_rhs op= rhs
#[cfg(not(feature = "no_object"))]
Expr::Dot(..) => {
self.eval_dot_index_chain(global, caches, scope, this_ptr, lhs, _new_val)
}
_ => unreachable!("cannot assign to expression: {:?}", lhs),
}?;
// Must be either `var[index] op= val` or `var.prop op= val`.
// The return value of any op-assignment (should be `()`) is thrown away and not used.
let _ =
match lhs {
// name op= rhs (handled above)
Expr::Variable(..) => {
unreachable!("Expr::Variable case is already handled")
}
// idx_lhs[idx_expr] op= rhs
#[cfg(not(feature = "no_index"))]
Expr::Index(..) => self
.eval_dot_index_chain(global, caches, scope, this_ptr, lhs, _new_val),
// dot_lhs.dot_rhs op= rhs
#[cfg(not(feature = "no_object"))]
Expr::Dot(..) => self
.eval_dot_index_chain(global, caches, scope, this_ptr, lhs, _new_val),
_ => unreachable!("cannot assign to expression: {:?}", lhs),
}?;
return Ok(Dynamic::UNIT);
}
@@ -723,7 +729,8 @@ impl Engine {
// Evaluate initial value
let mut value = self
.eval_expr(global, caches, scope, this_ptr, expr)?
.flatten();
.flatten()
.intern_string(self);
let _alias = if !rewind_scope {
// Put global constants into global module

View File

@@ -89,9 +89,9 @@ pub enum Target<'a> {
#[cfg(not(feature = "no_closure"))]
SharedValue {
/// Lock guard to the shared [`Dynamic`].
source: crate::types::dynamic::DynamicWriteLock<'a, Dynamic>,
/// Copy of the value.
value: Dynamic,
guard: crate::types::dynamic::DynamicWriteLock<'a, Dynamic>,
/// Copy of the shared value.
shared_value: Dynamic,
},
/// The target is a temporary [`Dynamic`] value (i.e. its mutation can cause no side effects).
TempValue(Dynamic),
@@ -178,21 +178,21 @@ impl<'a> Target<'a> {
}
}
/// Is the [`Target`] a shared value?
#[cfg(not(feature = "no_closure"))]
#[inline]
#[must_use]
pub fn is_shared(&self) -> bool {
match self {
#[cfg(not(feature = "no_closure"))]
return match self {
Self::RefMut(r) => r.is_shared(),
#[cfg(not(feature = "no_closure"))]
Self::SharedValue { .. } => true,
Self::TempValue(value) => value.is_shared(),
#[cfg(not(feature = "no_index"))]
Self::Bit { .. }
| Self::BitField { .. }
| Self::BlobByte { .. }
| Self::StringChar { .. } => false,
}
};
#[cfg(feature = "no_closure")]
return false;
}
/// Get the value of the [`Target`] as a [`Dynamic`], cloning a referenced value if necessary.
#[inline]
@@ -200,7 +200,7 @@ impl<'a> Target<'a> {
match self {
Self::RefMut(r) => r.clone(), // Referenced value is cloned
#[cfg(not(feature = "no_closure"))]
Self::SharedValue { value, .. } => value, // Original shared value is simply taken
Self::SharedValue { shared_value, .. } => shared_value, // Original shared value is simply taken
Self::TempValue(value) => value, // Owned value is simply taken
#[cfg(not(feature = "no_index"))]
Self::Bit { value, .. } => value, // boolean is taken
@@ -227,7 +227,7 @@ impl<'a> Target<'a> {
match self {
Self::RefMut(r) => Self::TempValue(r.clone()),
#[cfg(not(feature = "no_closure"))]
Self::SharedValue { value, .. } => Self::TempValue(value),
Self::SharedValue { shared_value, .. } => Self::TempValue(shared_value),
_ => self,
}
}
@@ -239,7 +239,7 @@ impl<'a> Target<'a> {
match self {
Self::RefMut(r) => r,
#[cfg(not(feature = "no_closure"))]
Self::SharedValue { source, .. } => source,
Self::SharedValue { guard, .. } => guard,
Self::TempValue(value) => value,
#[cfg(not(feature = "no_index"))]
Self::Bit { source, .. } => source,
@@ -365,9 +365,12 @@ impl<'a> From<&'a mut Dynamic> for Target<'a> {
#[cfg(not(feature = "no_closure"))]
if value.is_shared() {
// Cloning is cheap for a shared value
let val = value.clone();
let source = value.write_lock::<Dynamic>().expect("`Dynamic`");
return Self::SharedValue { source, value: val };
let shared_value = value.clone();
let guard = value.write_lock::<Dynamic>().expect("`Dynamic`");
return Self::SharedValue {
guard,
shared_value,
};
}
Self::RefMut(value)
@@ -382,7 +385,7 @@ impl Deref for Target<'_> {
match self {
Self::RefMut(r) => r,
#[cfg(not(feature = "no_closure"))]
Self::SharedValue { source, .. } => source,
Self::SharedValue { guard, .. } => guard,
Self::TempValue(ref value) => value,
#[cfg(not(feature = "no_index"))]
Self::Bit { ref value, .. }
@@ -415,7 +418,7 @@ impl DerefMut for Target<'_> {
match self {
Self::RefMut(r) => r,
#[cfg(not(feature = "no_closure"))]
Self::SharedValue { source, .. } => &mut *source,
Self::SharedValue { guard, .. } => &mut *guard,
Self::TempValue(ref mut value) => value,
#[cfg(not(feature = "no_index"))]
Self::Bit { ref mut value, .. }