Simplify Dynamic::as_XXX calls.
This commit is contained in:
parent
ce046422f0
commit
a1d42b826a
@ -16,6 +16,7 @@ Bug fixes
|
|||||||
* `import` statements inside `eval` no longer cause errors in subsequent code.
|
* `import` statements inside `eval` no longer cause errors in subsequent code.
|
||||||
* Functions marked `global` in `import`ed modules with no alias names now work properly.
|
* Functions marked `global` in `import`ed modules with no alias names now work properly.
|
||||||
* Incorrect loop optimizations that are too aggressive (e.g. unrolling a `do { ... } until true` with a `break` statement inside) and cause crashes are removed.
|
* Incorrect loop optimizations that are too aggressive (e.g. unrolling a `do { ... } until true` with a `break` statement inside) and cause crashes are removed.
|
||||||
|
* `Dynamic::is` now works properly for shared values.
|
||||||
|
|
||||||
Breaking changes
|
Breaking changes
|
||||||
----------------
|
----------------
|
||||||
|
@ -52,7 +52,6 @@ impl Engine {
|
|||||||
global: &mut GlobalRuntimeState,
|
global: &mut GlobalRuntimeState,
|
||||||
caches: &mut Caches,
|
caches: &mut Caches,
|
||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
|
|
||||||
scope: &'s mut Scope,
|
scope: &'s mut Scope,
|
||||||
this_ptr: &'s mut Dynamic,
|
this_ptr: &'s mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
@ -136,7 +135,6 @@ impl Engine {
|
|||||||
global: &mut GlobalRuntimeState,
|
global: &mut GlobalRuntimeState,
|
||||||
caches: &mut Caches,
|
caches: &mut Caches,
|
||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
|
|
||||||
scope: &'s mut Scope,
|
scope: &'s mut Scope,
|
||||||
this_ptr: &'s mut Dynamic,
|
this_ptr: &'s mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
@ -221,7 +219,6 @@ impl Engine {
|
|||||||
global: &mut GlobalRuntimeState,
|
global: &mut GlobalRuntimeState,
|
||||||
caches: &mut Caches,
|
caches: &mut Caches,
|
||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
|
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Dynamic,
|
this_ptr: &mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
|
@ -6,7 +6,7 @@ use crate::ast::{
|
|||||||
ASTFlags, BinaryExpr, Expr, Ident, OpAssignment, Stmt, SwitchCasesCollection, TryCatchBlock,
|
ASTFlags, BinaryExpr, Expr, Ident, OpAssignment, Stmt, SwitchCasesCollection, TryCatchBlock,
|
||||||
};
|
};
|
||||||
use crate::func::{get_builtin_op_assignment_fn, get_hasher};
|
use crate::func::{get_builtin_op_assignment_fn, get_hasher};
|
||||||
use crate::types::dynamic::{AccessMode, Union};
|
use crate::types::dynamic::AccessMode;
|
||||||
use crate::types::RestoreOnDrop;
|
use crate::types::RestoreOnDrop;
|
||||||
use crate::{
|
use crate::{
|
||||||
Dynamic, Engine, ImmutableString, Position, RhaiResult, RhaiResultOf, Scope, SharedModule, ERR,
|
Dynamic, Engine, ImmutableString, Position, RhaiResult, RhaiResultOf, Scope, SharedModule, ERR,
|
||||||
@ -687,7 +687,7 @@ impl Engine {
|
|||||||
.map(|_| Dynamic::UNIT)
|
.map(|_| Dynamic::UNIT)
|
||||||
.map_err(|result_err| match *result_err {
|
.map_err(|result_err| match *result_err {
|
||||||
// Re-throw exception
|
// Re-throw exception
|
||||||
ERR::ErrorRuntime(Dynamic(Union::Unit(..)), pos) => {
|
ERR::ErrorRuntime(v, pos) if v.is_unit() => {
|
||||||
err.set_position(pos);
|
err.set_position(pos);
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
@ -690,7 +690,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
|||||||
PlusAssign => Some(|_ctx, args| {
|
PlusAssign => Some(|_ctx, args| {
|
||||||
let (first, second) = args.split_first_mut().expect(BUILTIN);
|
let (first, second) = args.split_first_mut().expect(BUILTIN);
|
||||||
let x = &mut *first.write_lock::<ImmutableString>().expect(BUILTIN);
|
let x = &mut *first.write_lock::<ImmutableString>().expect(BUILTIN);
|
||||||
let y = std::mem::take(second[0]).cast::<ImmutableString>();
|
let y = &*second[0].read_lock::<ImmutableString>().expect(BUILTIN);
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if !x.is_empty() && !y.is_empty() {
|
if !x.is_empty() && !y.is_empty() {
|
||||||
@ -704,7 +704,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
|||||||
MinusAssign => Some(|_, args| {
|
MinusAssign => Some(|_, args| {
|
||||||
let (first, second) = args.split_first_mut().expect(BUILTIN);
|
let (first, second) = args.split_first_mut().expect(BUILTIN);
|
||||||
let x = &mut *first.write_lock::<ImmutableString>().expect(BUILTIN);
|
let x = &mut *first.write_lock::<ImmutableString>().expect(BUILTIN);
|
||||||
let y = std::mem::take(second[0]).cast::<ImmutableString>();
|
let y = &*second[0].read_lock::<ImmutableString>().expect(BUILTIN);
|
||||||
Ok((*x -= y).into())
|
Ok((*x -= y).into())
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -718,7 +718,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
|||||||
|
|
||||||
return match op {
|
return match op {
|
||||||
PlusAssign => Some(|_ctx, args| {
|
PlusAssign => Some(|_ctx, args| {
|
||||||
let x = std::mem::take(args[1]).cast::<Array>();
|
let x = std::mem::take(args[1]).into_array().expect(BUILTIN);
|
||||||
|
|
||||||
if x.is_empty() {
|
if x.is_empty() {
|
||||||
return Ok(Dynamic::UNIT);
|
return Ok(Dynamic::UNIT);
|
||||||
@ -749,7 +749,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
|||||||
|
|
||||||
return match op {
|
return match op {
|
||||||
PlusAssign => Some(|_ctx, args| {
|
PlusAssign => Some(|_ctx, args| {
|
||||||
let blob2 = std::mem::take(args[1]).cast::<Blob>();
|
let blob2 = std::mem::take(args[1]).into_blob().expect(BUILTIN);
|
||||||
let blob1 = &mut *args[0].write_lock::<Blob>().expect(BUILTIN);
|
let blob1 = &mut *args[0].write_lock::<Blob>().expect(BUILTIN);
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
@ -951,14 +951,14 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
|||||||
|
|
||||||
return match op {
|
return match op {
|
||||||
PlusAssign => Some(|_ctx, args| {
|
PlusAssign => Some(|_ctx, args| {
|
||||||
let s = std::mem::take(args[1]).cast::<ImmutableString>();
|
let (first, second) = args.split_first_mut().expect(BUILTIN);
|
||||||
|
let blob = &mut *first.write_lock::<Blob>().expect(BUILTIN);
|
||||||
|
let s = &*second[0].read_lock::<ImmutableString>().expect(BUILTIN);
|
||||||
|
|
||||||
if s.is_empty() {
|
if s.is_empty() {
|
||||||
return Ok(Dynamic::UNIT);
|
return Ok(Dynamic::UNIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
let blob = &mut *args[0].write_lock::<Blob>().expect(BUILTIN);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
_ctx.engine().raise_err_if_over_data_size_limit((
|
_ctx.engine().raise_err_if_over_data_size_limit((
|
||||||
blob.len() + s.len(),
|
blob.len() + s.len(),
|
||||||
@ -966,7 +966,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
|||||||
0,
|
0,
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
Ok(append_str(blob, &s).into())
|
Ok(append_str(blob, s).into())
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
@ -260,10 +260,18 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
/// Is the value held by this [`Dynamic`] a particular type?
|
/// Is the value held by this [`Dynamic`] a particular type?
|
||||||
///
|
///
|
||||||
/// If the [`Dynamic`] is a shared variant checking is performed on top of its internal value.
|
/// # Panics or Deadlocks When Value is Shared
|
||||||
|
///
|
||||||
|
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
|
||||||
|
/// Otherwise, this call panics if the data is currently borrowed for write.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is<T: Any + Clone>(&self) -> bool {
|
pub fn is<T: Any + Clone>(&self) -> bool {
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
if self.is_shared() {
|
||||||
|
return TypeId::of::<T>() == self.type_id();
|
||||||
|
}
|
||||||
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<()>() {
|
if TypeId::of::<T>() == TypeId::of::<()>() {
|
||||||
return matches!(self.0, Union::Unit(..));
|
return matches!(self.0, Union::Unit(..));
|
||||||
}
|
}
|
||||||
@ -1819,9 +1827,12 @@ impl Dynamic {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_unit(&self) -> Result<(), &'static str> {
|
pub fn as_unit(&self) -> Result<(), &'static str> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Unit(v, ..) => Ok(v),
|
Union::Unit(..) => Ok(()),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
|
Union::Unit(..) => Ok(()),
|
||||||
|
_ => Err(cell.type_name()),
|
||||||
|
},
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1832,7 +1843,10 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Int(n, ..) => Ok(n),
|
Union::Int(n, ..) => Ok(n),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
|
Union::Int(n, ..) => Ok(n),
|
||||||
|
_ => Err(cell.type_name()),
|
||||||
|
},
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1846,7 +1860,10 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Float(n, ..) => Ok(*n),
|
Union::Float(n, ..) => Ok(*n),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
|
Union::Float(n, ..) => Ok(*n),
|
||||||
|
_ => Err(cell.type_name()),
|
||||||
|
},
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1860,7 +1877,10 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Decimal(ref n, ..) => Ok(**n),
|
Union::Decimal(ref n, ..) => Ok(**n),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
|
Union::Decimal(ref n, ..) => Ok(**n),
|
||||||
|
_ => Err(cell.type_name()),
|
||||||
|
},
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1871,7 +1891,10 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Bool(b, ..) => Ok(b),
|
Union::Bool(b, ..) => Ok(b),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
|
Union::Bool(b, ..) => Ok(b),
|
||||||
|
_ => Err(cell.type_name()),
|
||||||
|
},
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1880,9 +1903,12 @@ impl Dynamic {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_char(&self) -> Result<char, &'static str> {
|
pub fn as_char(&self) -> Result<char, &'static str> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Char(n, ..) => Ok(n),
|
Union::Char(c, ..) => Ok(c),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
|
Union::Char(c, ..) => Ok(c),
|
||||||
|
_ => Err(cell.type_name()),
|
||||||
|
},
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1917,14 +1943,10 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Str(s, ..) => Ok(s),
|
Union::Str(s, ..) => Ok(s),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(ref cell, ..) => {
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
let value = crate::func::locked_read(cell);
|
|
||||||
|
|
||||||
match value.0 {
|
|
||||||
Union::Str(ref s, ..) => Ok(s.clone()),
|
Union::Str(ref s, ..) => Ok(s.clone()),
|
||||||
_ => Err((*value).type_name()),
|
_ => Err(cell.type_name()),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1938,14 +1960,10 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Array(a, ..) => Ok(*a),
|
Union::Array(a, ..) => Ok(*a),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(ref cell, ..) => {
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
let value = crate::func::locked_read(cell);
|
|
||||||
|
|
||||||
match value.0 {
|
|
||||||
Union::Array(ref a, ..) => Ok(a.as_ref().clone()),
|
Union::Array(ref a, ..) => Ok(a.as_ref().clone()),
|
||||||
_ => Err((*value).type_name()),
|
_ => Err(cell.type_name()),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1973,12 +1991,12 @@ impl Dynamic {
|
|||||||
v.try_cast::<T>().ok_or(typ)
|
v.try_cast::<T>().ok_or(typ)
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
Union::Blob(..) if TypeId::of::<T>() == TypeId::of::<u8>() => Ok(self.cast::<Vec<T>>()),
|
Union::Blob(b, ..) if TypeId::of::<T>() == TypeId::of::<u8>() => {
|
||||||
|
Ok(reify!(*b => Vec<T>))
|
||||||
|
}
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(ref cell, ..) => {
|
Union::Shared(ref cell, ..) => {
|
||||||
let value = crate::func::locked_read(cell);
|
match crate::func::locked_read(cell).0 {
|
||||||
|
|
||||||
match value.0 {
|
|
||||||
Union::Array(ref a, ..) => {
|
Union::Array(ref a, ..) => {
|
||||||
a.iter()
|
a.iter()
|
||||||
.map(|v| {
|
.map(|v| {
|
||||||
@ -1996,10 +2014,10 @@ impl Dynamic {
|
|||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
Union::Blob(..) if TypeId::of::<T>() == TypeId::of::<u8>() => {
|
Union::Blob(ref b, ..) if TypeId::of::<T>() == TypeId::of::<u8>() => {
|
||||||
Ok((*value).clone().cast::<Vec<T>>())
|
Ok(reify!(b.clone() => Vec<T>))
|
||||||
}
|
}
|
||||||
_ => Err((*value).type_name()),
|
_ => Err(cell.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
@ -2013,16 +2031,12 @@ impl Dynamic {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn into_blob(self) -> Result<crate::Blob, &'static str> {
|
pub fn into_blob(self) -> Result<crate::Blob, &'static str> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
Union::Blob(a, ..) => Ok(*a),
|
Union::Blob(b, ..) => Ok(*b),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(ref cell, ..) => {
|
Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
|
||||||
let value = crate::func::locked_read(cell);
|
Union::Blob(ref b, ..) => Ok(b.as_ref().clone()),
|
||||||
|
_ => Err(cell.type_name()),
|
||||||
match value.0 {
|
},
|
||||||
Union::Blob(ref a, ..) => Ok(a.as_ref().clone()),
|
|
||||||
_ => Err((*value).type_name()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user