Remove Dynamic::NULL, use .as_deref_mut() for this_ptr.
This commit is contained in:
parent
99080be91d
commit
babc0b5466
@ -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"))]
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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(())
|
||||
})
|
||||
|
@ -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));
|
||||
|
@ -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>> {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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(..) => {
|
||||
|
111
src/func/call.rs
111
src/func/call.rs
@ -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();
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) => (),
|
||||
|
@ -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),
|
||||
|
@ -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()),
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user