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

@ -219,17 +219,11 @@ impl Engine {
let orig_lib_len = global.lib.len();
let mut orig_tag = None;
if let Some(value) = options.tag {
orig_tag = Some(mem::replace(&mut global.tag, value));
}
let orig_tag = options.tag.map(|v| mem::replace(&mut global.tag, v));
let mut this_ptr = options.this_ptr;
global.lib.push(ast.shared_lib().clone());
let mut no_this_ptr = Dynamic::NULL;
let this_ptr = options.this_ptr.unwrap_or(&mut no_this_ptr);
#[cfg(not(feature = "no_module"))]
let orig_embedded_module_resolver = std::mem::replace(
&mut global.embedded_module_resolver,
@ -264,7 +258,7 @@ impl Engine {
global,
caches,
scope,
this_ptr,
this_ptr.as_deref_mut(),
None,
fn_def,
args,
@ -279,7 +273,7 @@ impl Engine {
if self.is_debugger_registered() {
global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate;
let node = &crate::ast::Stmt::Noop(Position::NONE);
self.run_debugger(global, caches, scope, this_ptr, node)?;
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), node)?;
}
#[cfg(not(feature = "no_module"))]

View File

@ -250,9 +250,8 @@ impl Engine {
#[cfg(feature = "debugging")]
if self.is_debugger_registered() {
global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate;
let mut this_ptr = Dynamic::NULL;
let node = &crate::ast::Stmt::Noop(Position::NONE);
self.run_debugger(global, caches, scope, &mut this_ptr, node)?;
self.run_debugger(global, caches, scope, None, node)?;
}
Ok(r)
})

View File

@ -131,9 +131,8 @@ impl Engine {
#[cfg(feature = "debugging")]
if self.is_debugger_registered() {
global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate;
let mut this_ptr = crate::Dynamic::NULL;
let node = &crate::ast::Stmt::Noop(crate::Position::NONE);
self.run_debugger(global, caches, scope, &mut this_ptr, node)?;
self.run_debugger(global, caches, scope, None, node)?;
}
Ok(())
})

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(..) => {

View File

@ -438,7 +438,6 @@ impl Engine {
};
if trigger {
let scope = &mut Scope::new();
let mut this_ptr = Dynamic::NULL;
let node = crate::ast::Stmt::Noop(pos);
let node = (&node).into();
let event = match _result {
@ -446,10 +445,9 @@ impl Engine {
Err(ref err) => DebuggerEvent::FunctionExitWithError(err),
};
if let Err(err) =
self.run_debugger_raw(global, caches, scope, &mut this_ptr, node, event)
{
_result = Err(err);
match self.run_debugger_raw(global, caches, scope, None, node, event) {
Ok(..) => (),
Err(err) => _result = Err(err),
}
}
@ -676,7 +674,15 @@ impl Engine {
let (first_arg, rest_args) = _args.split_first_mut().unwrap();
self.call_script_fn(
global, caches, scope, first_arg, environ, f, rest_args, true, pos,
global,
caches,
scope,
Some(first_arg),
environ,
f,
rest_args,
true,
pos,
)
} else {
// Normal call of script function
@ -691,19 +697,7 @@ impl Engine {
auto_restore!(args = (_args) if swap => move |a| backup.restore_first_arg(a));
let mut this_ptr = Dynamic::NULL;
self.call_script_fn(
global,
caches,
scope,
&mut this_ptr,
environ,
f,
args,
true,
pos,
)
self.call_script_fn(global, caches, scope, None, environ, f, args, true, pos)
}
.map(|r| (r, false));
}
@ -724,7 +718,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
this_ptr: Option<&mut Dynamic>,
arg_expr: &Expr,
) -> RhaiResultOf<(Dynamic, Position)> {
// Literal values
@ -782,14 +776,12 @@ impl Engine {
#[cfg(not(feature = "no_function"))]
if let Some(fn_def) = fn_ptr.fn_def() {
if fn_def.params.len() == args.len() {
let mut this_ptr = Dynamic::NULL;
return self
.call_script_fn(
global,
caches,
&mut Scope::new(),
&mut this_ptr,
None,
fn_ptr.encapsulated_environ(),
fn_def,
args,
@ -876,7 +868,7 @@ impl Engine {
global,
caches,
&mut Scope::new(),
target,
Some(target),
_environ.as_deref(),
&fn_def,
args,
@ -1018,7 +1010,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
fn_name: &str,
op_token: Token,
first_arg: Option<&Expr>,
@ -1042,7 +1034,7 @@ impl Engine {
KEYWORD_FN_PTR_CALL if total_args >= 1 => {
let arg = first_arg.unwrap();
let (arg_value, arg_pos) =
self.get_arg_value(global, caches, scope, this_ptr, arg)?;
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), arg)?;
if !arg_value.is_fnptr() {
let typ = self.map_type_name(arg_value.type_name());
@ -1074,23 +1066,17 @@ impl Engine {
.into_iter()
.map(Ok)
.chain(a_expr.iter().map(|expr| -> Result<_, RhaiError> {
let this_ptr = this_ptr.as_deref_mut();
self.get_arg_value(global, caches, scope, this_ptr, expr)
.map(|(v, ..)| v)
}))
.collect::<RhaiResultOf<FnArgsVec<_>>>()?;
let args = &mut arg_values.iter_mut().collect::<FnArgsVec<_>>();
let mut this_ptr = Dynamic::NULL;
let scope = &mut Scope::new();
let environ = _environ.as_deref();
return self.call_script_fn(
global,
caches,
&mut Scope::new(),
&mut this_ptr,
_environ.as_deref(),
&fn_def,
args,
true,
pos,
global, caches, scope, None, environ, &fn_def, args, true, pos,
);
}
}
@ -1134,7 +1120,7 @@ impl Engine {
KEYWORD_FN_PTR_CURRY if total_args > 1 => {
let first = first_arg.unwrap();
let (arg_value, arg_pos) =
self.get_arg_value(global, caches, scope, this_ptr, first)?;
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), first)?;
if !arg_value.is_fnptr() {
let typ = self.map_type_name(arg_value.type_name());
@ -1145,7 +1131,8 @@ impl Engine {
// Append the new curried arguments to the existing list.
a_expr.iter().try_for_each(|expr| -> Result<_, RhaiError> {
let (value, ..) = self.get_arg_value(global, caches, scope, this_ptr, expr)?;
let (value, ..) =
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
fn_ptr.add_curry(value);
Ok(())
})?;
@ -1157,7 +1144,8 @@ impl Engine {
#[cfg(not(feature = "no_closure"))]
crate::engine::KEYWORD_IS_SHARED if total_args == 1 => {
let arg = first_arg.unwrap();
let (arg_value, ..) = self.get_arg_value(global, caches, scope, this_ptr, arg)?;
let (arg_value, ..) =
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), arg)?;
return Ok(arg_value.is_shared().into());
}
@ -1166,7 +1154,7 @@ impl Engine {
crate::engine::KEYWORD_IS_DEF_FN if total_args == 2 => {
let first = first_arg.unwrap();
let (arg_value, arg_pos) =
self.get_arg_value(global, caches, scope, this_ptr, first)?;
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), first)?;
let fn_name = arg_value
.into_immutable_string()
@ -1258,7 +1246,7 @@ impl Engine {
.copied()
.chain(a_expr.iter())
.try_for_each(|expr| {
self.get_arg_value(global, caches, scope, this_ptr, expr)
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)
.map(|(value, ..)| arg_values.push(value.flatten()))
})?;
args.extend(curry.iter_mut());
@ -1286,11 +1274,11 @@ impl Engine {
let first_expr = first_arg.unwrap();
#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr, first_expr)?;
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?;
// func(x, ...) -> x.func(...)
a_expr.iter().try_for_each(|expr| {
self.get_arg_value(global, caches, scope, this_ptr, expr)
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)
.map(|(value, ..)| arg_values.push(value.flatten()))
})?;
@ -1317,7 +1305,7 @@ impl Engine {
.into_iter()
.chain(a_expr.iter())
.try_for_each(|expr| {
self.get_arg_value(global, caches, scope, this_ptr, expr)
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)
.map(|(value, ..)| arg_values.push(value.flatten()))
})?;
args.extend(curry.iter_mut());
@ -1339,7 +1327,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
namespace: &crate::ast::Namespace,
fn_name: &str,
args_expr: &[Expr],
@ -1358,13 +1346,19 @@ impl Engine {
// and avoid cloning the value
if !args_expr.is_empty() && args_expr[0].is_variable_access(true) {
#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr, &args_expr[0])?;
self.run_debugger(
global,
caches,
scope,
this_ptr.as_deref_mut(),
&args_expr[0],
)?;
// func(x, ...) -> x.func(...)
arg_values.push(Dynamic::UNIT);
args_expr.iter().skip(1).try_for_each(|expr| {
self.get_arg_value(global, caches, scope, this_ptr, expr)
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)
.map(|(value, ..)| arg_values.push(value.flatten()))
})?;
@ -1393,7 +1387,7 @@ impl Engine {
} else {
// func(..., ...) or func(mod::x, ...)
args_expr.iter().try_for_each(|expr| {
self.get_arg_value(global, caches, scope, this_ptr, expr)
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)
.map(|(value, ..)| arg_values.push(value.flatten()))
})?;
args.extend(arg_values.iter_mut());
@ -1466,25 +1460,14 @@ impl Engine {
#[cfg(not(feature = "no_function"))]
Some(func) if func.is_script() => {
let f = func.get_script_fn_def().expect("script-defined function");
let environ = func.get_encapsulated_environ();
let environ = func.get_encapsulated_environ();
let scope = &mut Scope::new();
let mut this_ptr = Dynamic::NULL;
let orig_source = mem::replace(&mut global.source, module.id_raw().cloned());
auto_restore!(global => move |g| g.source = orig_source);
self.call_script_fn(
global,
caches,
scope,
&mut this_ptr,
environ,
f,
args,
true,
pos,
)
self.call_script_fn(global, caches, scope, None, environ, f, args, true, pos)
}
Some(f) if f.is_plugin_fn() => {
@ -1581,7 +1564,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
expr: &FnCallExpr,
pos: Position,
) -> RhaiResult {
@ -1601,7 +1584,7 @@ impl Engine {
// Short-circuit native unary operator call if under Fast Operators mode
if op_token == Token::Bang && self.fast_operators() && args.len() == 1 {
let mut value = self
.get_arg_value(global, caches, scope, this_ptr, &args[0])?
.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), &args[0])?
.0
.flatten();
@ -1617,7 +1600,7 @@ impl Engine {
// Short-circuit native binary operator call if under Fast Operators mode
if op_token != NO_TOKEN && self.fast_operators() && args.len() == 2 {
let mut lhs = self
.get_arg_value(global, caches, scope, this_ptr, &args[0])?
.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), &args[0])?
.0
.flatten();

View File

@ -28,7 +28,7 @@ impl Engine {
global: &mut GlobalRuntimeState,
caches: &mut Caches,
scope: &mut Scope,
this_ptr: &mut Dynamic,
mut this_ptr: Option<&mut Dynamic>,
_environ: Option<&EncapsulatedEnviron>,
fn_def: &ScriptFnDef,
args: &mut FnCallArgs,
@ -108,12 +108,19 @@ impl Engine {
#[cfg(feature = "debugging")]
if self.is_debugger_registered() {
let node = crate::ast::Stmt::Noop(fn_def.body.position());
self.run_debugger(global, caches, scope, this_ptr, &node)?;
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), &node)?;
}
// Evaluate the function
let mut _result: RhaiResult = self
.eval_stmt_block(global, caches, scope, this_ptr, &fn_def.body, rewind_scope)
.eval_stmt_block(
global,
caches,
scope,
this_ptr.as_deref_mut(),
&fn_def.body,
rewind_scope,
)
.or_else(|err| match *err {
// Convert return statement to return value
ERR::Return(x, ..) => Ok(x),

View File

@ -54,7 +54,7 @@ struct OptimizerState<'a> {
/// Has the [`AST`] been changed during this pass?
changed: bool,
/// Collection of constants to use for eager function evaluations.
variables: StaticVec<(Identifier, AccessMode, Dynamic)>,
variables: StaticVec<(Identifier, AccessMode, Option<Dynamic>)>,
/// Activate constants propagation?
propagate_constants: bool,
/// An [`Engine`] instance for eager function evaluation.
@ -115,7 +115,12 @@ impl<'a> OptimizerState<'a> {
}
/// Add a new variable to the list.
#[inline(always)]
pub fn push_var(&mut self, name: impl Into<Identifier>, access: AccessMode, value: Dynamic) {
pub fn push_var(
&mut self,
name: impl Into<Identifier>,
access: AccessMode,
value: Option<Dynamic>,
) {
self.variables.push((name.into(), access, value));
}
/// Look up a constant from the list.
@ -129,8 +134,7 @@ impl<'a> OptimizerState<'a> {
if n == name {
return match access {
AccessMode::ReadWrite => None,
AccessMode::ReadOnly if value.is_null() => None,
AccessMode::ReadOnly => Some(value),
AccessMode::ReadOnly => value.as_ref(),
};
}
}
@ -144,7 +148,7 @@ impl<'a> OptimizerState<'a> {
fn_name: &str,
op_token: Token,
arg_values: &mut [Dynamic],
) -> Dynamic {
) -> Option<Dynamic> {
self.engine
.exec_native_fn_call(
&mut self.global,
@ -156,7 +160,8 @@ impl<'a> OptimizerState<'a> {
false,
Position::NONE,
)
.map_or(Dynamic::NULL, |(v, ..)| v)
.ok()
.map(|(v, ..)| v)
}
}
@ -234,13 +239,13 @@ fn optimize_stmt_block(
state.push_var(
x.0.as_str(),
AccessMode::ReadOnly,
x.1.get_literal_value().unwrap_or(Dynamic::NULL),
x.1.get_literal_value(),
);
}
} else {
// Add variables into the state
optimize_expr(&mut x.1, state, false);
state.push_var(x.0.as_str(), AccessMode::ReadWrite, Dynamic::NULL);
state.push_var(x.0.as_str(), AccessMode::ReadWrite, None);
}
}
// Optimize the statement
@ -1190,15 +1195,15 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
let arg_values = &mut x.args.iter().map(Expr::get_literal_value).collect::<Option<StaticVec<_>>>().unwrap();
let result = match x.name.as_str() {
KEYWORD_TYPE_OF if arg_values.len() == 1 => state.engine.map_type_name(arg_values[0].type_name()).into(),
KEYWORD_TYPE_OF if arg_values.len() == 1 => Some(state.engine.map_type_name(arg_values[0].type_name()).into()),
#[cfg(not(feature = "no_closure"))]
crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Dynamic::FALSE,
crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Some(Dynamic::FALSE),
_ => state.call_fn_with_constant_arguments(&x.name, x.op_token.clone(), arg_values)
};
if !result.is_null() {
if let Some(r) = result {
state.set_dirty();
*expr = Expr::from_dynamic(result, *pos);
*expr = Expr::from_dynamic(r, *pos);
return;
}
}
@ -1303,15 +1308,15 @@ impl Engine {
// Add constants from global modules
for (name, value) in self.global_modules.iter().rev().flat_map(|m| m.iter_var()) {
state.push_var(name, AccessMode::ReadOnly, value.clone());
state.push_var(name, AccessMode::ReadOnly, Some(value.clone()));
}
// Add constants and variables from the scope
for (name, constant, value) in scope.iter() {
if constant {
state.push_var(name, AccessMode::ReadOnly, value);
state.push_var(name, AccessMode::ReadOnly, Some(value));
} else {
state.push_var(name, AccessMode::ReadWrite, Dynamic::NULL);
state.push_var(name, AccessMode::ReadWrite, None);
}
}

View File

@ -2890,8 +2890,7 @@ impl Engine {
will_shadow,
};
let caches = &mut Caches::new();
let mut this_ptr = Dynamic::NULL;
let context = EvalContext::new(self, global, caches, stack, &mut this_ptr);
let context = EvalContext::new(self, global, caches, stack, None);
match filter(false, info, context) {
Ok(true) => (),

View File

@ -125,8 +125,6 @@ impl<'de> Deserializer<'de> for DynamicDeserializer<'de> {
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> RhaiResultOf<V::Value> {
match self.0 .0 {
Union::Null => unreachable!(),
Union::Unit(..) => self.deserialize_unit(visitor),
Union::Bool(..) => self.deserialize_bool(visitor),
Union::Str(..) => self.deserialize_str(visitor),

View File

@ -15,8 +15,6 @@ use crate::types::dynamic::Variant;
impl Serialize for Dynamic {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => ser.serialize_unit(),
Union::Bool(x, ..) => ser.serialize_bool(x),
Union::Str(ref s, ..) => ser.serialize_str(s.as_str()),

View File

@ -57,9 +57,6 @@ pub struct Dynamic(pub(crate) Union);
/// Most variants are boxed to reduce the size.
#[must_use]
pub enum Union {
/// An error value which should not exist.
Null,
/// The Unit value - ().
Unit((), Tag, AccessMode),
/// A boolean value.
@ -187,8 +184,6 @@ impl Dynamic {
#[must_use]
pub const fn tag(&self) -> Tag {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(_, tag, _)
| Union::Bool(_, tag, _)
| Union::Str(_, tag, _)
@ -214,8 +209,6 @@ impl Dynamic {
/// Attach arbitrary data to this [`Dynamic`].
pub fn set_tag(&mut self, value: Tag) -> &mut Self {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(_, ref mut tag, _)
| Union::Bool(_, ref mut tag, _)
| Union::Str(_, ref mut tag, _)
@ -239,12 +232,6 @@ impl Dynamic {
}
self
}
/// Is this [`Dynamic`] null?
#[inline(always)]
#[must_use]
pub(crate) const fn is_null(&self) -> bool {
matches!(self.0, Union::Null)
}
/// Does this [`Dynamic`] hold a variant data type instead of one of the supported system
/// primitive types?
#[inline(always)]
@ -334,8 +321,6 @@ impl Dynamic {
#[must_use]
pub fn type_id(&self) -> TypeId {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => TypeId::of::<()>(),
Union::Bool(..) => TypeId::of::<bool>(),
Union::Str(..) => TypeId::of::<ImmutableString>(),
@ -370,8 +355,6 @@ impl Dynamic {
#[must_use]
pub fn type_name(&self) -> &'static str {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => "()",
Union::Bool(..) => "bool",
Union::Str(..) => "string",
@ -416,8 +399,6 @@ impl Hash for Dynamic {
mem::discriminant(&self.0).hash(state);
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => (),
Union::Bool(ref b, ..) => b.hash(state),
Union::Str(ref s, ..) => s.hash(state),
@ -449,8 +430,6 @@ impl Hash for Dynamic {
impl fmt::Display for Dynamic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => Ok(()),
Union::Bool(ref v, ..) => fmt::Display::fmt(v, f),
Union::Str(ref v, ..) => fmt::Display::fmt(v, f),
@ -544,8 +523,6 @@ impl fmt::Debug for Dynamic {
#[inline(never)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(ref v, ..) => fmt::Debug::fmt(v, f),
Union::Bool(ref v, ..) => fmt::Debug::fmt(v, f),
Union::Str(ref v, ..) => fmt::Debug::fmt(v, f),
@ -657,8 +634,6 @@ impl Clone for Dynamic {
/// The cloned copy is marked read-write even if the original is read-only.
fn clone(&self) -> Self {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(v, tag, ..) => Self(Union::Unit(v, tag, ReadWrite)),
Union::Bool(v, tag, ..) => Self(Union::Bool(v, tag, ReadWrite)),
Union::Str(ref v, tag, ..) => Self(Union::Str(v.clone(), tag, ReadWrite)),
@ -705,9 +680,6 @@ use std::f32::consts as FloatConstants;
use std::f64::consts as FloatConstants;
impl Dynamic {
/// A [`Dynamic`] containing a `null`.
pub(crate) const NULL: Self = Self(Union::Null);
/// A [`Dynamic`] containing a `()`.
pub const UNIT: Self = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite));
/// A [`Dynamic`] containing a `true`.
@ -921,8 +893,6 @@ impl Dynamic {
#[must_use]
pub(crate) const fn access_mode(&self) -> AccessMode {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(.., access)
| Union::Bool(.., access)
| Union::Str(.., access)
@ -948,8 +918,6 @@ impl Dynamic {
/// Set the [`AccessMode`] for this [`Dynamic`].
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(.., ref mut access)
| Union::Bool(.., ref mut access)
| Union::Str(.., ref mut access)
@ -1138,7 +1106,6 @@ impl Dynamic {
let _access = self.access_mode();
match self.0 {
Union::Null => unreachable!(),
Union::Shared(..) => self,
_ => Self(Union::Shared(
crate::Locked::new(self).into(),
@ -1584,7 +1551,6 @@ impl Dynamic {
}
match self.0 {
Union::Null => unreachable!(),
Union::Variant(ref v, ..) => (***v).as_any().downcast_ref::<T>(),
#[cfg(not(feature = "no_closure"))]
Union::Shared(..) => None,
@ -1683,7 +1649,6 @@ impl Dynamic {
}
match self.0 {
Union::Null => unreachable!(),
Union::Variant(ref mut v, ..) => (***v).as_any_mut().downcast_mut::<T>(),
#[cfg(not(feature = "no_closure"))]
Union::Shared(..) => None,

View File

@ -298,19 +298,19 @@ impl FnPtr {
// Linked to scripted function?
#[cfg(not(feature = "no_function"))]
if let Some(fn_def) = self.fn_def() {
if let Some(ref fn_def) = self.fn_def {
if fn_def.params.len() == args.len() {
let global = &mut context.global_runtime_state().clone();
global.level += 1;
let caches = &mut crate::eval::Caches::new();
let mut null_ptr = Dynamic::NULL;
let mut this_ptr = this_ptr;
return context.engine().call_script_fn(
global,
caches,
&mut crate::Scope::new(),
this_ptr.unwrap_or(&mut null_ptr),
this_ptr.as_deref_mut(),
self.encapsulated_environ(),
&fn_def,
args,
@ -348,8 +348,8 @@ impl FnPtr {
#[cfg(not(feature = "no_function"))]
#[inline(always)]
#[must_use]
pub(crate) fn fn_def(&self) -> Option<&Shared<crate::ast::ScriptFnDef>> {
self.fn_def.as_ref()
pub(crate) fn fn_def(&self) -> Option<&crate::ast::ScriptFnDef> {
self.fn_def.as_deref()
}
/// Set a reference to the linked [`ScriptFnDef`][crate::ast::ScriptFnDef].
#[cfg(not(feature = "no_function"))]
@ -410,12 +410,11 @@ impl FnPtr {
extras: [Dynamic; E],
) -> RhaiResult {
#[cfg(not(feature = "no_function"))]
{
let arity = self.fn_def().map(|f| f.params.len()).unwrap_or(0);
if let Some(arity) = self.fn_def().map(|f| f.params.len()) {
if arity == N {
return self.call_raw(&ctx, None, items);
} else if arity == N + E {
}
if arity == N + E {
let mut items2 = FnArgsVec::with_capacity(items.len() + extras.len());
items2.extend(IntoIterator::into_iter(items));
items2.extend(IntoIterator::into_iter(extras));