Remove Dynamic::NULL, use .as_deref_mut() for this_ptr.

This commit is contained in:
Stephen Chung
2022-12-20 16:52:55 +08:00
parent 99080be91d
commit babc0b5466
16 changed files with 235 additions and 255 deletions

View File

@@ -340,7 +340,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
expr: &Expr,
new_val: Option<(Dynamic, &OpAssignment)>,
) -> RhaiResult {
@@ -379,7 +379,13 @@ impl Engine {
}
// All other patterns - evaluate the arguments chain
_ => self.eval_dot_index_chain_arguments(
global, caches, scope, this_ptr, expr, rhs, idx_values,
global,
caches,
scope,
this_ptr.as_deref_mut(),
expr,
rhs,
idx_values,
)?,
}
@@ -387,22 +393,13 @@ impl Engine {
// id.??? or id[???]
Expr::Variable(.., var_pos) => {
#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr, lhs)?;
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), lhs)?;
self.track_operation(global, *var_pos)?;
let target = &mut self.search_namespace(global, caches, scope, this_ptr, lhs)?;
let mut this_ptr = Dynamic::NULL;
self.eval_dot_index_chain_raw(
global,
caches,
&mut this_ptr,
lhs,
expr,
target,
rhs,
idx_values,
new_val,
global, caches, None, lhs, expr, target, rhs, idx_values, new_val,
)
}
// {expr}.??? = ??? or {expr}[???] = ???
@@ -410,7 +407,7 @@ impl Engine {
// {expr}.??? or {expr}[???]
lhs_expr => {
let value = self
.eval_expr(global, caches, scope, this_ptr, lhs_expr)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), lhs_expr)?
.flatten();
let obj_ptr = &mut value.into();
@@ -428,7 +425,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
parent: &Expr,
expr: &Expr,
idx_values: &mut FnArgsVec<Dynamic>,
@@ -440,12 +437,10 @@ impl Engine {
match expr {
#[cfg(not(feature = "no_object"))]
Expr::MethodCall(x, ..) if chain_type == ChainType::Dotting && !x.is_qualified() => {
for arg_expr in &x.args {
idx_values.push(
self.get_arg_value(global, caches, scope, this_ptr, arg_expr)?
.0
.flatten(),
);
for expr in &x.args {
let arg_value =
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
idx_values.push(arg_value.0.flatten());
}
}
#[cfg(not(feature = "no_object"))]
@@ -474,12 +469,15 @@ impl Engine {
Expr::MethodCall(x, ..)
if chain_type == ChainType::Dotting && !x.is_qualified() =>
{
for arg_expr in &x.args {
_arg_values.push(
self.get_arg_value(global, caches, scope, this_ptr, arg_expr)?
.0
.flatten(),
);
for expr in &x.args {
let arg_value = self.get_arg_value(
global,
caches,
scope,
this_ptr.as_deref_mut(),
expr,
)?;
_arg_values.push(arg_value.0.flatten());
}
}
#[cfg(not(feature = "no_object"))]
@@ -493,7 +491,7 @@ impl Engine {
#[cfg(not(feature = "no_index"))]
_ if chain_type == ChainType::Indexing => {
_arg_values.push(
self.eval_expr(global, caches, scope, this_ptr, lhs)?
self.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), lhs)?
.flatten(),
);
}
@@ -530,7 +528,7 @@ impl Engine {
&self,
global: &mut GlobalRuntimeState,
caches: &mut Caches,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
root: &Expr,
parent: &Expr,
target: &mut Target,
@@ -560,7 +558,7 @@ impl Engine {
if !parent.options().contains(ASTFlags::BREAK) =>
{
#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr, parent)?;
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), parent)?;
let idx_val = &mut idx_values.pop().unwrap();
let mut idx_val_for_setter = idx_val.clone();
@@ -843,7 +841,13 @@ impl Engine {
let val_target = &mut match x.lhs {
Expr::Property(ref p, pos) => {
#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr, _node)?;
self.run_debugger(
global,
caches,
scope,
this_ptr.as_deref_mut(),
_node,
)?;
let index = &mut p.2.clone().into();
self.get_indexed_mut(
@@ -854,7 +858,11 @@ impl Engine {
Expr::MethodCall(ref x, pos) if !x.is_qualified() => {
#[cfg(feature = "debugging")]
let reset = self.run_debugger_with_reset(
global, caches, scope, this_ptr, _node,
global,
caches,
scope,
this_ptr.as_deref_mut(),
_node,
)?;
#[cfg(feature = "debugging")]
auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset));
@@ -896,7 +904,13 @@ impl Engine {
// xxx.prop[expr] | xxx.prop.expr
Expr::Property(ref p, pos) => {
#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr, _node)?;
self.run_debugger(
global,
caches,
scope,
this_ptr.as_deref_mut(),
_node,
)?;
let ((getter, hash_get), (setter, hash_set), name) = &**p;
let args = &mut [target.as_mut()];
@@ -972,7 +986,11 @@ impl Engine {
let val = {
#[cfg(feature = "debugging")]
let reset = self.run_debugger_with_reset(
global, caches, scope, this_ptr, _node,
global,
caches,
scope,
this_ptr.as_deref_mut(),
_node,
)?;
#[cfg(feature = "debugging")]
auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset));

View File

@@ -410,7 +410,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
this_ptr: Option<&mut Dynamic>,
node: impl Into<ASTNode<'a>>,
) -> RhaiResultOf<()> {
if self.is_debugger_registered() {
@@ -435,7 +435,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
this_ptr: Option<&mut Dynamic>,
node: impl Into<ASTNode<'a>>,
) -> RhaiResultOf<Option<DebuggerStatus>> {
if self.is_debugger_registered() {
@@ -456,7 +456,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
this_ptr: Option<&mut Dynamic>,
node: impl Into<ASTNode<'a>>,
) -> RhaiResultOf<Option<DebuggerStatus>> {
let node = node.into();
@@ -502,7 +502,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
this_ptr: Option<&mut Dynamic>,
node: ASTNode<'a>,
event: DebuggerEvent,
) -> Result<Option<DebuggerStatus>, Box<crate::EvalAltResult>> {

View File

@@ -17,7 +17,7 @@ pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
/// The current [`Scope`].
scope: &'s mut Scope<'ps>,
/// The current bound `this` pointer, if any.
this_ptr: &'t mut Dynamic,
this_ptr: Option<&'t mut Dynamic>,
}
impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
@@ -29,7 +29,7 @@ impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
global: &'g mut GlobalRuntimeState,
caches: &'c mut Caches,
scope: &'s mut Scope<'ps>,
this_ptr: &'t mut Dynamic,
this_ptr: Option<&'t mut Dynamic>,
) -> Self {
Self {
engine,
@@ -118,24 +118,16 @@ impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
&self.global.lib
}
/// The current bound `this` pointer, if any.
#[inline]
#[inline(always)]
#[must_use]
pub fn this_ptr(&self) -> Option<&Dynamic> {
if self.this_ptr.is_null() {
None
} else {
Some(self.this_ptr)
}
self.this_ptr.as_deref()
}
/// Mutable reference to the current bound `this` pointer, if any.
#[inline]
#[inline(always)]
#[must_use]
pub fn this_ptr_mut(&mut self) -> Option<&mut Dynamic> {
if self.this_ptr.is_null() {
None
} else {
Some(self.this_ptr)
}
self.this_ptr.as_deref_mut()
}
/// The current nesting level of function calls.
#[inline(always)]
@@ -177,19 +169,20 @@ impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
rewind_scope: bool,
) -> crate::RhaiResult {
let expr: &crate::ast::Expr = expr;
let this_ptr = self.this_ptr.as_deref_mut();
match expr {
crate::ast::Expr::Stmt(statements) => self.engine.eval_stmt_block(
crate::ast::Expr::Stmt(stmts) => self.engine.eval_stmt_block(
self.global,
self.caches,
self.scope,
self.this_ptr,
statements,
this_ptr,
stmts,
rewind_scope,
),
_ => self
.engine
.eval_expr(self.global, self.caches, self.scope, self.this_ptr, expr),
.eval_expr(self.global, self.caches, self.scope, this_ptr, expr),
}
}
}

View File

@@ -53,7 +53,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &'s mut Scope,
this_ptr: &'s mut Dynamic,
this_ptr: Option<&'s mut Dynamic>,
expr: &Expr,
) -> RhaiResultOf<Target<'s>> {
match expr {
@@ -132,7 +132,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &'s mut Scope,
this_ptr: &'s mut Dynamic,
this_ptr: Option<&'s mut Dynamic>,
expr: &Expr,
) -> RhaiResultOf<Target<'s>> {
// Make sure that the pointer indirection is taken only when absolutely necessary.
@@ -142,10 +142,10 @@ impl Engine {
Expr::Variable(v, None, ..)
if v.0.is_none() && v.1.is_empty() && v.3 == KEYWORD_THIS =>
{
return if this_ptr.is_null() {
Err(ERR::ErrorUnboundThis(expr.position()).into())
} else {
return if let Some(this_ptr) = this_ptr {
Ok(this_ptr.into())
} else {
Err(ERR::ErrorUnboundThis(expr.position()).into())
};
}
@@ -223,7 +223,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
expr: &Expr,
) -> RhaiResult {
// Coded this way for better branch prediction.
@@ -233,7 +233,8 @@ impl Engine {
// binary operators are also function calls.
if let Expr::FnCall(x, pos) = expr {
#[cfg(feature = "debugging")]
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?;
let reset =
self.run_debugger_with_reset(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
#[cfg(feature = "debugging")]
auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset));
@@ -247,16 +248,14 @@ impl Engine {
// will cost more than the mis-predicted `match` branch.
if let Expr::Variable(x, index, var_pos) = expr {
#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr, expr)?;
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
self.track_operation(global, expr.position())?;
return if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS {
if this_ptr.is_null() {
ERR::ErrorUnboundThis(*var_pos).into()
} else {
Ok(this_ptr.clone())
}
this_ptr
.ok_or_else(|| ERR::ErrorUnboundThis(*var_pos).into())
.cloned()
} else {
self.search_namespace(global, caches, scope, this_ptr, expr)
.map(Target::take_or_clone)
@@ -264,7 +263,8 @@ impl Engine {
}
#[cfg(feature = "debugging")]
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?;
let reset =
self.run_debugger_with_reset(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
#[cfg(feature = "debugging")]
auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset));
@@ -291,7 +291,7 @@ impl Engine {
x.iter()
.try_for_each(|expr| {
let item = self
.eval_expr(global, caches, scope, this_ptr, expr)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)?
.flatten();
op_info.pos = expr.start_position();
@@ -312,7 +312,13 @@ impl Engine {
crate::Array::with_capacity(x.len()),
|mut array, item_expr| {
let value = self
.eval_expr(global, caches, scope, this_ptr, item_expr)?
.eval_expr(
global,
caches,
scope,
this_ptr.as_deref_mut(),
item_expr,
)?
.flatten();
#[cfg(not(feature = "unchecked"))]
@@ -344,7 +350,7 @@ impl Engine {
x.0.iter()
.try_fold(x.1.clone(), |mut map, (key, value_expr)| {
let value = self
.eval_expr(global, caches, scope, this_ptr, value_expr)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), value_expr)?
.flatten();
#[cfg(not(feature = "unchecked"))]
@@ -367,7 +373,7 @@ impl Engine {
}
Expr::And(x, ..) => Ok((self
.eval_expr(global, caches, scope, this_ptr, &x.lhs)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), &x.lhs)?
.as_bool()
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, x.lhs.position()))?
&& self
@@ -377,7 +383,7 @@ impl Engine {
.into()),
Expr::Or(x, ..) => Ok((self
.eval_expr(global, caches, scope, this_ptr, &x.lhs)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), &x.lhs)?
.as_bool()
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, x.lhs.position()))?
|| self
@@ -387,7 +393,8 @@ impl Engine {
.into()),
Expr::Coalesce(x, ..) => {
let value = self.eval_expr(global, caches, scope, this_ptr, &x.lhs)?;
let value =
self.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), &x.lhs)?;
if value.is_unit() {
self.eval_expr(global, caches, scope, this_ptr, &x.rhs)

View File

@@ -32,7 +32,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
statements: &[Stmt],
restore_orig_state: bool,
) -> RhaiResult {
@@ -71,6 +71,8 @@ impl Engine {
// Run the statements
statements.iter().try_fold(Dynamic::UNIT, |_, stmt| {
let this_ptr = this_ptr.as_deref_mut();
#[cfg(not(feature = "no_module"))]
let imports_len = global.num_imports();
@@ -198,12 +200,13 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
stmt: &Stmt,
rewind_scope: bool,
) -> RhaiResult {
#[cfg(feature = "debugging")]
let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, stmt)?;
let reset =
self.run_debugger_with_reset(global, caches, scope, this_ptr.as_deref_mut(), stmt)?;
#[cfg(feature = "debugging")]
auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset));
@@ -227,7 +230,7 @@ impl Engine {
if let Expr::Variable(x, ..) = lhs {
let rhs_val = self
.eval_expr(global, caches, scope, this_ptr, rhs)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), rhs)?
.flatten();
let mut target = self.search_namespace(global, caches, scope, this_ptr, lhs)?;
@@ -259,7 +262,7 @@ impl Engine {
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
{
let rhs_val = self
.eval_expr(global, caches, scope, this_ptr, rhs)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), rhs)?
.flatten()
.intern_string(self);
@@ -310,7 +313,7 @@ impl Engine {
let (expr, if_block, else_block) = &**x;
let guard_val = self
.eval_expr(global, caches, scope, this_ptr, expr)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)?
.as_bool()
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, expr.position()))?;
@@ -337,7 +340,7 @@ impl Engine {
let mut result = None;
let value = self.eval_expr(global, caches, scope, this_ptr, expr)?;
let value = self.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
if value.is_hashable() {
let hasher = &mut get_hasher();
@@ -354,7 +357,7 @@ impl Engine {
let cond_result = match block.condition {
Expr::BoolConstant(b, ..) => b,
ref c => self
.eval_expr(global, caches, scope, this_ptr, c)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), c)?
.as_bool()
.map_err(|typ| {
self.make_type_mismatch_err::<bool>(typ, c.position())
@@ -376,7 +379,7 @@ impl Engine {
let cond_result = match block.condition {
Expr::BoolConstant(b, ..) => b,
ref c => self
.eval_expr(global, caches, scope, this_ptr, c)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), c)?
.as_bool()
.map_err(|typ| {
self.make_type_mismatch_err::<bool>(typ, c.position())
@@ -409,14 +412,15 @@ impl Engine {
}
loop {
if let Err(err) =
self.eval_stmt_block(global, caches, scope, this_ptr, body, true)
{
match *err {
let this_ptr = this_ptr.as_deref_mut();
match self.eval_stmt_block(global, caches, scope, this_ptr, body, true) {
Ok(..) => (),
Err(err) => match *err {
ERR::LoopBreak(false, ..) => (),
ERR::LoopBreak(true, value, ..) => break Ok(value),
_ => break Err(err),
}
},
}
}
}
@@ -427,7 +431,7 @@ impl Engine {
loop {
let condition = self
.eval_expr(global, caches, scope, this_ptr, expr)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)?
.as_bool()
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, expr.position()))?;
@@ -439,14 +443,15 @@ impl Engine {
continue;
}
if let Err(err) =
self.eval_stmt_block(global, caches, scope, this_ptr, body, true)
{
match *err {
let this_ptr = this_ptr.as_deref_mut();
match self.eval_stmt_block(global, caches, scope, this_ptr, body, true) {
Ok(..) => (),
Err(err) => match *err {
ERR::LoopBreak(false, ..) => (),
ERR::LoopBreak(true, value, ..) => break Ok(value),
_ => break Err(err),
}
},
}
}
}
@@ -458,19 +463,20 @@ impl Engine {
loop {
if !body.is_empty() {
if let Err(err) =
self.eval_stmt_block(global, caches, scope, this_ptr, body, true)
{
match *err {
let this_ptr = this_ptr.as_deref_mut();
match self.eval_stmt_block(global, caches, scope, this_ptr, body, true) {
Ok(..) => (),
Err(err) => match *err {
ERR::LoopBreak(false, ..) => continue,
ERR::LoopBreak(true, value, ..) => break Ok(value),
_ => break Err(err),
}
},
}
}
let condition = self
.eval_expr(global, caches, scope, this_ptr, expr)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)?
.as_bool()
.map_err(|typ| self.make_type_mismatch_err::<bool>(typ, expr.position()))?;
@@ -485,7 +491,7 @@ impl Engine {
let (var_name, counter, expr, statements) = &**x;
let iter_obj = self
.eval_expr(global, caches, scope, this_ptr, expr)?
.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)?
.flatten();
let iter_type = iter_obj.type_id();
@@ -566,6 +572,8 @@ impl Engine {
continue;
}
let this_ptr = this_ptr.as_deref_mut();
match self.eval_stmt_block(global, caches, scope, this_ptr, statements, true) {
Ok(_) => (),
Err(err) => match *err {
@@ -603,7 +611,14 @@ impl Engine {
catch_block,
} = &**x;
match self.eval_stmt_block(global, caches, scope, this_ptr, try_block, true) {
match self.eval_stmt_block(
global,
caches,
scope,
this_ptr.as_deref_mut(),
try_block,
true,
) {
r @ Ok(_) => r,
Err(err) if err.is_pseudo_error() => Err(err),
Err(err) if !err.is_catchable() => Err(err),
@@ -650,6 +665,8 @@ impl Engine {
scope.push(catch_var.name.clone(), err_value);
}
let this_ptr = this_ptr.as_deref_mut();
self.eval_stmt_block(global, caches, scope, this_ptr, catch_block, true)
.map(|_| Dynamic::UNIT)
.map_err(|result_err| match *result_err {
@@ -707,7 +724,8 @@ impl Engine {
nesting_level: global.scope_level,
will_shadow,
};
let context = EvalContext::new(self, global, caches, scope, this_ptr);
let context =
EvalContext::new(self, global, caches, scope, this_ptr.as_deref_mut());
if !filter(true, info, context)? {
return Err(ERR::ErrorForbiddenVariable(var_name.to_string(), *pos).into());
@@ -866,7 +884,7 @@ impl Engine {
/// Evaluate a list of statements with no `this` pointer.
/// This is commonly used to evaluate a list of statements in an [`AST`][crate::AST] or a script function body.
#[inline]
#[inline(always)]
pub(crate) fn eval_global_statements(
&self,
global: &mut GlobalRuntimeState,
@@ -874,9 +892,7 @@ impl Engine {
scope: &mut Scope,
statements: &[Stmt],
) -> RhaiResult {
let mut this_ptr = Dynamic::NULL;
self.eval_stmt_block(global, caches, scope, &mut this_ptr, statements, false)
self.eval_stmt_block(global, caches, scope, None, statements, false)
.or_else(|err| match *err {
ERR::Return(out, ..) => Ok(out),
ERR::LoopBreak(..) => {