Add Dynamic::NULL to simplify this pointer binding.
This commit is contained in:
parent
6053aa1641
commit
8f128f37f0
@ -250,7 +250,9 @@ impl Engine {
|
||||
) -> RhaiResult {
|
||||
let statements = ast.statements();
|
||||
let lib = &[AsRef::<SharedModule>::as_ref(ast).clone()];
|
||||
let mut this_ptr = this_ptr;
|
||||
|
||||
let mut no_this_ptr = Dynamic::NULL;
|
||||
let mut this_ptr = this_ptr.unwrap_or(&mut no_this_ptr);
|
||||
|
||||
let orig_scope_len = scope.len();
|
||||
|
||||
|
@ -198,8 +198,10 @@ impl Engine {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
AsRef::<crate::SharedModule>::as_ref(ast).clone(),
|
||||
];
|
||||
let mut this = Dynamic::NULL;
|
||||
let node = &crate::ast::Stmt::Noop(Position::NONE);
|
||||
self.run_debugger(global, caches, lib, 0, scope, &mut None, node)?;
|
||||
|
||||
self.run_debugger(global, caches, lib, 0, scope, &mut this, node)?;
|
||||
}
|
||||
|
||||
let typ = self.map_type_name(result.type_name());
|
||||
|
@ -141,8 +141,9 @@ impl Engine {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
AsRef::<crate::SharedModule>::as_ref(ast).clone(),
|
||||
];
|
||||
let mut this = crate::Dynamic::NULL;
|
||||
let node = &crate::ast::Stmt::Noop(crate::Position::NONE);
|
||||
self.run_debugger(global, caches, lib, 0, scope, &mut None, node)?;
|
||||
self.run_debugger(global, caches, lib, 0, scope, &mut this, node)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -45,7 +45,7 @@ impl Engine {
|
||||
caches: &mut Caches,
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
target: &mut Target,
|
||||
root: (&str, Position),
|
||||
_parent: &Expr,
|
||||
@ -573,7 +573,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
expr: &Expr,
|
||||
new_val: &mut Option<(Dynamic, &OpAssignment)>,
|
||||
) -> RhaiResult {
|
||||
@ -630,9 +630,10 @@ impl Engine {
|
||||
|
||||
let obj_ptr = &mut target;
|
||||
let root = (x.3.as_str(), *var_pos);
|
||||
let mut this = Dynamic::NULL;
|
||||
|
||||
self.eval_dot_index_chain_helper(
|
||||
global, caches, lib, level, &mut None, obj_ptr, root, expr, options, rhs,
|
||||
global, caches, lib, level, &mut this, obj_ptr, root, expr, options, rhs,
|
||||
idx_values, chain_type, new_val,
|
||||
)
|
||||
}
|
||||
@ -664,7 +665,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
expr: &Expr,
|
||||
parent_options: ASTFlags,
|
||||
parent_chain_type: ChainType,
|
||||
|
@ -416,7 +416,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
node: impl Into<ASTNode<'a>>,
|
||||
) -> RhaiResultOf<()> {
|
||||
if self.debugger.is_some() {
|
||||
@ -443,7 +443,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
node: impl Into<ASTNode<'a>>,
|
||||
) -> RhaiResultOf<Option<DebuggerStatus>> {
|
||||
if self.debugger.is_some() {
|
||||
@ -466,7 +466,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
node: impl Into<ASTNode<'a>>,
|
||||
) -> RhaiResultOf<Option<DebuggerStatus>> {
|
||||
let node = node.into();
|
||||
@ -513,7 +513,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
node: ASTNode<'a>,
|
||||
event: DebuggerEvent,
|
||||
) -> Result<Option<DebuggerStatus>, Box<crate::EvalAltResult>> {
|
||||
|
@ -8,7 +8,7 @@ use std::prelude::v1::*;
|
||||
/// Context of a script evaluation process.
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
||||
pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
|
||||
/// The current [`Engine`].
|
||||
engine: &'a Engine,
|
||||
/// The current [`Scope`].
|
||||
@ -20,12 +20,12 @@ pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
||||
/// The current stack of imported [modules][Module].
|
||||
lib: &'a [SharedModule],
|
||||
/// The current bound `this` pointer, if any.
|
||||
this_ptr: &'t mut Option<&'pt mut Dynamic>,
|
||||
this_ptr: &'t mut Dynamic,
|
||||
/// The current nesting level of function calls.
|
||||
level: usize,
|
||||
}
|
||||
|
||||
impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
||||
impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
|
||||
/// Create a new [`EvalContext`].
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
@ -36,7 +36,7 @@ impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
||||
lib: &'a [SharedModule],
|
||||
level: usize,
|
||||
scope: &'s mut Scope<'ps>,
|
||||
this_ptr: &'t mut Option<&'pt mut Dynamic>,
|
||||
this_ptr: &'t mut Dynamic,
|
||||
) -> Self {
|
||||
Self {
|
||||
engine,
|
||||
@ -104,8 +104,8 @@ impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
||||
#[cfg(feature = "internals")]
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn global_runtime_state_mut(&mut self) -> &mut &'g mut GlobalRuntimeState {
|
||||
&mut self.global
|
||||
pub fn global_runtime_state_mut(&mut self) -> &mut GlobalRuntimeState {
|
||||
self.global
|
||||
}
|
||||
/// Get an iterator over the namespaces containing definition of all script-defined functions.
|
||||
#[inline]
|
||||
@ -121,16 +121,24 @@ impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
||||
self.lib
|
||||
}
|
||||
/// The current bound `this` pointer, if any.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn this_ptr(&self) -> Option<&Dynamic> {
|
||||
self.this_ptr.as_ref().map(|v| &**v)
|
||||
if self.this_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(self.this_ptr)
|
||||
}
|
||||
}
|
||||
/// Mutable reference to the current bound `this` pointer, if any.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn this_ptr_mut(&mut self) -> &mut Option<&'pt mut Dynamic> {
|
||||
self.this_ptr
|
||||
pub fn this_ptr_mut(&mut self) -> Option<&mut Dynamic> {
|
||||
if self.this_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(self.this_ptr)
|
||||
}
|
||||
}
|
||||
/// The current nesting level of function calls.
|
||||
#[inline(always)]
|
||||
|
@ -54,7 +54,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &'s mut Scope,
|
||||
this_ptr: &'s mut Option<&mut Dynamic>,
|
||||
this_ptr: &'s mut Dynamic,
|
||||
expr: &Expr,
|
||||
) -> RhaiResultOf<(Target<'s>, Position)> {
|
||||
match expr {
|
||||
@ -140,7 +140,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &'s mut Scope,
|
||||
this_ptr: &'s mut Option<&mut Dynamic>,
|
||||
this_ptr: &'s mut Dynamic,
|
||||
expr: &Expr,
|
||||
) -> RhaiResultOf<(Target<'s>, Position)> {
|
||||
// Make sure that the pointer indirection is taken only when absolutely necessary.
|
||||
@ -148,10 +148,11 @@ impl Engine {
|
||||
let (index, var_pos) = match expr {
|
||||
// Check if the variable is `this`
|
||||
Expr::Variable(v, None, pos) if v.0.is_none() && v.3 == KEYWORD_THIS => {
|
||||
return this_ptr.as_mut().map_or_else(
|
||||
|| Err(ERR::ErrorUnboundThis(*pos).into()),
|
||||
|val| Ok(((*val).into(), *pos)),
|
||||
)
|
||||
return if this_ptr.is_null() {
|
||||
Err(ERR::ErrorUnboundThis(*pos).into())
|
||||
} else {
|
||||
Ok((this_ptr.into(), *pos))
|
||||
};
|
||||
}
|
||||
_ if global.always_search_scope => (0, expr.start_position()),
|
||||
Expr::Variable(.., Some(i), pos) => (i.get() as usize, *pos),
|
||||
@ -224,7 +225,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
expr: &Expr,
|
||||
) -> RhaiResult {
|
||||
// Coded this way for better branch prediction.
|
||||
@ -256,10 +257,11 @@ impl Engine {
|
||||
self.track_operation(global, expr.position())?;
|
||||
|
||||
return if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS {
|
||||
this_ptr
|
||||
.as_deref()
|
||||
.cloned()
|
||||
.ok_or_else(|| ERR::ErrorUnboundThis(*var_pos).into())
|
||||
if this_ptr.is_null() {
|
||||
ERR::ErrorUnboundThis(*var_pos).into()
|
||||
} else {
|
||||
Ok(this_ptr.clone())
|
||||
}
|
||||
} else {
|
||||
self.search_namespace(global, caches, lib, level, scope, this_ptr, expr)
|
||||
.map(|(val, ..)| val.take_or_clone())
|
||||
|
@ -29,7 +29,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
statements: &[Stmt],
|
||||
restore_orig_state: bool,
|
||||
) -> RhaiResult {
|
||||
@ -203,7 +203,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
stmt: &Stmt,
|
||||
rewind_scope: bool,
|
||||
) -> RhaiResult {
|
||||
@ -912,8 +912,10 @@ impl Engine {
|
||||
scope: &mut Scope,
|
||||
statements: &[Stmt],
|
||||
) -> RhaiResult {
|
||||
let mut this = Dynamic::NULL;
|
||||
|
||||
self.eval_stmt_block(
|
||||
global, caches, lib, level, scope, &mut None, statements, false,
|
||||
global, caches, lib, level, scope, &mut this, statements, false,
|
||||
)
|
||||
.or_else(|err| match *err {
|
||||
ERR::Return(out, ..) => Ok(out),
|
||||
|
@ -11,8 +11,8 @@ use crate::eval::{Caches, FnResolutionCacheEntry, GlobalRuntimeState};
|
||||
use crate::tokenizer::{is_valid_function_name, Token};
|
||||
use crate::types::RestoreOnDrop;
|
||||
use crate::{
|
||||
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString, SharedModule,
|
||||
OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, ERR,
|
||||
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString,
|
||||
OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, SharedModule, ERR,
|
||||
};
|
||||
#[cfg(feature = "no_std")]
|
||||
use hashbrown::hash_map::Entry;
|
||||
@ -407,6 +407,7 @@ impl Engine {
|
||||
};
|
||||
if trigger {
|
||||
let scope = &mut &mut Scope::new();
|
||||
let mut this = Dynamic::NULL;
|
||||
let node = crate::ast::Stmt::Noop(pos);
|
||||
let node = (&node).into();
|
||||
let event = match _result {
|
||||
@ -415,7 +416,7 @@ impl Engine {
|
||||
};
|
||||
|
||||
if let Err(err) = self
|
||||
.run_debugger_raw(global, caches, lib, level, scope, &mut None, node, event)
|
||||
.run_debugger_raw(global, caches, lib, level, scope, &mut this, node, event)
|
||||
{
|
||||
_result = Err(err);
|
||||
}
|
||||
@ -646,16 +647,7 @@ impl Engine {
|
||||
let (first_arg, rest_args) = args.split_first_mut().unwrap();
|
||||
|
||||
self.call_script_fn(
|
||||
global,
|
||||
caches,
|
||||
lib,
|
||||
level,
|
||||
scope,
|
||||
&mut Some(*first_arg),
|
||||
func,
|
||||
rest_args,
|
||||
true,
|
||||
pos,
|
||||
global, caches, lib, level, scope, first_arg, func, rest_args, true, pos,
|
||||
)
|
||||
} else {
|
||||
// Normal call of script function
|
||||
@ -672,8 +664,10 @@ impl Engine {
|
||||
backup.restore_first_arg(a)
|
||||
});
|
||||
|
||||
let mut this = Dynamic::NULL;
|
||||
|
||||
self.call_script_fn(
|
||||
global, caches, lib, level, scope, &mut None, func, args, true, pos,
|
||||
global, caches, lib, level, scope, &mut this, func, args, true, pos,
|
||||
)
|
||||
}
|
||||
.map(|r| (r, false));
|
||||
@ -697,7 +691,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
arg_expr: &Expr,
|
||||
) -> RhaiResultOf<(Dynamic, Position)> {
|
||||
// Literal values
|
||||
@ -956,7 +950,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
fn_name: &str,
|
||||
op_token: Option<&Token>,
|
||||
first_arg: Option<&Expr>,
|
||||
@ -1247,7 +1241,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
namespace: &crate::ast::Namespace,
|
||||
fn_name: &str,
|
||||
args_expr: &[Expr],
|
||||
@ -1376,12 +1370,13 @@ impl Engine {
|
||||
Some(f) if f.is_script() => {
|
||||
let fn_def = f.get_script_fn_def().expect("script-defined function");
|
||||
let new_scope = &mut Scope::new();
|
||||
let mut this = Dynamic::NULL;
|
||||
|
||||
let orig_source = mem::replace(&mut global.source, module.id_raw().cloned());
|
||||
let global = &mut *RestoreOnDrop::lock(global, move |g| g.source = orig_source);
|
||||
|
||||
self.call_script_fn(
|
||||
global, caches, lib, level, new_scope, &mut None, fn_def, &mut args, true, pos,
|
||||
global, caches, lib, level, new_scope, &mut this, fn_def, &mut args, true, pos,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1474,7 +1469,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
expr: &FnCallExpr,
|
||||
pos: Position,
|
||||
) -> RhaiResult {
|
||||
|
@ -29,7 +29,7 @@ impl Engine {
|
||||
lib: &[SharedModule],
|
||||
level: usize,
|
||||
scope: &mut Scope,
|
||||
this_ptr: &mut Option<&mut Dynamic>,
|
||||
this_ptr: &mut Dynamic,
|
||||
fn_def: &ScriptFnDef,
|
||||
args: &mut FnCallArgs,
|
||||
rewind_scope: bool,
|
||||
|
@ -50,7 +50,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, Option<Dynamic>)>,
|
||||
variables: StaticVec<(Identifier, AccessMode, Dynamic)>,
|
||||
/// Activate constants propagation?
|
||||
propagate_constants: bool,
|
||||
/// An [`Engine`] instance for eager function evaluation.
|
||||
@ -108,12 +108,7 @@ 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: Option<Dynamic>,
|
||||
) {
|
||||
pub fn push_var(&mut self, name: impl Into<Identifier>, access: AccessMode, value: Dynamic) {
|
||||
self.variables.push((name.into(), access, value));
|
||||
}
|
||||
/// Look up a constant from the list.
|
||||
@ -127,7 +122,8 @@ impl<'a> OptimizerState<'a> {
|
||||
if n == name {
|
||||
return match access {
|
||||
AccessMode::ReadWrite => None,
|
||||
AccessMode::ReadOnly => value.as_ref(),
|
||||
AccessMode::ReadOnly if value.is_null() => None,
|
||||
AccessMode::ReadOnly => Some(value),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -141,7 +137,7 @@ impl<'a> OptimizerState<'a> {
|
||||
fn_name: &str,
|
||||
op_token: Option<&Token>,
|
||||
arg_values: &mut [Dynamic],
|
||||
) -> Option<Dynamic> {
|
||||
) -> Dynamic {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
let lib = self.lib;
|
||||
#[cfg(feature = "no_function")]
|
||||
@ -160,8 +156,7 @@ impl<'a> OptimizerState<'a> {
|
||||
false,
|
||||
Position::NONE,
|
||||
)
|
||||
.ok()
|
||||
.map(|(v, ..)| v)
|
||||
.map_or(Dynamic::NULL, |(v, ..)| v)
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,13 +266,13 @@ fn optimize_stmt_block(
|
||||
state.push_var(
|
||||
x.0.as_str(),
|
||||
AccessMode::ReadOnly,
|
||||
x.1.get_literal_value(),
|
||||
x.1.get_literal_value().unwrap_or(Dynamic::NULL),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Add variables into the state
|
||||
optimize_expr(&mut x.1, state, false);
|
||||
state.push_var(x.0.as_str(), AccessMode::ReadWrite, None);
|
||||
state.push_var(x.0.as_str(), AccessMode::ReadWrite, Dynamic::NULL);
|
||||
}
|
||||
}
|
||||
// Optimize the statement
|
||||
@ -1197,13 +1192,13 @@ 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 => Some(state.engine.map_type_name(arg_values[0].type_name()).into()),
|
||||
KEYWORD_TYPE_OF if arg_values.len() == 1 => 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 => Some(Dynamic::FALSE),
|
||||
crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Dynamic::FALSE,
|
||||
_ => state.call_fn_with_constant_arguments(&x.name, x.op_token.as_ref(), arg_values)
|
||||
};
|
||||
|
||||
if let Some(result) = result {
|
||||
if !result.is_null() {
|
||||
state.set_dirty();
|
||||
*expr = Expr::from_dynamic(result, *pos);
|
||||
return;
|
||||
@ -1289,15 +1284,15 @@ fn optimize_top_level(
|
||||
.rev()
|
||||
.flat_map(|m| m.iter_var())
|
||||
{
|
||||
state.push_var(name, AccessMode::ReadOnly, Some(value.clone()));
|
||||
state.push_var(name, AccessMode::ReadOnly, value.clone());
|
||||
}
|
||||
|
||||
// Add constants and variables from the scope
|
||||
for (name, constant, value) in scope.iter() {
|
||||
if constant {
|
||||
state.push_var(name, AccessMode::ReadOnly, Some(value));
|
||||
state.push_var(name, AccessMode::ReadOnly, value);
|
||||
} else {
|
||||
state.push_var(name, AccessMode::ReadWrite, None);
|
||||
state.push_var(name, AccessMode::ReadWrite, Dynamic::NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2907,7 +2907,7 @@ impl Engine {
|
||||
will_shadow,
|
||||
};
|
||||
let caches = &mut Caches::new();
|
||||
let this_ptr = &mut None;
|
||||
let mut this = Dynamic::NULL;
|
||||
|
||||
let context = EvalContext::new(
|
||||
self,
|
||||
@ -2916,7 +2916,7 @@ impl Engine {
|
||||
&[],
|
||||
level,
|
||||
&mut state.stack,
|
||||
this_ptr,
|
||||
&mut this,
|
||||
);
|
||||
|
||||
match filter(false, info, context) {
|
||||
|
@ -125,6 +125,8 @@ 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,6 +15,8 @@ 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()),
|
||||
|
@ -55,6 +55,9 @@ pub struct Dynamic(pub(crate) Union);
|
||||
///
|
||||
/// Most variants are boxed to reduce the size.
|
||||
pub enum Union {
|
||||
/// An error value which should not exist.
|
||||
Null,
|
||||
|
||||
/// The Unit value - ().
|
||||
Unit((), Tag, AccessMode),
|
||||
/// A boolean value.
|
||||
@ -178,6 +181,8 @@ 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, _)
|
||||
@ -203,6 +208,8 @@ 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, _)
|
||||
@ -226,6 +233,12 @@ 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)]
|
||||
@ -307,6 +320,8 @@ 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>(),
|
||||
@ -341,6 +356,8 @@ 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",
|
||||
@ -385,6 +402,8 @@ 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),
|
||||
@ -416,6 +435,8 @@ 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),
|
||||
@ -509,6 +530,8 @@ 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),
|
||||
@ -619,6 +642,8 @@ 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)),
|
||||
@ -666,6 +691,9 @@ 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`.
|
||||
@ -888,6 +916,8 @@ 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)
|
||||
@ -913,6 +943,8 @@ 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)
|
||||
@ -1107,6 +1139,7 @@ impl Dynamic {
|
||||
let _access = self.access_mode();
|
||||
|
||||
match self.0 {
|
||||
Union::Null => unreachable!(),
|
||||
Union::Shared(..) => self,
|
||||
_ => Self(Union::Shared(
|
||||
crate::Locked::new(self).into(),
|
||||
@ -1151,6 +1184,8 @@ impl Dynamic {
|
||||
reify!(self, |v: T| return Some(v));
|
||||
|
||||
match self.0 {
|
||||
Union::Null => unreachable!(),
|
||||
|
||||
Union::Int(v, ..) => reify!(v => Option<T>),
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Union::Float(v, ..) => reify!(*v => Option<T>),
|
||||
@ -1485,6 +1520,7 @@ 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,
|
||||
@ -1583,6 +1619,7 @@ 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,
|
||||
|
0
unreachable!()
Normal file
0
unreachable!()
Normal file
Loading…
Reference in New Issue
Block a user