Code style cleanup.

This commit is contained in:
Stephen Chung 2021-06-13 17:41:34 +08:00
parent 8ca24059b1
commit 743d48f44f
8 changed files with 563 additions and 618 deletions

View File

@ -917,7 +917,7 @@ impl StmtBlock {
/// Get the statements of this statements block. /// Get the statements of this statements block.
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn statements(&mut self) -> &mut StaticVec<Stmt> { pub fn statements_mut(&mut self) -> &mut StaticVec<Stmt> {
&mut self.0 &mut self.0
} }
} }
@ -1537,18 +1537,6 @@ impl FnCallHashes {
pub fn is_native_only(&self) -> bool { pub fn is_native_only(&self) -> bool {
self.script.is_none() self.script.is_none()
} }
/// Get the script function hash from this [`FnCallHashes`].
#[inline(always)]
#[must_use]
pub fn script_hash(&self) -> Option<u64> {
self.script
}
/// Get the naive Rust function hash from this [`FnCallHashes`].
#[inline(always)]
#[must_use]
pub fn native_hash(&self) -> u64 {
self.native
}
} }
/// _(INTERNALS)_ A function call. /// _(INTERNALS)_ A function call.

View File

@ -253,10 +253,10 @@ impl<'d, T: Any + Clone> Deref for DynamicReadLock<'d, T> {
#[inline(always)] #[inline(always)]
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match &self.0 { match self.0 {
DynamicReadLockInner::Reference(reference) => *reference, DynamicReadLockInner::Reference(ref reference) => *reference,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
DynamicReadLockInner::Guard(guard) => guard.downcast_ref().expect( DynamicReadLockInner::Guard(ref guard) => guard.downcast_ref().expect(
"never fails because the read guard was created after checking the data type", "never fails because the read guard was created after checking the data type",
), ),
} }
@ -296,10 +296,10 @@ impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> {
#[inline(always)] #[inline(always)]
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match &self.0 { match self.0 {
DynamicWriteLockInner::Reference(reference) => *reference, DynamicWriteLockInner::Reference(ref reference) => *reference,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
DynamicWriteLockInner::Guard(guard) => guard.downcast_ref().expect( DynamicWriteLockInner::Guard(ref guard) => guard.downcast_ref().expect(
"never fails because the write guard was created after checking the data type", "never fails because the write guard was created after checking the data type",
), ),
} }
@ -309,10 +309,10 @@ impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> {
impl<'d, T: Any + Clone> DerefMut for DynamicWriteLock<'d, T> { impl<'d, T: Any + Clone> DerefMut for DynamicWriteLock<'d, T> {
#[inline(always)] #[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
match &mut self.0 { match self.0 {
DynamicWriteLockInner::Reference(reference) => *reference, DynamicWriteLockInner::Reference(ref mut reference) => *reference,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
DynamicWriteLockInner::Guard(guard) => guard.downcast_mut().expect( DynamicWriteLockInner::Guard(ref mut guard) => guard.downcast_mut().expect(
"never fails because the write guard was created after checking the data type", "never fails because the write guard was created after checking the data type",
), ),
} }
@ -348,27 +348,27 @@ impl Dynamic {
} }
/// Attach arbitrary data to this [`Dynamic`]. /// Attach arbitrary data to this [`Dynamic`].
pub fn set_tag(&mut self, value: Tag) -> &mut Self { pub fn set_tag(&mut self, value: Tag) -> &mut Self {
match &mut self.0 { match self.0 {
Union::Unit(_, tag, _) Union::Unit(_, ref mut tag, _)
| Union::Bool(_, tag, _) | Union::Bool(_, ref mut tag, _)
| Union::Str(_, tag, _) | Union::Str(_, ref mut tag, _)
| Union::Char(_, tag, _) | Union::Char(_, ref mut tag, _)
| Union::Int(_, tag, _) | Union::Int(_, ref mut tag, _)
| Union::FnPtr(_, tag, _) | Union::FnPtr(_, ref mut tag, _)
| Union::Variant(_, tag, _) => *tag = value, | Union::Variant(_, ref mut tag, _) => *tag = value,
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Union::Float(_, tag, _) => *tag = value, Union::Float(_, ref mut tag, _) => *tag = value,
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
Union::Decimal(_, tag, _) => *tag = value, Union::Decimal(_, ref mut tag, _) => *tag = value,
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Array(_, tag, _) => *tag = value, Union::Array(_, ref mut tag, _) => *tag = value,
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Union::Map(_, tag, _) => *tag = value, Union::Map(_, ref mut tag, _) => *tag = value,
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
Union::TimeStamp(_, tag, _) => *tag = value, Union::TimeStamp(_, ref mut tag, _) => *tag = value,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(_, tag, _) => *tag = value, Union::Shared(_, ref mut tag, _) => *tag = value,
} }
self self
} }
@ -420,7 +420,7 @@ impl Dynamic {
/// Otherwise, this call panics if the data is currently borrowed for write. /// Otherwise, this call panics if the data is currently borrowed for write.
#[must_use] #[must_use]
pub fn type_id(&self) -> TypeId { pub fn type_id(&self) -> TypeId {
match &self.0 { match self.0 {
Union::Unit(_, _, _) => TypeId::of::<()>(), Union::Unit(_, _, _) => TypeId::of::<()>(),
Union::Bool(_, _, _) => TypeId::of::<bool>(), Union::Bool(_, _, _) => TypeId::of::<bool>(),
Union::Str(_, _, _) => TypeId::of::<ImmutableString>(), Union::Str(_, _, _) => TypeId::of::<ImmutableString>(),
@ -438,17 +438,15 @@ impl Dynamic {
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
Union::TimeStamp(_, _, _) => TypeId::of::<Instant>(), Union::TimeStamp(_, _, _) => TypeId::of::<Instant>(),
Union::Variant(value, _, _) => value.as_ref().as_ref().type_id(), Union::Variant(ref value, _, _) => (***value).type_id(),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(cell, _, _) => { #[cfg(not(feature = "sync"))]
#[cfg(not(feature = "sync"))] Union::Shared(ref cell, _, _) => (*cell.borrow()).type_id(),
let value = cell.borrow();
#[cfg(feature = "sync")]
let value = cell.read().unwrap();
(*value).type_id() #[cfg(not(feature = "no_closure"))]
} #[cfg(feature = "sync")]
Union::Shared(ref cell, _, _) => (*cell.read().unwrap()).type_id(),
} }
} }
/// Get the name of the type of the value held by this [`Dynamic`]. /// Get the name of the type of the value held by this [`Dynamic`].
@ -459,7 +457,7 @@ impl Dynamic {
/// Otherwise, this call panics if the data is currently borrowed for write. /// Otherwise, this call panics if the data is currently borrowed for write.
#[must_use] #[must_use]
pub fn type_name(&self) -> &'static str { pub fn type_name(&self) -> &'static str {
match &self.0 { match self.0 {
Union::Unit(_, _, _) => "()", Union::Unit(_, _, _) => "()",
Union::Bool(_, _, _) => "bool", Union::Bool(_, _, _) => "bool",
Union::Str(_, _, _) => "string", Union::Str(_, _, _) => "string",
@ -477,17 +475,17 @@ impl Dynamic {
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
Union::TimeStamp(_, _, _) => "timestamp", Union::TimeStamp(_, _, _) => "timestamp",
Union::Variant(value, _, _) => value.as_ref().as_ref().type_name(), Union::Variant(ref value, _, _) => (***value).type_name(),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
Union::Shared(cell, _, _) => cell Union::Shared(ref cell, _, _) => cell
.try_borrow() .try_borrow()
.map(|v| (*v).type_name()) .map(|v| (*v).type_name())
.unwrap_or("<shared>"), .unwrap_or("<shared>"),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
Union::Shared(cell, _, _) => (*cell.read().unwrap()).type_name(), Union::Shared(ref cell, _, _) => (*cell.read().unwrap()).type_name(),
} }
} }
} }
@ -501,76 +499,67 @@ impl Hash for Dynamic {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
std::mem::discriminant(&self.0).hash(state); std::mem::discriminant(&self.0).hash(state);
match &self.0 { match self.0 {
Union::Unit(_, _, _) => ().hash(state), Union::Unit(_, _, _) => ().hash(state),
Union::Bool(b, _, _) => b.hash(state), Union::Bool(ref b, _, _) => b.hash(state),
Union::Str(s, _, _) => s.hash(state), Union::Str(ref s, _, _) => s.hash(state),
Union::Char(c, _, _) => c.hash(state), Union::Char(ref c, _, _) => c.hash(state),
Union::Int(i, _, _) => i.hash(state), Union::Int(ref i, _, _) => i.hash(state),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Union::Float(f, _, _) => f.hash(state), Union::Float(ref f, _, _) => f.hash(state),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Array(a, _, _) => a.as_ref().hash(state), Union::Array(ref a, _, _) => a.as_ref().hash(state),
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Union::Map(m, _, _) => m.as_ref().hash(state), Union::Map(ref m, _, _) => m.as_ref().hash(state),
Union::FnPtr(f, _, _) => f.hash(state), Union::FnPtr(ref f, _, _) => f.hash(state),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(cell, _, _) => { #[cfg(not(feature = "sync"))]
#[cfg(not(feature = "sync"))] Union::Shared(ref cell, _, _) => (*cell.borrow()).hash(state),
let value = cell.borrow();
#[cfg(feature = "sync")]
let value = cell.read().unwrap();
(*value).hash(state) #[cfg(not(feature = "no_closure"))]
} #[cfg(feature = "sync")]
Union::Shared(ref cell, _, _) => (*cell.read().unwrap()).hash(state),
#[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))] #[cfg(not(feature = "only_i64"))]
Union::Variant(value, _, _) => { Union::Variant(ref value, _, _) => {
let value = value.as_ref().as_ref(); let value_any = (***value).as_any();
let _type_id = value.type_id(); let type_id = value_any.type_id();
let _value_any = value.as_any();
if _type_id == TypeId::of::<u8>() { if type_id == TypeId::of::<u8>() {
TypeId::of::<u8>().hash(state); TypeId::of::<u8>().hash(state);
_value_any.downcast_ref::<u8>().expect(CHECKED).hash(state); value_any.downcast_ref::<u8>().expect(CHECKED).hash(state);
} else if _type_id == TypeId::of::<u16>() { } else if type_id == TypeId::of::<u16>() {
TypeId::of::<u16>().hash(state); TypeId::of::<u16>().hash(state);
_value_any.downcast_ref::<u16>().expect(CHECKED).hash(state); value_any.downcast_ref::<u16>().expect(CHECKED).hash(state);
} else if _type_id == TypeId::of::<u32>() { } else if type_id == TypeId::of::<u32>() {
TypeId::of::<u32>().hash(state); TypeId::of::<u32>().hash(state);
_value_any.downcast_ref::<u32>().expect(CHECKED).hash(state); value_any.downcast_ref::<u32>().expect(CHECKED).hash(state);
} else if _type_id == TypeId::of::<u64>() { } else if type_id == TypeId::of::<u64>() {
TypeId::of::<u64>().hash(state); TypeId::of::<u64>().hash(state);
_value_any.downcast_ref::<u64>().expect(CHECKED).hash(state); value_any.downcast_ref::<u64>().expect(CHECKED).hash(state);
} else if _type_id == TypeId::of::<i8>() { } else if type_id == TypeId::of::<i8>() {
TypeId::of::<i8>().hash(state); TypeId::of::<i8>().hash(state);
_value_any.downcast_ref::<i8>().expect(CHECKED).hash(state); value_any.downcast_ref::<i8>().expect(CHECKED).hash(state);
} else if _type_id == TypeId::of::<i16>() { } else if type_id == TypeId::of::<i16>() {
TypeId::of::<i16>().hash(state); TypeId::of::<i16>().hash(state);
_value_any.downcast_ref::<i16>().expect(CHECKED).hash(state); value_any.downcast_ref::<i16>().expect(CHECKED).hash(state);
} else if _type_id == TypeId::of::<i32>() { } else if type_id == TypeId::of::<i32>() {
TypeId::of::<i32>().hash(state); TypeId::of::<i32>().hash(state);
_value_any.downcast_ref::<i32>().expect(CHECKED).hash(state); value_any.downcast_ref::<i32>().expect(CHECKED).hash(state);
} else if _type_id == TypeId::of::<i64>() { } else if type_id == TypeId::of::<i64>() {
TypeId::of::<i64>().hash(state); TypeId::of::<i64>().hash(state);
_value_any.downcast_ref::<i64>().expect(CHECKED).hash(state); value_any.downcast_ref::<i64>().expect(CHECKED).hash(state);
} }
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))] #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
if _type_id == TypeId::of::<u128>() { if type_id == TypeId::of::<u128>() {
TypeId::of::<u128>().hash(state); TypeId::of::<u128>().hash(state);
_value_any value_any.downcast_ref::<u128>().expect(CHECKED).hash(state);
.downcast_ref::<u128>() } else if type_id == TypeId::of::<i128>() {
.expect(CHECKED)
.hash(state);
} else if _type_id == TypeId::of::<i128>() {
TypeId::of::<i128>().hash(state); TypeId::of::<i128>().hash(state);
_value_any value_any.downcast_ref::<i128>().expect(CHECKED).hash(state);
.downcast_ref::<i128>()
.expect(CHECKED)
.hash(state);
} }
} }
@ -617,31 +606,30 @@ pub(crate) fn map_std_type_name(name: &str) -> &str {
impl fmt::Display for Dynamic { impl fmt::Display for Dynamic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.0 { match self.0 {
Union::Unit(_, _, _) => write!(f, ""), Union::Unit(_, _, _) => write!(f, ""),
Union::Bool(value, _, _) => fmt::Display::fmt(value, f), Union::Bool(ref value, _, _) => fmt::Display::fmt(value, f),
Union::Str(value, _, _) => fmt::Display::fmt(value, f), Union::Str(ref value, _, _) => fmt::Display::fmt(value, f),
Union::Char(value, _, _) => fmt::Display::fmt(value, f), Union::Char(ref value, _, _) => fmt::Display::fmt(value, f),
Union::Int(value, _, _) => fmt::Display::fmt(value, f), Union::Int(ref value, _, _) => fmt::Display::fmt(value, f),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Union::Float(value, _, _) => fmt::Display::fmt(value, f), Union::Float(ref value, _, _) => fmt::Display::fmt(value, f),
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
Union::Decimal(value, _, _) => fmt::Display::fmt(value, f), Union::Decimal(ref value, _, _) => fmt::Display::fmt(value, f),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Array(value, _, _) => fmt::Debug::fmt(value, f), Union::Array(ref value, _, _) => fmt::Debug::fmt(value, f),
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Union::Map(value, _, _) => { Union::Map(ref value, _, _) => {
f.write_str("#")?; f.write_str("#")?;
fmt::Debug::fmt(value, f) fmt::Debug::fmt(value, f)
} }
Union::FnPtr(value, _, _) => fmt::Display::fmt(value, f), Union::FnPtr(ref value, _, _) => fmt::Display::fmt(value, f),
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
Union::TimeStamp(_, _, _) => f.write_str("<timestamp>"), Union::TimeStamp(_, _, _) => f.write_str("<timestamp>"),
Union::Variant(value, _, _) => { Union::Variant(ref value, _, _) => {
let value = value.as_ref().as_ref(); let _value_any = (***value).as_any();
let _type_id = value.type_id(); let _type_id = _value_any.type_id();
let _value_any = value.as_any();
#[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))] #[cfg(not(feature = "only_i64"))]
@ -677,12 +665,12 @@ impl fmt::Display for Dynamic {
return fmt::Display::fmt(_value_any.downcast_ref::<i128>().expect(CHECKED), f); return fmt::Display::fmt(_value_any.downcast_ref::<i128>().expect(CHECKED), f);
} }
f.write_str(value.type_name()) f.write_str((***value).type_name())
} }
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
Union::Shared(cell, _, _) => { Union::Shared(ref cell, _, _) => {
if let Ok(v) = cell.try_borrow() { if let Ok(v) = cell.try_borrow() {
fmt::Display::fmt(&*v, f) fmt::Display::fmt(&*v, f)
} else { } else {
@ -691,38 +679,37 @@ impl fmt::Display for Dynamic {
} }
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
Union::Shared(cell, _, _) => fmt::Display::fmt(&*cell.read().unwrap(), f), Union::Shared(ref cell, _, _) => fmt::Display::fmt(&*cell.read().unwrap(), f),
} }
} }
} }
impl fmt::Debug for Dynamic { impl fmt::Debug for Dynamic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.0 { match self.0 {
Union::Unit(value, _, _) => fmt::Debug::fmt(value, f), Union::Unit(ref value, _, _) => fmt::Debug::fmt(value, f),
Union::Bool(value, _, _) => fmt::Debug::fmt(value, f), Union::Bool(ref value, _, _) => fmt::Debug::fmt(value, f),
Union::Str(value, _, _) => fmt::Debug::fmt(value, f), Union::Str(ref value, _, _) => fmt::Debug::fmt(value, f),
Union::Char(value, _, _) => fmt::Debug::fmt(value, f), Union::Char(ref value, _, _) => fmt::Debug::fmt(value, f),
Union::Int(value, _, _) => fmt::Debug::fmt(value, f), Union::Int(ref value, _, _) => fmt::Debug::fmt(value, f),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Union::Float(value, _, _) => fmt::Debug::fmt(value, f), Union::Float(ref value, _, _) => fmt::Debug::fmt(value, f),
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
Union::Decimal(value, _, _) => fmt::Debug::fmt(value, f), Union::Decimal(ref value, _, _) => fmt::Debug::fmt(value, f),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Array(value, _, _) => fmt::Debug::fmt(value, f), Union::Array(ref value, _, _) => fmt::Debug::fmt(value, f),
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Union::Map(value, _, _) => { Union::Map(ref value, _, _) => {
f.write_str("#")?; f.write_str("#")?;
fmt::Debug::fmt(value, f) fmt::Debug::fmt(value, f)
} }
Union::FnPtr(value, _, _) => fmt::Debug::fmt(value, f), Union::FnPtr(ref value, _, _) => fmt::Debug::fmt(value, f),
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
Union::TimeStamp(_, _, _) => write!(f, "<timestamp>"), Union::TimeStamp(_, _, _) => write!(f, "<timestamp>"),
Union::Variant(value, _, _) => { Union::Variant(ref value, _, _) => {
let value = value.as_ref().as_ref(); let _value_any = (***value).as_any();
let _type_id = value.type_id(); let _type_id = _value_any.type_id();
let _value_any = value.as_any();
const CHECKED: &str = "never fails because the type was checked"; const CHECKED: &str = "never fails because the type was checked";
@ -760,12 +747,12 @@ impl fmt::Debug for Dynamic {
return fmt::Debug::fmt(_value_any.downcast_ref::<i128>().expect(CHECKED), f); return fmt::Debug::fmt(_value_any.downcast_ref::<i128>().expect(CHECKED), f);
} }
f.write_str(value.type_name()) f.write_str((***value).type_name())
} }
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
Union::Shared(cell, _, _) => { Union::Shared(ref cell, _, _) => {
if let Ok(v) = cell.try_borrow() { if let Ok(v) = cell.try_borrow() {
write!(f, "{:?} (shared)", *v) write!(f, "{:?} (shared)", *v)
} else { } else {
@ -774,7 +761,7 @@ impl fmt::Debug for Dynamic {
} }
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
Union::Shared(cell, _, _) => fmt::Debug::fmt(&*cell.read().unwrap(), f), Union::Shared(ref cell, _, _) => fmt::Debug::fmt(&*cell.read().unwrap(), f),
} }
} }
} }
@ -921,37 +908,37 @@ impl Dynamic {
} }
/// Set the [`AccessMode`] for this [`Dynamic`]. /// Set the [`AccessMode`] for this [`Dynamic`].
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self { pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
match &mut self.0 { match self.0 {
Union::Unit(_, _, access) Union::Unit(_, _, ref mut access)
| Union::Bool(_, _, access) | Union::Bool(_, _, ref mut access)
| Union::Str(_, _, access) | Union::Str(_, _, ref mut access)
| Union::Char(_, _, access) | Union::Char(_, _, ref mut access)
| Union::Int(_, _, access) | Union::Int(_, _, ref mut access)
| Union::FnPtr(_, _, access) | Union::FnPtr(_, _, ref mut access)
| Union::Variant(_, _, access) => *access = typ, | Union::Variant(_, _, ref mut access) => *access = typ,
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Union::Float(_, _, access) => *access = typ, Union::Float(_, _, ref mut access) => *access = typ,
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
Union::Decimal(_, _, access) => *access = typ, Union::Decimal(_, _, ref mut access) => *access = typ,
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Union::Array(a, _, access) => { Union::Array(ref mut a, _, ref mut access) => {
*access = typ; *access = typ;
a.iter_mut().for_each(|v| { a.iter_mut().for_each(|v| {
v.set_access_mode(typ); v.set_access_mode(typ);
}); });
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Union::Map(m, _, access) => { Union::Map(ref mut m, _, ref mut access) => {
*access = typ; *access = typ;
m.values_mut().for_each(|v| { m.values_mut().for_each(|v| {
v.set_access_mode(typ); v.set_access_mode(typ);
}); });
} }
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
Union::TimeStamp(_, _, access) => *access = typ, Union::TimeStamp(_, _, ref mut access) => *access = typ,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(_, _, access) => *access = typ, Union::Shared(_, _, ref mut access) => *access = typ,
} }
self self
} }
@ -967,17 +954,22 @@ impl Dynamic {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
match self.0 { match self.0 {
Union::Shared(_, _, ReadOnly) => return true, Union::Shared(_, _, ReadOnly) => return true,
Union::Shared(ref cell, _, _) => {
#[cfg(not(feature = "sync"))]
let value = cell.borrow();
#[cfg(feature = "sync")]
let value = cell.read().unwrap();
return match value.access_mode() { #[cfg(not(feature = "sync"))]
Union::Shared(ref cell, _, _) => {
return match cell.borrow().access_mode() {
ReadWrite => false, ReadWrite => false,
ReadOnly => true, ReadOnly => true,
}; }
} }
#[cfg(feature = "sync")]
Union::Shared(ref cell, _, _) => {
return match cell.read().unwrap().access_mode() {
ReadWrite => false,
ReadOnly => true,
}
}
_ => (), _ => (),
} }
@ -989,7 +981,7 @@ impl Dynamic {
/// Can this [`Dynamic`] be hashed? /// Can this [`Dynamic`] be hashed?
#[must_use] #[must_use]
pub(crate) fn is_hashable(&self) -> bool { pub(crate) fn is_hashable(&self) -> bool {
match &self.0 { match self.0 {
Union::Unit(_, _, _) Union::Unit(_, _, _)
| Union::Bool(_, _, _) | Union::Bool(_, _, _)
| Union::Str(_, _, _) | Union::Str(_, _, _)
@ -1004,14 +996,12 @@ impl Dynamic {
Union::Map(_, _, _) => true, Union::Map(_, _, _) => true,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(cell, _, _) => { #[cfg(not(feature = "sync"))]
#[cfg(not(feature = "sync"))] Union::Shared(ref cell, _, _) => cell.borrow().is_hashable(),
let value = cell.borrow();
#[cfg(feature = "sync")]
let value = cell.read().unwrap();
value.is_hashable() #[cfg(not(feature = "no_closure"))]
} #[cfg(feature = "sync")]
Union::Shared(ref cell, _, _) => cell.read().unwrap().is_hashable(),
_ => false, _ => false,
} }
@ -1388,20 +1378,15 @@ impl Dynamic {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn flatten_clone(&self) -> Self { pub fn flatten_clone(&self) -> Self {
#[cfg(not(feature = "no_closure"))] match self.0 {
match &self.0 { #[cfg(not(feature = "no_closure"))]
Union::Shared(cell, _, _) => { #[cfg(not(feature = "sync"))]
#[cfg(not(feature = "sync"))] Union::Shared(ref cell, _, _) => cell.borrow().clone(),
let value = cell.borrow(); #[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
let value = cell.read().unwrap(); Union::Shared(ref cell, _, _) => cell.read().unwrap().clone(),
_ => self.clone(),
return value.clone();
}
_ => (),
} }
self.clone()
} }
/// Flatten the [`Dynamic`]. /// Flatten the [`Dynamic`].
/// ///
@ -1412,30 +1397,20 @@ impl Dynamic {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn flatten(self) -> Self { pub fn flatten(self) -> Self {
#[cfg(not(feature = "no_closure"))]
match self.0 { match self.0 {
Union::Shared(cell, _, _) => { #[cfg(not(feature = "no_closure"))]
return crate::fn_native::shared_try_take(cell).map_or_else( Union::Shared(cell, _, _) => crate::fn_native::shared_try_take(cell).map_or_else(
|cell| { #[cfg(not(feature = "sync"))]
#[cfg(not(feature = "sync"))] |cell| cell.borrow().clone(),
let value = cell.borrow(); #[cfg(feature = "sync")]
#[cfg(feature = "sync")] |cell| cell.read().unwrap().clone(),
let value = cell.read().unwrap(); #[cfg(not(feature = "sync"))]
|value| value.into_inner(),
value.clone() #[cfg(feature = "sync")]
}, |value| value.into_inner().unwrap(),
|value| { ),
#[cfg(not(feature = "sync"))] _ => self,
return value.into_inner();
#[cfg(feature = "sync")]
return value.into_inner().unwrap();
},
)
}
_ => (),
} }
self
} }
/// Flatten the [`Dynamic`] in place. /// Flatten the [`Dynamic`] in place.
/// ///
@ -1445,26 +1420,20 @@ impl Dynamic {
/// outstanding references, or a cloned copy otherwise. /// outstanding references, or a cloned copy otherwise.
#[inline(always)] #[inline(always)]
pub(crate) fn flatten_in_place(&mut self) -> &mut Self { pub(crate) fn flatten_in_place(&mut self) -> &mut Self {
#[cfg(not(feature = "no_closure"))]
match self.0 { match self.0 {
#[cfg(not(feature = "no_closure"))]
Union::Shared(_, _, _) => match std::mem::take(self).0 { Union::Shared(_, _, _) => match std::mem::take(self).0 {
Union::Shared(cell, _, _) => { Union::Shared(cell, _, _) => {
*self = crate::fn_native::shared_try_take(cell).map_or_else( *self = crate::fn_native::shared_try_take(cell).map_or_else(
|cell| { #[cfg(not(feature = "sync"))]
#[cfg(not(feature = "sync"))] |cell| cell.borrow().clone(),
let value = cell.borrow(); #[cfg(feature = "sync")]
#[cfg(feature = "sync")] |cell| cell.read().unwrap().clone(),
let value = cell.read().unwrap(); #[cfg(not(feature = "sync"))]
|value| value.into_inner(),
value.clone() #[cfg(feature = "sync")]
}, |value| value.into_inner().unwrap(),
|value| { );
#[cfg(not(feature = "sync"))]
return value.into_inner();
#[cfg(feature = "sync")]
return value.into_inner().unwrap();
},
)
} }
_ => unreachable!(), _ => unreachable!(),
}, },
@ -1577,73 +1546,73 @@ impl Dynamic {
// Coded this way in order to maximally leverage potentials for dead-code removal. // Coded this way in order to maximally leverage potentials for dead-code removal.
if TypeId::of::<T>() == TypeId::of::<INT>() { if TypeId::of::<T>() == TypeId::of::<INT>() {
return match &self.0 { return match self.0 {
Union::Int(value, _, _) => value.as_any().downcast_ref::<T>(), Union::Int(ref value, _, _) => value.as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
if TypeId::of::<T>() == TypeId::of::<FLOAT>() { if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
return match &self.0 { return match self.0 {
Union::Float(value, _, _) => value.as_ref().as_any().downcast_ref::<T>(), Union::Float(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
if TypeId::of::<T>() == TypeId::of::<Decimal>() { if TypeId::of::<T>() == TypeId::of::<Decimal>() {
return match &self.0 { return match self.0 {
Union::Decimal(value, _, _) => value.as_ref().as_any().downcast_ref::<T>(), Union::Decimal(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<bool>() { if TypeId::of::<T>() == TypeId::of::<bool>() {
return match &self.0 { return match self.0 {
Union::Bool(value, _, _) => value.as_any().downcast_ref::<T>(), Union::Bool(ref value, _, _) => value.as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() { if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
return match &self.0 { return match self.0 {
Union::Str(value, _, _) => value.as_any().downcast_ref::<T>(), Union::Str(ref value, _, _) => value.as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<char>() { if TypeId::of::<T>() == TypeId::of::<char>() {
return match &self.0 { return match self.0 {
Union::Char(value, _, _) => value.as_any().downcast_ref::<T>(), Union::Char(ref value, _, _) => value.as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if TypeId::of::<T>() == TypeId::of::<Array>() { if TypeId::of::<T>() == TypeId::of::<Array>() {
return match &self.0 { return match self.0 {
Union::Array(value, _, _) => value.as_ref().as_any().downcast_ref::<T>(), Union::Array(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
if TypeId::of::<T>() == TypeId::of::<Map>() { if TypeId::of::<T>() == TypeId::of::<Map>() {
return match &self.0 { return match self.0 {
Union::Map(value, _, _) => value.as_ref().as_any().downcast_ref::<T>(), Union::Map(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<FnPtr>() { if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
return match &self.0 { return match self.0 {
Union::FnPtr(value, _, _) => value.as_ref().as_any().downcast_ref::<T>(), Union::FnPtr(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
if TypeId::of::<T>() == TypeId::of::<Instant>() { if TypeId::of::<T>() == TypeId::of::<Instant>() {
return match &self.0 { return match self.0 {
Union::TimeStamp(value, _, _) => value.as_ref().as_any().downcast_ref::<T>(), Union::TimeStamp(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<()>() { if TypeId::of::<T>() == TypeId::of::<()>() {
return match &self.0 { return match self.0 {
Union::Unit(value, _, _) => value.as_any().downcast_ref::<T>(), Union::Unit(ref value, _, _) => value.as_any().downcast_ref::<T>(),
_ => None, _ => None,
}; };
} }
@ -1651,8 +1620,8 @@ impl Dynamic {
return self.as_any().downcast_ref::<T>(); return self.as_any().downcast_ref::<T>();
} }
match &self.0 { match self.0 {
Union::Variant(value, _, _) => value.as_ref().as_ref().as_any().downcast_ref::<T>(), Union::Variant(ref value, _, _) => (***value).as_any().downcast_ref::<T>(),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(_, _, _) => None, Union::Shared(_, _, _) => None,
_ => None, _ => None,
@ -1668,73 +1637,83 @@ impl Dynamic {
// Coded this way in order to maximally leverage potentials for dead-code removal. // Coded this way in order to maximally leverage potentials for dead-code removal.
if TypeId::of::<T>() == TypeId::of::<INT>() { if TypeId::of::<T>() == TypeId::of::<INT>() {
return match &mut self.0 { return match self.0 {
Union::Int(value, _, _) => value.as_mut_any().downcast_mut::<T>(), Union::Int(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
if TypeId::of::<T>() == TypeId::of::<FLOAT>() { if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
return match &mut self.0 { return match self.0 {
Union::Float(value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(), Union::Float(ref mut value, _, _) => {
value.as_mut().as_mut_any().downcast_mut::<T>()
}
_ => None, _ => None,
}; };
} }
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
if TypeId::of::<T>() == TypeId::of::<Decimal>() { if TypeId::of::<T>() == TypeId::of::<Decimal>() {
return match &mut self.0 { return match self.0 {
Union::Decimal(value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(), Union::Decimal(ref mut value, _, _) => {
value.as_mut().as_mut_any().downcast_mut::<T>()
}
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<bool>() { if TypeId::of::<T>() == TypeId::of::<bool>() {
return match &mut self.0 { return match self.0 {
Union::Bool(value, _, _) => value.as_mut_any().downcast_mut::<T>(), Union::Bool(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() { if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
return match &mut self.0 { return match self.0 {
Union::Str(value, _, _) => value.as_mut_any().downcast_mut::<T>(), Union::Str(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<char>() { if TypeId::of::<T>() == TypeId::of::<char>() {
return match &mut self.0 { return match self.0 {
Union::Char(value, _, _) => value.as_mut_any().downcast_mut::<T>(), Union::Char(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if TypeId::of::<T>() == TypeId::of::<Array>() { if TypeId::of::<T>() == TypeId::of::<Array>() {
return match &mut self.0 { return match self.0 {
Union::Array(value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(), Union::Array(ref mut value, _, _) => {
value.as_mut().as_mut_any().downcast_mut::<T>()
}
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
if TypeId::of::<T>() == TypeId::of::<Map>() { if TypeId::of::<T>() == TypeId::of::<Map>() {
return match &mut self.0 { return match self.0 {
Union::Map(value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(), Union::Map(ref mut value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(),
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<FnPtr>() { if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
return match &mut self.0 { return match self.0 {
Union::FnPtr(value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(), Union::FnPtr(ref mut value, _, _) => {
value.as_mut().as_mut_any().downcast_mut::<T>()
}
_ => None, _ => None,
}; };
} }
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
if TypeId::of::<T>() == TypeId::of::<Instant>() { if TypeId::of::<T>() == TypeId::of::<Instant>() {
return match &mut self.0 { return match self.0 {
Union::TimeStamp(value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(), Union::TimeStamp(ref mut value, _, _) => {
value.as_mut().as_mut_any().downcast_mut::<T>()
}
_ => None, _ => None,
}; };
} }
if TypeId::of::<T>() == TypeId::of::<()>() { if TypeId::of::<T>() == TypeId::of::<()>() {
return match &mut self.0 { return match self.0 {
Union::Unit(value, _, _) => value.as_mut_any().downcast_mut::<T>(), Union::Unit(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
_ => None, _ => None,
}; };
} }
@ -1742,8 +1721,8 @@ impl Dynamic {
return self.as_mut_any().downcast_mut::<T>(); return self.as_mut_any().downcast_mut::<T>();
} }
match &mut self.0 { match self.0 {
Union::Variant(value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(), Union::Variant(ref mut value, _, _) => (***value).as_mut_any().downcast_mut::<T>(),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(_, _, _) => None, Union::Shared(_, _, _) => None,
_ => None, _ => None,
@ -1898,8 +1877,8 @@ impl Dynamic {
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
let value = cell.read().unwrap(); let value = cell.read().unwrap();
match &value.0 { match value.0 {
Union::Str(s, _, _) => Ok(s.clone()), Union::Str(ref s, _, _) => Ok(s.clone()),
_ => Err((*value).type_name()), _ => Err((*value).type_name()),
} }
} }

View File

@ -1320,9 +1320,9 @@ impl Engine {
// xxx.fn_name(arg_expr_list) // xxx.fn_name(arg_expr_list)
Expr::FnCall(x, pos) if !x.is_qualified() && new_val.is_none() => { Expr::FnCall(x, pos) if !x.is_qualified() && new_val.is_none() => {
let FnCallExpr { name, hashes, .. } = x.as_ref(); let FnCallExpr { name, hashes, .. } = x.as_ref();
let mut args = idx_val.as_fn_call_args(); let args = &mut idx_val.as_fn_call_args();
self.make_method_call( self.make_method_call(
mods, state, lib, name, *hashes, target, &mut args, *pos, level, mods, state, lib, name, *hashes, target, args, *pos, level,
) )
} }
// xxx.fn_name(...) = ??? // xxx.fn_name(...) = ???
@ -1340,11 +1340,11 @@ impl Engine {
new_val.expect("never fails because `new_val` is `Some`"); new_val.expect("never fails because `new_val` is `Some`");
let index = name.into(); let index = name.into();
{ {
let mut val = self.get_indexed_mut( let val_target = &mut self.get_indexed_mut(
mods, state, lib, target, index, *pos, true, false, level, mods, state, lib, target, index, *pos, true, false, level,
)?; )?;
self.eval_op_assignment( self.eval_op_assignment(
mods, state, lib, op_info, op_pos, &mut val, root, new_val, mods, state, lib, op_info, op_pos, val_target, root, new_val,
) )
.map_err(|err| err.fill_position(new_pos))?; .map_err(|err| err.fill_position(new_pos))?;
} }
@ -1369,11 +1369,11 @@ impl Engine {
if op_info.is_some() { if op_info.is_some() {
let hash = FnCallHashes::from_native(*hash_get); let hash = FnCallHashes::from_native(*hash_get);
let mut args = [target.as_mut()]; let args = &mut [target.as_mut()];
let (mut orig_val, _) = self let (mut orig_val, _) = self
.exec_fn_call( .exec_fn_call(
mods, state, lib, getter, hash, &mut args, is_ref, true, *pos, mods, state, lib, getter, hash, args, is_ref, true, *pos, None,
None, level, level,
) )
.or_else(|err| match *err { .or_else(|err| match *err {
// Try an indexer if property does not exist // Try an indexer if property does not exist
@ -1413,16 +1413,14 @@ impl Engine {
} }
let hash = FnCallHashes::from_native(*hash_set); let hash = FnCallHashes::from_native(*hash_set);
let mut args = [target.as_mut(), &mut new_val]; let args = &mut [target.as_mut(), &mut new_val];
self.exec_fn_call( self.exec_fn_call(
mods, state, lib, setter, hash, &mut args, is_ref, true, *pos, None, mods, state, lib, setter, hash, args, is_ref, true, *pos, None, level,
level,
) )
.or_else(|err| match *err { .or_else(|err| match *err {
// Try an indexer if property does not exist // Try an indexer if property does not exist
EvalAltResult::ErrorDotExpr(_, _) => { EvalAltResult::ErrorDotExpr(_, _) => {
let mut prop = name.into(); let args = &mut [target, &mut name.into(), &mut new_val];
let args = &mut [target, &mut prop, &mut new_val];
let hash_set = let hash_set =
FnCallHashes::from_native(crate::calc_fn_hash(FN_IDX_SET, 3)); FnCallHashes::from_native(crate::calc_fn_hash(FN_IDX_SET, 3));
self.exec_fn_call( self.exec_fn_call(
@ -1443,10 +1441,9 @@ impl Engine {
Expr::Property(x) => { Expr::Property(x) => {
let ((getter, hash_get), _, (name, pos)) = x.as_ref(); let ((getter, hash_get), _, (name, pos)) = x.as_ref();
let hash = FnCallHashes::from_native(*hash_get); let hash = FnCallHashes::from_native(*hash_get);
let mut args = [target.as_mut()]; let args = &mut [target.as_mut()];
self.exec_fn_call( self.exec_fn_call(
mods, state, lib, getter, hash, &mut args, is_ref, true, *pos, None, mods, state, lib, getter, hash, args, is_ref, true, *pos, None, level,
level,
) )
.map_or_else( .map_or_else(
|err| match *err { |err| match *err {
@ -1471,8 +1468,8 @@ impl Engine {
} }
// {xxx:map}.sub_lhs[expr] | {xxx:map}.sub_lhs.expr // {xxx:map}.sub_lhs[expr] | {xxx:map}.sub_lhs.expr
Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) if target.is::<Map>() => { Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) if target.is::<Map>() => {
let mut val = match &x.lhs { let val_target = &mut match x.lhs {
Expr::Property(p) => { Expr::Property(ref p) => {
let (name, pos) = &p.2; let (name, pos) = &p.2;
let index = name.into(); let index = name.into();
self.get_indexed_mut( self.get_indexed_mut(
@ -1480,11 +1477,11 @@ impl Engine {
)? )?
} }
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr // {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
Expr::FnCall(x, pos) if !x.is_qualified() => { Expr::FnCall(ref x, pos) if !x.is_qualified() => {
let FnCallExpr { name, hashes, .. } = x.as_ref(); let FnCallExpr { name, hashes, .. } = x.as_ref();
let mut args = idx_val.as_fn_call_args(); let args = &mut idx_val.as_fn_call_args();
let (val, _) = self.make_method_call( let (val, _) = self.make_method_call(
mods, state, lib, name, *hashes, target, &mut args, *pos, level, mods, state, lib, name, *hashes, target, args, pos, level,
)?; )?;
val.into() val.into()
} }
@ -1493,21 +1490,21 @@ impl Engine {
"function call in dot chain should not be namespace-qualified" "function call in dot chain should not be namespace-qualified"
), ),
// Others - syntax error // Others - syntax error
expr => unreachable!("invalid dot expression: {:?}", expr), ref expr => unreachable!("invalid dot expression: {:?}", expr),
}; };
let rhs_chain = match_chain_type(rhs); let rhs_chain = match_chain_type(rhs);
self.eval_dot_index_chain_helper( self.eval_dot_index_chain_helper(
mods, state, lib, this_ptr, &mut val, root, &x.rhs, idx_values, mods, state, lib, this_ptr, val_target, root, &x.rhs, idx_values,
rhs_chain, level, new_val, rhs_chain, level, new_val,
) )
.map_err(|err| err.fill_position(*x_pos)) .map_err(|err| err.fill_position(*x_pos))
} }
// xxx.sub_lhs[expr] | xxx.sub_lhs.expr // xxx.sub_lhs[expr] | xxx.sub_lhs.expr
Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) => { Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) => {
match &x.lhs { match x.lhs {
// xxx.prop[expr] | xxx.prop.expr // xxx.prop[expr] | xxx.prop.expr
Expr::Property(p) => { Expr::Property(ref p) => {
let ((getter, hash_get), (setter, hash_set), (name, pos)) = let ((getter, hash_get), (setter, hash_set), (name, pos)) =
p.as_ref(); p.as_ref();
let rhs_chain = match_chain_type(rhs); let rhs_chain = match_chain_type(rhs);
@ -1570,8 +1567,8 @@ impl Engine {
|err| match *err { |err| match *err {
// Try an indexer if property does not exist // Try an indexer if property does not exist
EvalAltResult::ErrorDotExpr(_, _) => { EvalAltResult::ErrorDotExpr(_, _) => {
let mut prop = name.into(); let args =
let args = &mut [target.as_mut(), &mut prop, val]; &mut [target.as_mut(), &mut name.into(), val];
let hash_set = FnCallHashes::from_native( let hash_set = FnCallHashes::from_native(
crate::calc_fn_hash(FN_IDX_SET, 3), crate::calc_fn_hash(FN_IDX_SET, 3),
); );
@ -1598,12 +1595,12 @@ impl Engine {
Ok((result, may_be_changed)) Ok((result, may_be_changed))
} }
// xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr // xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr
Expr::FnCall(f, pos) if !f.is_qualified() => { Expr::FnCall(ref f, pos) if !f.is_qualified() => {
let FnCallExpr { name, hashes, .. } = f.as_ref(); let FnCallExpr { name, hashes, .. } = f.as_ref();
let rhs_chain = match_chain_type(rhs); let rhs_chain = match_chain_type(rhs);
let mut args = idx_val.as_fn_call_args(); let args = &mut idx_val.as_fn_call_args();
let (mut val, _) = self.make_method_call( let (mut val, _) = self.make_method_call(
mods, state, lib, name, *hashes, target, &mut args, *pos, level, mods, state, lib, name, *hashes, target, args, pos, level,
)?; )?;
let val = &mut val; let val = &mut val;
let target = &mut val.into(); let target = &mut val.into();
@ -1612,14 +1609,14 @@ impl Engine {
mods, state, lib, this_ptr, target, root, &x.rhs, idx_values, mods, state, lib, this_ptr, target, root, &x.rhs, idx_values,
rhs_chain, level, new_val, rhs_chain, level, new_val,
) )
.map_err(|err| err.fill_position(*pos)) .map_err(|err| err.fill_position(pos))
} }
// xxx.module::fn_name(...) - syntax error // xxx.module::fn_name(...) - syntax error
Expr::FnCall(_, _) => unreachable!( Expr::FnCall(_, _) => unreachable!(
"function call in dot chain should not be namespace-qualified" "function call in dot chain should not be namespace-qualified"
), ),
// Others - syntax error // Others - syntax error
expr => unreachable!("invalid dot expression: {:?}", expr), ref expr => unreachable!("invalid dot expression: {:?}", expr),
} }
} }
// Syntax error // Syntax error
@ -2109,7 +2106,7 @@ impl Engine {
let namespace = namespace let namespace = namespace
.as_ref() .as_ref()
.expect("never fails because function call is qualified"); .expect("never fails because function call is qualified");
let hash = hashes.native_hash(); let hash = hashes.native;
self.make_qualified_function_call( self.make_qualified_function_call(
scope, mods, state, lib, this_ptr, namespace, name, args, constants, hash, scope, mods, state, lib, this_ptr, namespace, name, args, constants, hash,
*pos, level, *pos, level,
@ -2702,7 +2699,7 @@ impl Engine {
let namespace = namespace let namespace = namespace
.as_ref() .as_ref()
.expect("never fails because function call is qualified"); .expect("never fails because function call is qualified");
let hash = hashes.native_hash(); let hash = hashes.native;
self.make_qualified_function_call( self.make_qualified_function_call(
scope, mods, state, lib, this_ptr, namespace, name, args, constants, hash, scope, mods, state, lib, this_ptr, namespace, name, args, constants, hash,
*pos, level, *pos, level,

View File

@ -56,91 +56,89 @@ pub fn get_builtin_binary_op_fn(
// One of the operands is a custom type, so it is never built-in // One of the operands is a custom type, so it is never built-in
if x.is_variant() || y.is_variant() { if x.is_variant() || y.is_variant() {
if is_numeric(type1) && is_numeric(type2) { return if is_numeric(type1) && is_numeric(type2) {
// Disallow comparisons between different numeric types // Disallow comparisons between different numeric types
return None; None
} } else if type1 != type2 {
// If the types are not the same, default to not compare
// If the types are not the same, default to not compare match op {
if type1 != type2 {
return match op {
"!=" => Some(|_, _| Ok(Dynamic::TRUE)), "!=" => Some(|_, _| Ok(Dynamic::TRUE)),
"==" | ">" | ">=" | "<" | "<=" => Some(|_, _| Ok(Dynamic::FALSE)), "==" | ">" | ">=" | "<" | "<=" => Some(|_, _| Ok(Dynamic::FALSE)),
_ => None, _ => None,
}; }
} } else {
// Disallow comparisons between the same type
// Disallow comparisons between the same type None
return None; };
} }
let types_pair = (type1, type2); let types_pair = (type1, type2);
macro_rules! impl_op { macro_rules! impl_op {
($xx:ident $op:tt $yy:ident) => { ($xx:ident $op:tt $yy:ident) => {
return Some(|_, args| { Some(|_, args| {
let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); let x = &*args[0].read_lock::<$xx>().expect(BUILTIN);
let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); let y = &*args[1].read_lock::<$yy>().expect(BUILTIN);
Ok((x $op y).into()) Ok((x $op y).into())
}) })
}; };
($xx:ident . $func:ident ( $yy:ty )) => { ($xx:ident . $func:ident ( $yy:ty )) => {
return Some(|_, args| { Some(|_, args| {
let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); let x = &*args[0].read_lock::<$xx>().expect(BUILTIN);
let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); let y = &*args[1].read_lock::<$yy>().expect(BUILTIN);
Ok(x.$func(y).into()) Ok(x.$func(y).into())
}) })
}; };
($xx:ident . $func:ident ( $yy:ident . $yyy:ident () )) => { ($xx:ident . $func:ident ( $yy:ident . $yyy:ident () )) => {
return Some(|_, args| { Some(|_, args| {
let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); let x = &*args[0].read_lock::<$xx>().expect(BUILTIN);
let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); let y = &*args[1].read_lock::<$yy>().expect(BUILTIN);
Ok(x.$func(y.$yyy()).into()) Ok(x.$func(y.$yyy()).into())
}) })
}; };
($func:ident ( $op:tt )) => { ($func:ident ( $op:tt )) => {
return Some(|_, args| { Some(|_, args| {
let (x, y) = $func(args); let (x, y) = $func(args);
Ok((x $op y).into()) Ok((x $op y).into())
}) })
}; };
($base:ty => $xx:ident $op:tt $yy:ident) => { ($base:ty => $xx:ident $op:tt $yy:ident) => {
return Some(|_, args| { Some(|_, args| {
let x = args[0].$xx().expect(BUILTIN) as $base; let x = args[0].$xx().expect(BUILTIN) as $base;
let y = args[1].$yy().expect(BUILTIN) as $base; let y = args[1].$yy().expect(BUILTIN) as $base;
Ok((x $op y).into()) Ok((x $op y).into())
}) })
}; };
($base:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty)) => { ($base:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty)) => {
return Some(|_, args| { Some(|_, args| {
let x = args[0].$xx().expect(BUILTIN) as $base; let x = args[0].$xx().expect(BUILTIN) as $base;
let y = args[1].$yy().expect(BUILTIN) as $base; let y = args[1].$yy().expect(BUILTIN) as $base;
Ok(x.$func(y as $yyy).into()) Ok(x.$func(y as $yyy).into())
}) })
}; };
($base:ty => $func:ident ( $xx:ident, $yy:ident )) => { ($base:ty => $func:ident ( $xx:ident, $yy:ident )) => {
return Some(|_, args| { Some(|_, args| {
let x = args[0].$xx().expect(BUILTIN) as $base; let x = args[0].$xx().expect(BUILTIN) as $base;
let y = args[1].$yy().expect(BUILTIN) as $base; let y = args[1].$yy().expect(BUILTIN) as $base;
$func(x, y).map(Into::<Dynamic>::into) $func(x, y).map(Into::<Dynamic>::into)
}) })
}; };
(from $base:ty => $xx:ident $op:tt $yy:ident) => { (from $base:ty => $xx:ident $op:tt $yy:ident) => {
return Some(|_, args| { Some(|_, args| {
let x = <$base>::from(args[0].$xx().expect(BUILTIN)); let x = <$base>::from(args[0].$xx().expect(BUILTIN));
let y = <$base>::from(args[1].$yy().expect(BUILTIN)); let y = <$base>::from(args[1].$yy().expect(BUILTIN));
Ok((x $op y).into()) Ok((x $op y).into())
}) })
}; };
(from $base:ty => $xx:ident . $func:ident ( $yy:ident )) => { (from $base:ty => $xx:ident . $func:ident ( $yy:ident )) => {
return Some(|_, args| { Some(|_, args| {
let x = <$base>::from(args[0].$xx().expect(BUILTIN)); let x = <$base>::from(args[0].$xx().expect(BUILTIN));
let y = <$base>::from(args[1].$yy().expect(BUILTIN)); let y = <$base>::from(args[1].$yy().expect(BUILTIN));
Ok(x.$func(y).into()) Ok(x.$func(y).into())
}) })
}; };
(from $base:ty => $func:ident ( $xx:ident, $yy:ident )) => { (from $base:ty => $func:ident ( $xx:ident, $yy:ident )) => {
return Some(|_, args| { Some(|_, args| {
let x = <$base>::from(args[0].$xx().expect(BUILTIN)); let x = <$base>::from(args[0].$xx().expect(BUILTIN));
let y = <$base>::from(args[1].$yy().expect(BUILTIN)); let y = <$base>::from(args[1].$yy().expect(BUILTIN));
$func(x, y).map(Into::<Dynamic>::into) $func(x, y).map(Into::<Dynamic>::into)
@ -152,7 +150,7 @@ pub fn get_builtin_binary_op_fn(
($x:ty, $xx:ident, $y:ty, $yy:ident) => { ($x:ty, $xx:ident, $y:ty, $yy:ident) => {
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) { if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) {
match op { return match op {
"+" => impl_op!(FLOAT => $xx + $yy), "+" => impl_op!(FLOAT => $xx + $yy),
"-" => impl_op!(FLOAT => $xx - $yy), "-" => impl_op!(FLOAT => $xx - $yy),
"*" => impl_op!(FLOAT => $xx * $yy), "*" => impl_op!(FLOAT => $xx * $yy),
@ -165,8 +163,8 @@ pub fn get_builtin_binary_op_fn(
">=" => impl_op!(FLOAT => $xx >= $yy), ">=" => impl_op!(FLOAT => $xx >= $yy),
"<" => impl_op!(FLOAT => $xx < $yy), "<" => impl_op!(FLOAT => $xx < $yy),
"<=" => impl_op!(FLOAT => $xx <= $yy), "<=" => impl_op!(FLOAT => $xx <= $yy),
_ => return None, _ => None,
} };
} }
}; };
} }
@ -179,41 +177,43 @@ pub fn get_builtin_binary_op_fn(
($x:ty, $xx:ident, $y:ty, $yy:ident) => { ($x:ty, $xx:ident, $y:ty, $yy:ident) => {
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) { if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) {
if cfg!(not(feature = "unBUILTIN")) { #[cfg(not(feature = "unchecked"))]
use crate::packages::arithmetic::decimal_functions::*; use crate::packages::arithmetic::decimal_functions::*;
match op { #[cfg(not(feature = "unchecked"))]
"+" => impl_op!(from Decimal => add($xx, $yy)), match op {
"-" => impl_op!(from Decimal => subtract($xx, $yy)), "+" => return impl_op!(from Decimal => add($xx, $yy)),
"*" => impl_op!(from Decimal => multiply($xx, $yy)), "-" => return impl_op!(from Decimal => subtract($xx, $yy)),
"/" => impl_op!(from Decimal => divide($xx, $yy)), "*" => return impl_op!(from Decimal => multiply($xx, $yy)),
"%" => impl_op!(from Decimal => modulo($xx, $yy)), "/" => return impl_op!(from Decimal => divide($xx, $yy)),
"**" => impl_op!(from Decimal => power($xx, $yy)), "%" => return impl_op!(from Decimal => modulo($xx, $yy)),
_ => () "**" => return impl_op!(from Decimal => power($xx, $yy)),
} _ => ()
} else {
use rust_decimal::MathematicalOps;
match op {
"+" => impl_op!(from Decimal => $xx + $yy),
"-" => impl_op!(from Decimal => $xx - $yy),
"*" => impl_op!(from Decimal => $xx * $yy),
"/" => impl_op!(from Decimal => $xx / $yy),
"%" => impl_op!(from Decimal => $xx % $yy),
"**" => impl_op!(from Decimal => $xx.powd($yy)),
_ => ()
}
} }
#[cfg(feature = "unchecked")]
use rust_decimal::MathematicalOps;
#[cfg(feature = "unchecked")]
match op { match op {
"+" => return impl_op!(from Decimal => $xx + $yy),
"-" => return impl_op!(from Decimal => $xx - $yy),
"*" => return impl_op!(from Decimal => $xx * $yy),
"/" => return impl_op!(from Decimal => $xx / $yy),
"%" => return impl_op!(from Decimal => $xx % $yy),
"**" => return impl_op!(from Decimal => $xx.powd($yy)),
_ => ()
}
return match op {
"==" => impl_op!(from Decimal => $xx == $yy), "==" => impl_op!(from Decimal => $xx == $yy),
"!=" => impl_op!(from Decimal => $xx != $yy), "!=" => impl_op!(from Decimal => $xx != $yy),
">" => impl_op!(from Decimal => $xx > $yy), ">" => impl_op!(from Decimal => $xx > $yy),
">=" => impl_op!(from Decimal => $xx >= $yy), ">=" => impl_op!(from Decimal => $xx >= $yy),
"<" => impl_op!(from Decimal => $xx < $yy), "<" => impl_op!(from Decimal => $xx < $yy),
"<=" => impl_op!(from Decimal => $xx <= $yy), "<=" => impl_op!(from Decimal => $xx <= $yy),
_ => return None _ => None
} };
} }
}; };
} }
@ -234,22 +234,20 @@ pub fn get_builtin_binary_op_fn(
(s1, s2) (s1, s2)
} }
match op { return match op {
"+" => { "+" => Some(|_, args| {
return Some(|_, args| { let x = args[0].as_char().expect(BUILTIN);
let x = args[0].as_char().expect(BUILTIN); let y = &*args[1].read_lock::<ImmutableString>().expect(BUILTIN);
let y = &*args[1].read_lock::<ImmutableString>().expect(BUILTIN); Ok(format!("{}{}", x, y).into())
Ok(format!("{}{}", x, y).into()) }),
})
}
"==" => impl_op!(get_s1s2(==)), "==" => impl_op!(get_s1s2(==)),
"!=" => impl_op!(get_s1s2(!=)), "!=" => impl_op!(get_s1s2(!=)),
">" => impl_op!(get_s1s2(>)), ">" => impl_op!(get_s1s2(>)),
">=" => impl_op!(get_s1s2(>=)), ">=" => impl_op!(get_s1s2(>=)),
"<" => impl_op!(get_s1s2(<)), "<" => impl_op!(get_s1s2(<)),
"<=" => impl_op!(get_s1s2(<=)), "<=" => impl_op!(get_s1s2(<=)),
_ => return None, _ => None,
} };
} }
// string op char // string op char
if types_pair == (TypeId::of::<ImmutableString>(), TypeId::of::<char>()) { if types_pair == (TypeId::of::<ImmutableString>(), TypeId::of::<char>()) {
@ -263,36 +261,30 @@ pub fn get_builtin_binary_op_fn(
(s1, s2) (s1, s2)
} }
match op { return match op {
"+" => { "+" => Some(|_, args| {
return Some(|_, args| { let x = &*args[0].read_lock::<ImmutableString>().expect(BUILTIN);
let x = &*args[0].read_lock::<ImmutableString>().expect(BUILTIN); let y = args[1].as_char().expect(BUILTIN);
let y = args[1].as_char().expect(BUILTIN); Ok((x + y).into())
Ok((x + y).into()) }),
}) "-" => Some(|_, args| {
} let x = &*args[0].read_lock::<ImmutableString>().expect(BUILTIN);
"-" => { let y = args[1].as_char().expect(BUILTIN);
return Some(|_, args| { Ok((x - y).into())
let x = &*args[0].read_lock::<ImmutableString>().expect(BUILTIN); }),
let y = args[1].as_char().expect(BUILTIN);
Ok((x - y).into())
})
}
"==" => impl_op!(get_s1s2(==)), "==" => impl_op!(get_s1s2(==)),
"!=" => impl_op!(get_s1s2(!=)), "!=" => impl_op!(get_s1s2(!=)),
">" => impl_op!(get_s1s2(>)), ">" => impl_op!(get_s1s2(>)),
">=" => impl_op!(get_s1s2(>=)), ">=" => impl_op!(get_s1s2(>=)),
"<" => impl_op!(get_s1s2(<)), "<" => impl_op!(get_s1s2(<)),
"<=" => impl_op!(get_s1s2(<=)), "<=" => impl_op!(get_s1s2(<=)),
OP_CONTAINS => { OP_CONTAINS => Some(|_, args| {
return Some(|_, args| { let s = &*args[0].read_lock::<ImmutableString>().expect(BUILTIN);
let s = &*args[0].read_lock::<ImmutableString>().expect(BUILTIN); let c = args[1].as_char().expect(BUILTIN);
let c = args[1].as_char().expect(BUILTIN); Ok((s.contains(c)).into())
Ok((s.contains(c)).into()) }),
}) _ => None,
} };
_ => return None,
}
} }
// map op string // map op string
@ -300,10 +292,10 @@ pub fn get_builtin_binary_op_fn(
if types_pair == (TypeId::of::<crate::Map>(), TypeId::of::<ImmutableString>()) { if types_pair == (TypeId::of::<crate::Map>(), TypeId::of::<ImmutableString>()) {
use crate::Map; use crate::Map;
match op { return match op {
OP_CONTAINS => impl_op!(Map.contains_key(ImmutableString.as_str())), OP_CONTAINS => impl_op!(Map.contains_key(ImmutableString.as_str())),
_ => return None, _ => None,
} };
} }
// Default comparison operators for different types // Default comparison operators for different types
@ -318,35 +310,36 @@ pub fn get_builtin_binary_op_fn(
// Beyond here, type1 == type2 // Beyond here, type1 == type2
if type1 == TypeId::of::<INT>() { if type1 == TypeId::of::<INT>() {
if cfg!(not(feature = "unBUILTIN")) { #[cfg(not(feature = "unchecked"))]
use crate::packages::arithmetic::arith_basic::INT::functions::*; use crate::packages::arithmetic::arith_basic::INT::functions::*;
match op { #[cfg(not(feature = "unchecked"))]
"+" => impl_op!(INT => add(as_int, as_int)), match op {
"-" => impl_op!(INT => subtract(as_int, as_int)), "+" => return impl_op!(INT => add(as_int, as_int)),
"*" => impl_op!(INT => multiply(as_int, as_int)), "-" => return impl_op!(INT => subtract(as_int, as_int)),
"/" => impl_op!(INT => divide(as_int, as_int)), "*" => return impl_op!(INT => multiply(as_int, as_int)),
"%" => impl_op!(INT => modulo(as_int, as_int)), "/" => return impl_op!(INT => divide(as_int, as_int)),
"**" => impl_op!(INT => power(as_int, as_int)), "%" => return impl_op!(INT => modulo(as_int, as_int)),
">>" => impl_op!(INT => shift_right(as_int, as_int)), "**" => return impl_op!(INT => power(as_int, as_int)),
"<<" => impl_op!(INT => shift_left(as_int, as_int)), ">>" => return impl_op!(INT => shift_right(as_int, as_int)),
_ => (), "<<" => return impl_op!(INT => shift_left(as_int, as_int)),
} _ => (),
} else {
match op {
"+" => impl_op!(INT => as_int + as_int),
"-" => impl_op!(INT => as_int - as_int),
"*" => impl_op!(INT => as_int * as_int),
"/" => impl_op!(INT => as_int / as_int),
"%" => impl_op!(INT => as_int % as_int),
"**" => impl_op!(INT => as_int.pow(as_int as u32)),
">>" => impl_op!(INT => as_int >> as_int),
"<<" => impl_op!(INT => as_int << as_int),
_ => (),
}
} }
#[cfg(feature = "unchecked")]
match op { match op {
"+" => return impl_op!(INT => as_int + as_int),
"-" => return impl_op!(INT => as_int - as_int),
"*" => return impl_op!(INT => as_int * as_int),
"/" => return impl_op!(INT => as_int / as_int),
"%" => return impl_op!(INT => as_int % as_int),
"**" => return impl_op!(INT => as_int.pow(as_int as u32)),
">>" => return impl_op!(INT => as_int >> as_int),
"<<" => return impl_op!(INT => as_int << as_int),
_ => (),
}
return match op {
"==" => impl_op!(INT => as_int == as_int), "==" => impl_op!(INT => as_int == as_int),
"!=" => impl_op!(INT => as_int != as_int), "!=" => impl_op!(INT => as_int != as_int),
">" => impl_op!(INT => as_int > as_int), ">" => impl_op!(INT => as_int > as_int),
@ -356,12 +349,12 @@ pub fn get_builtin_binary_op_fn(
"&" => impl_op!(INT => as_int & as_int), "&" => impl_op!(INT => as_int & as_int),
"|" => impl_op!(INT => as_int | as_int), "|" => impl_op!(INT => as_int | as_int),
"^" => impl_op!(INT => as_int ^ as_int), "^" => impl_op!(INT => as_int ^ as_int),
_ => return None, _ => None,
} };
} }
if type1 == TypeId::of::<bool>() { if type1 == TypeId::of::<bool>() {
match op { return match op {
"==" => impl_op!(bool => as_bool == as_bool), "==" => impl_op!(bool => as_bool == as_bool),
"!=" => impl_op!(bool => as_bool != as_bool), "!=" => impl_op!(bool => as_bool != as_bool),
">" => impl_op!(bool => as_bool > as_bool), ">" => impl_op!(bool => as_bool > as_bool),
@ -371,12 +364,12 @@ pub fn get_builtin_binary_op_fn(
"&" => impl_op!(bool => as_bool & as_bool), "&" => impl_op!(bool => as_bool & as_bool),
"|" => impl_op!(bool => as_bool | as_bool), "|" => impl_op!(bool => as_bool | as_bool),
"^" => impl_op!(bool => as_bool ^ as_bool), "^" => impl_op!(bool => as_bool ^ as_bool),
_ => return None, _ => None,
} };
} }
if type1 == TypeId::of::<ImmutableString>() { if type1 == TypeId::of::<ImmutableString>() {
match op { return match op {
"+" => impl_op!(ImmutableString + ImmutableString), "+" => impl_op!(ImmutableString + ImmutableString),
"-" => impl_op!(ImmutableString - ImmutableString), "-" => impl_op!(ImmutableString - ImmutableString),
"==" => impl_op!(ImmutableString == ImmutableString), "==" => impl_op!(ImmutableString == ImmutableString),
@ -385,42 +378,38 @@ pub fn get_builtin_binary_op_fn(
">=" => impl_op!(ImmutableString >= ImmutableString), ">=" => impl_op!(ImmutableString >= ImmutableString),
"<" => impl_op!(ImmutableString < ImmutableString), "<" => impl_op!(ImmutableString < ImmutableString),
"<=" => impl_op!(ImmutableString <= ImmutableString), "<=" => impl_op!(ImmutableString <= ImmutableString),
OP_CONTAINS => { OP_CONTAINS => Some(|_, args| {
return Some(|_, args| { let s1 = &*args[0].read_lock::<ImmutableString>().expect(BUILTIN);
let s1 = &*args[0].read_lock::<ImmutableString>().expect(BUILTIN); let s2 = &*args[1].read_lock::<ImmutableString>().expect(BUILTIN);
let s2 = &*args[1].read_lock::<ImmutableString>().expect(BUILTIN); Ok((s1.contains(s2.as_str())).into())
Ok((s1.contains(s2.as_str())).into()) }),
}) _ => None,
} };
_ => return None,
}
} }
if type1 == TypeId::of::<char>() { if type1 == TypeId::of::<char>() {
match op { return match op {
"+" => { "+" => Some(|_, args| {
return Some(|_, args| { let x = args[0].as_char().expect(BUILTIN);
let x = args[0].as_char().expect(BUILTIN); let y = args[1].as_char().expect(BUILTIN);
let y = args[1].as_char().expect(BUILTIN); Ok(format!("{}{}", x, y).into())
Ok(format!("{}{}", x, y).into()) }),
})
}
"==" => impl_op!(char => as_char == as_char), "==" => impl_op!(char => as_char == as_char),
"!=" => impl_op!(char => as_char != as_char), "!=" => impl_op!(char => as_char != as_char),
">" => impl_op!(char => as_char > as_char), ">" => impl_op!(char => as_char > as_char),
">=" => impl_op!(char => as_char >= as_char), ">=" => impl_op!(char => as_char >= as_char),
"<" => impl_op!(char => as_char < as_char), "<" => impl_op!(char => as_char < as_char),
"<=" => impl_op!(char => as_char <= as_char), "<=" => impl_op!(char => as_char <= as_char),
_ => return None, _ => None,
} };
} }
if type1 == TypeId::of::<()>() { if type1 == TypeId::of::<()>() {
match op { return match op {
"==" => return Some(|_, _| Ok(Dynamic::TRUE)), "==" => Some(|_, _| Ok(Dynamic::TRUE)),
"!=" | ">" | ">=" | "<" | "<=" => return Some(|_, _| Ok(Dynamic::FALSE)), "!=" | ">" | ">=" | "<" | "<=" => Some(|_, _| Ok(Dynamic::FALSE)),
_ => return None, _ => None,
} };
} }
None None
@ -444,53 +433,53 @@ pub fn get_builtin_op_assignment_fn(
macro_rules! impl_op { macro_rules! impl_op {
($x:ty = x $op:tt $yy:ident) => { ($x:ty = x $op:tt $yy:ident) => {
return Some(|_, args| { Some(|_, args| {
let x = args[0].$yy().expect(BUILTIN); let x = args[0].$yy().expect(BUILTIN);
let y = args[1].$yy().expect(BUILTIN) as $x; let y = args[1].$yy().expect(BUILTIN) as $x;
Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x $op y).into()) Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x $op y).into())
}) })
}; };
($x:ident $op:tt $yy:ident) => { ($x:ident $op:tt $yy:ident) => {
return Some(|_, args| { Some(|_, args| {
let y = args[1].$yy().expect(BUILTIN) as $x; let y = args[1].$yy().expect(BUILTIN) as $x;
Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into())
}) })
}; };
($x:ident $op:tt $yy:ident as $yyy:ty) => { ($x:ident $op:tt $yy:ident as $yyy:ty) => {
return Some(|_, args| { Some(|_, args| {
let y = args[1].$yy().expect(BUILTIN) as $yyy; let y = args[1].$yy().expect(BUILTIN) as $yyy;
Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into())
}) })
}; };
($x:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty )) => { ($x:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty )) => {
return Some(|_, args| { Some(|_, args| {
let x = args[0].$xx().expect(BUILTIN); let x = args[0].$xx().expect(BUILTIN);
let y = args[1].$yy().expect(BUILTIN) as $x; let y = args[1].$yy().expect(BUILTIN) as $x;
Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x.$func(y as $yyy)).into()) Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x.$func(y as $yyy)).into())
}) })
}; };
($x:ty => $func:ident ( $xx:ident, $yy:ident )) => { ($x:ty => $func:ident ( $xx:ident, $yy:ident )) => {
return Some(|_, args| { Some(|_, args| {
let x = args[0].$xx().expect(BUILTIN); let x = args[0].$xx().expect(BUILTIN);
let y = args[1].$yy().expect(BUILTIN) as $x; let y = args[1].$yy().expect(BUILTIN) as $x;
Ok((*args[0].write_lock().expect(BUILTIN) = $func(x, y)?).into()) Ok((*args[0].write_lock().expect(BUILTIN) = $func(x, y)?).into())
}) })
}; };
(from $x:ident $op:tt $yy:ident) => { (from $x:ident $op:tt $yy:ident) => {
return Some(|_, args| { Some(|_, args| {
let y = <$x>::from(args[1].$yy().expect(BUILTIN)); let y = <$x>::from(args[1].$yy().expect(BUILTIN));
Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into())
}) })
}; };
(from $x:ty => $xx:ident . $func:ident ( $yy:ident )) => { (from $x:ty => $xx:ident . $func:ident ( $yy:ident )) => {
return Some(|_, args| { Some(|_, args| {
let x = args[0].$xx().expect(BUILTIN); let x = args[0].$xx().expect(BUILTIN);
let y = <$x>::from(args[1].$yy().expect(BUILTIN)); let y = <$x>::from(args[1].$yy().expect(BUILTIN));
Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x.$func(y)).into()) Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x.$func(y)).into())
}) })
}; };
(from $x:ty => $func:ident ( $xx:ident, $yy:ident )) => { (from $x:ty => $func:ident ( $xx:ident, $yy:ident )) => {
return Some(|_, args| { Some(|_, args| {
let x = args[0].$xx().expect(BUILTIN); let x = args[0].$xx().expect(BUILTIN);
let y = <$x>::from(args[1].$yy().expect(BUILTIN)); let y = <$x>::from(args[1].$yy().expect(BUILTIN));
Ok((*args[0].write_lock().expect(BUILTIN) = $func(x, y)?).into()) Ok((*args[0].write_lock().expect(BUILTIN) = $func(x, y)?).into())
@ -502,15 +491,15 @@ pub fn get_builtin_op_assignment_fn(
($x:ident, $xx:ident, $y:ty, $yy:ident) => { ($x:ident, $xx:ident, $y:ty, $yy:ident) => {
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) { if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) {
match op { return match op {
"+=" => impl_op!($x += $yy), "+=" => impl_op!($x += $yy),
"-=" => impl_op!($x -= $yy), "-=" => impl_op!($x -= $yy),
"*=" => impl_op!($x *= $yy), "*=" => impl_op!($x *= $yy),
"/=" => impl_op!($x /= $yy), "/=" => impl_op!($x /= $yy),
"%=" => impl_op!($x %= $yy), "%=" => impl_op!($x %= $yy),
"**=" => impl_op!($x => $xx.powf($yy as $x)), "**=" => impl_op!($x => $xx.powf($yy as $x)),
_ => return None, _ => None,
} };
} }
} }
} }
@ -522,31 +511,33 @@ pub fn get_builtin_op_assignment_fn(
($x:ident, $xx:ident, $y:ty, $yy:ident) => { ($x:ident, $xx:ident, $y:ty, $yy:ident) => {
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) { if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) {
if cfg!(not(feature = "unBUILTIN")) { #[cfg(not(feature = "unchecked"))]
use crate::packages::arithmetic::decimal_functions::*; use crate::packages::arithmetic::decimal_functions::*;
match op { #[cfg(not(feature = "unchecked"))]
"+=" => impl_op!(from $x => add($xx, $yy)), return match op {
"-=" => impl_op!(from $x => subtract($xx, $yy)), "+=" => impl_op!(from $x => add($xx, $yy)),
"*=" => impl_op!(from $x => multiply($xx, $yy)), "-=" => impl_op!(from $x => subtract($xx, $yy)),
"/=" => impl_op!(from $x => divide($xx, $yy)), "*=" => impl_op!(from $x => multiply($xx, $yy)),
"%=" => impl_op!(from $x => modulo($xx, $yy)), "/=" => impl_op!(from $x => divide($xx, $yy)),
"**=" => impl_op!(from $x => power($xx, $yy)), "%=" => impl_op!(from $x => modulo($xx, $yy)),
_ => return None, "**=" => impl_op!(from $x => power($xx, $yy)),
} _ => None,
} else { };
use rust_decimal::MathematicalOps;
match op { #[cfg(feature = "unchecked")]
"+=" => impl_op!(from $x += $yy), use rust_decimal::MathematicalOps;
"-=" => impl_op!(from $x -= $yy),
"*=" => impl_op!(from $x *= $yy), #[cfg(feature = "unchecked")]
"/=" => impl_op!(from $x /= $yy), return match op {
"%=" => impl_op!(from $x %= $yy), "+=" => impl_op!(from $x += $yy),
"**=" => impl_op!(from $x => $xx.powd($yy)), "-=" => impl_op!(from $x -= $yy),
_ => return None, "*=" => impl_op!(from $x *= $yy),
} "/=" => impl_op!(from $x /= $yy),
} "%=" => impl_op!(from $x %= $yy),
"**=" => impl_op!(from $x => $xx.powd($yy)),
_ => None,
};
} }
}; };
} }
@ -556,31 +547,29 @@ pub fn get_builtin_op_assignment_fn(
// string op= char // string op= char
if types_pair == (TypeId::of::<ImmutableString>(), TypeId::of::<char>()) { if types_pair == (TypeId::of::<ImmutableString>(), TypeId::of::<char>()) {
match op { return match op {
"+=" => impl_op!(ImmutableString += as_char as char), "+=" => impl_op!(ImmutableString += as_char as char),
"-=" => impl_op!(ImmutableString -= as_char as char), "-=" => impl_op!(ImmutableString -= as_char as char),
_ => return None, _ => None,
} };
} }
// char op= string // char op= string
if types_pair == (TypeId::of::<char>(), TypeId::of::<ImmutableString>()) { if types_pair == (TypeId::of::<char>(), TypeId::of::<ImmutableString>()) {
match op { return match op {
"+=" => { "+=" => Some(|_, args| {
return Some(|_, args| { let mut ch = args[0].as_char().expect(BUILTIN).to_string();
let mut ch = args[0].as_char().expect(BUILTIN).to_string(); ch.push_str(
ch.push_str( args[1]
args[1] .read_lock::<ImmutableString>()
.read_lock::<ImmutableString>() .expect(BUILTIN)
.expect(BUILTIN) .as_str(),
.as_str(), );
);
let mut x = args[0].write_lock::<Dynamic>().expect(BUILTIN); let mut x = args[0].write_lock::<Dynamic>().expect(BUILTIN);
Ok((*x = ch.into()).into()) Ok((*x = ch.into()).into())
}) }),
} _ => None,
_ => return None, };
}
} }
// No built-in op-assignments for different types. // No built-in op-assignments for different types.
@ -590,83 +579,78 @@ pub fn get_builtin_op_assignment_fn(
// Beyond here, type1 == type2 // Beyond here, type1 == type2
if type1 == TypeId::of::<INT>() { if type1 == TypeId::of::<INT>() {
if cfg!(not(feature = "unBUILTIN")) { #[cfg(not(feature = "unchecked"))]
use crate::packages::arithmetic::arith_basic::INT::functions::*; use crate::packages::arithmetic::arith_basic::INT::functions::*;
match op { #[cfg(not(feature = "unchecked"))]
"+=" => impl_op!(INT => add(as_int, as_int)), match op {
"-=" => impl_op!(INT => subtract(as_int, as_int)), "+=" => return impl_op!(INT => add(as_int, as_int)),
"*=" => impl_op!(INT => multiply(as_int, as_int)), "-=" => return impl_op!(INT => subtract(as_int, as_int)),
"/=" => impl_op!(INT => divide(as_int, as_int)), "*=" => return impl_op!(INT => multiply(as_int, as_int)),
"%=" => impl_op!(INT => modulo(as_int, as_int)), "/=" => return impl_op!(INT => divide(as_int, as_int)),
"**=" => impl_op!(INT => power(as_int, as_int)), "%=" => return impl_op!(INT => modulo(as_int, as_int)),
">>=" => impl_op!(INT => shift_right(as_int, as_int)), "**=" => return impl_op!(INT => power(as_int, as_int)),
"<<=" => impl_op!(INT => shift_left(as_int, as_int)), ">>=" => return impl_op!(INT => shift_right(as_int, as_int)),
_ => (), "<<=" => return impl_op!(INT => shift_left(as_int, as_int)),
} _ => (),
} else {
match op {
"+=" => impl_op!(INT += as_int),
"-=" => impl_op!(INT -= as_int),
"*=" => impl_op!(INT *= as_int),
"/=" => impl_op!(INT /= as_int),
"%=" => impl_op!(INT %= as_int),
"**=" => impl_op!(INT => as_int.pow(as_int as u32)),
">>=" => impl_op!(INT >>= as_int),
"<<=" => impl_op!(INT <<= as_int),
_ => (),
}
} }
#[cfg(feature = "unchecked")]
match op { match op {
"+=" => return impl_op!(INT += as_int),
"-=" => return impl_op!(INT -= as_int),
"*=" => return impl_op!(INT *= as_int),
"/=" => return impl_op!(INT /= as_int),
"%=" => return impl_op!(INT %= as_int),
"**=" => return impl_op!(INT => as_int.pow(as_int as u32)),
">>=" => return impl_op!(INT >>= as_int),
"<<=" => return impl_op!(INT <<= as_int),
_ => (),
}
return match op {
"&=" => impl_op!(INT &= as_int), "&=" => impl_op!(INT &= as_int),
"|=" => impl_op!(INT |= as_int), "|=" => impl_op!(INT |= as_int),
"^=" => impl_op!(INT ^= as_int), "^=" => impl_op!(INT ^= as_int),
_ => (), _ => None,
} };
} }
if type1 == TypeId::of::<bool>() { if type1 == TypeId::of::<bool>() {
match op { return match op {
"&=" => impl_op!(bool = x && as_bool), "&=" => impl_op!(bool = x && as_bool),
"|=" => impl_op!(bool = x || as_bool), "|=" => impl_op!(bool = x || as_bool),
_ => return None, _ => None,
} };
} }
if type1 == TypeId::of::<char>() { if type1 == TypeId::of::<char>() {
match op { return match op {
"+=" => { "+=" => Some(|_, args| {
return Some(|_, args| { let y = args[1].as_char().expect(BUILTIN);
let y = args[1].as_char().expect(BUILTIN); let mut x = args[0].write_lock::<Dynamic>().expect(BUILTIN);
let mut x = args[0].write_lock::<Dynamic>().expect(BUILTIN); Ok((*x = format!("{}{}", *x, y).into()).into())
Ok((*x = format!("{}{}", *x, y).into()).into()) }),
}) _ => None,
} };
_ => return None,
}
} }
if type1 == TypeId::of::<ImmutableString>() { if type1 == TypeId::of::<ImmutableString>() {
match op { return match op {
"+=" => { "+=" => Some(|_, args| {
return Some(|_, args| { let (first, second) = args.split_first_mut().expect(BUILTIN);
let (first, second) = args.split_first_mut().expect(BUILTIN); let mut x = first.write_lock::<ImmutableString>().expect(BUILTIN);
let mut x = first.write_lock::<ImmutableString>().expect(BUILTIN); let y = &*second[0].read_lock::<ImmutableString>().expect(BUILTIN);
let y = &*second[0].read_lock::<ImmutableString>().expect(BUILTIN); Ok((*x += y).into())
Ok((*x += y).into()) }),
}) "-=" => Some(|_, args| {
} let (first, second) = args.split_first_mut().expect(BUILTIN);
"-=" => { let mut x = first.write_lock::<ImmutableString>().expect(BUILTIN);
return Some(|_, args| { let y = &*second[0].read_lock::<ImmutableString>().expect(BUILTIN);
let (first, second) = args.split_first_mut().expect(BUILTIN); Ok((*x -= y).into())
let mut x = first.write_lock::<ImmutableString>().expect(BUILTIN); }),
let y = &*second[0].read_lock::<ImmutableString>().expect(BUILTIN); _ => None,
Ok((*x -= y).into()) };
})
}
_ => return None,
}
} }
None None

View File

@ -618,7 +618,7 @@ impl Engine {
state: &mut State, state: &mut State,
lib: &[&Module], lib: &[&Module],
fn_name: &str, fn_name: &str,
hash: FnCallHashes, hashes: FnCallHashes,
args: &mut FnCallArgs, args: &mut FnCallArgs,
is_ref: bool, is_ref: bool,
_is_method: bool, _is_method: bool,
@ -689,7 +689,7 @@ impl Engine {
// Scripted function call? // Scripted function call?
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
let hash_script = hash.script_hash(); let hash_script = hashes.script;
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
if let Some(f) = hash_script.and_then(|hash| { if let Some(f) = hash_script.and_then(|hash| {
@ -779,7 +779,7 @@ impl Engine {
} }
// Native function call // Native function call
let hash = hash.native_hash(); let hash = hashes.native;
self.call_native_fn(mods, state, lib, fn_name, hash, args, is_ref, false, pos) self.call_native_fn(mods, state, lib, fn_name, hash, args, is_ref, false, pos)
} }

View File

@ -444,11 +444,11 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
// if expr { if_block } else { else_block } // if expr { if_block } else { else_block }
Stmt::If(condition, x, _) => { Stmt::If(condition, x, _) => {
optimize_expr(condition, state, false); optimize_expr(condition, state, false);
let if_block = mem::take(x.0.statements()).into_vec(); let if_block = mem::take(x.0.statements_mut()).into_vec();
*x.0.statements() = *x.0.statements_mut() =
optimize_stmt_block(if_block, state, preserve_result, true, false).into(); optimize_stmt_block(if_block, state, preserve_result, true, false).into();
let else_block = mem::take(x.1.statements()).into_vec(); let else_block = mem::take(x.1.statements_mut()).into_vec();
*x.1.statements() = *x.1.statements_mut() =
optimize_stmt_block(else_block, state, preserve_result, true, false).into(); optimize_stmt_block(else_block, state, preserve_result, true, false).into();
} }
@ -520,8 +520,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
_ => { _ => {
block.0 = Some(condition); block.0 = Some(condition);
*block.1.statements() = optimize_stmt_block( *block.1.statements_mut() = optimize_stmt_block(
mem::take(block.1.statements()).into_vec(), mem::take(block.1.statements_mut()).into_vec(),
state, state,
preserve_result, preserve_result,
true, true,
@ -541,8 +541,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
x.0.remove(&key); x.0.remove(&key);
} }
let def_block = mem::take(x.1.statements()).into_vec(); let def_block = mem::take(x.1.statements_mut()).into_vec();
*x.1.statements() = *x.1.statements_mut() =
optimize_stmt_block(def_block, state, preserve_result, true, false).into(); optimize_stmt_block(def_block, state, preserve_result, true, false).into();
} }
@ -554,8 +554,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
// while expr { block } // while expr { block }
Stmt::While(condition, body, _) => { Stmt::While(condition, body, _) => {
optimize_expr(condition, state, false); optimize_expr(condition, state, false);
let block = mem::take(body.statements()).into_vec(); let block = mem::take(body.statements_mut()).into_vec();
*body.statements() = optimize_stmt_block(block, state, false, true, false).into(); *body.statements_mut() = optimize_stmt_block(block, state, false, true, false).into();
if body.len() == 1 { if body.len() == 1 {
match body[0] { match body[0] {
@ -582,7 +582,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
| Stmt::Do(body, Expr::BoolConstant(false, _), true, _) => { | Stmt::Do(body, Expr::BoolConstant(false, _), true, _) => {
state.set_dirty(); state.set_dirty();
let block_pos = body.position(); let block_pos = body.position();
let block = mem::take(body.statements()).into_vec(); let block = mem::take(body.statements_mut()).into_vec();
*stmt = Stmt::Block( *stmt = Stmt::Block(
optimize_stmt_block(block, state, false, true, false).into_boxed_slice(), optimize_stmt_block(block, state, false, true, false).into_boxed_slice(),
block_pos, block_pos,
@ -591,14 +591,14 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
// do { block } while|until expr // do { block } while|until expr
Stmt::Do(body, condition, _, _) => { Stmt::Do(body, condition, _, _) => {
optimize_expr(condition, state, false); optimize_expr(condition, state, false);
let block = mem::take(body.statements()).into_vec(); let block = mem::take(body.statements_mut()).into_vec();
*body.statements() = optimize_stmt_block(block, state, false, true, false).into(); *body.statements_mut() = optimize_stmt_block(block, state, false, true, false).into();
} }
// for id in expr { block } // for id in expr { block }
Stmt::For(iterable, x, _) => { Stmt::For(iterable, x, _) => {
optimize_expr(iterable, state, false); optimize_expr(iterable, state, false);
let body = mem::take(x.2.statements()).into_vec(); let body = mem::take(x.2.statements_mut()).into_vec();
*x.2.statements() = optimize_stmt_block(body, state, false, true, false).into(); *x.2.statements_mut() = optimize_stmt_block(body, state, false, true, false).into();
} }
// let id = expr; // let id = expr;
Stmt::Let(expr, _, _, _) => optimize_expr(expr, state, false), Stmt::Let(expr, _, _, _) => optimize_expr(expr, state, false),
@ -636,10 +636,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
} }
// try { try_block } catch ( var ) { catch_block } // try { try_block } catch ( var ) { catch_block }
Stmt::TryCatch(x, _, _) => { Stmt::TryCatch(x, _, _) => {
let try_block = mem::take(x.0.statements()).into_vec(); let try_block = mem::take(x.0.statements_mut()).into_vec();
*x.0.statements() = optimize_stmt_block(try_block, state, false, true, false).into(); *x.0.statements_mut() =
let catch_block = mem::take(x.2.statements()).into_vec(); optimize_stmt_block(try_block, state, false, true, false).into();
*x.2.statements() = optimize_stmt_block(catch_block, state, false, true, false).into(); let catch_block = mem::take(x.2.statements_mut()).into_vec();
*x.2.statements_mut() =
optimize_stmt_block(catch_block, state, false, true, false).into();
} }
// func(...) // func(...)
Stmt::Expr(expr @ Expr::FnCall(_, _)) => { Stmt::Expr(expr @ Expr::FnCall(_, _)) => {
@ -686,7 +688,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State, _chaining: bool) {
Expr::Stmt(x) if x.is_empty() => { state.set_dirty(); *expr = Expr::Unit(x.position()) } Expr::Stmt(x) if x.is_empty() => { state.set_dirty(); *expr = Expr::Unit(x.position()) }
// { stmt; ... } - do not count promotion as dirty because it gets turned back into an array // { stmt; ... } - do not count promotion as dirty because it gets turned back into an array
Expr::Stmt(x) => { Expr::Stmt(x) => {
*x.statements() = optimize_stmt_block(mem::take(x.statements()).into_vec(), state, true, true, false).into(); *x.statements_mut() = optimize_stmt_block(mem::take(x.statements_mut()).into_vec(), state, true, true, false).into();
// { Stmt(Expr) } - promote // { Stmt(Expr) } - promote
match x.as_mut().as_mut() { match x.as_mut().as_mut() {
@ -948,7 +950,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State, _chaining: bool) {
let arg_types: StaticVec<_> = arg_values.iter().map(Dynamic::type_id).collect(); let arg_types: StaticVec<_> = arg_values.iter().map(Dynamic::type_id).collect();
// Search for overloaded operators (can override built-in). // Search for overloaded operators (can override built-in).
if !has_native_fn(state, x.hashes.native_hash(), arg_types.as_ref()) { if !has_native_fn(state, x.hashes.native, arg_types.as_ref()) {
if let Some(mut result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1]) if let Some(mut result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
.and_then(|f| { .and_then(|f| {
let ctx = (state.engine, x.name.as_ref(), state.lib).into(); let ctx = (state.engine, x.name.as_ref(), state.lib).into();
@ -1136,9 +1138,9 @@ pub fn optimize_into_ast(
// Optimize the function body // Optimize the function body
let state = &mut State::new(engine, lib2, level); let state = &mut State::new(engine, lib2, level);
let body = mem::take(fn_def.body.statements()).into_vec(); let body = mem::take(fn_def.body.statements_mut()).into_vec();
*fn_def.body.statements() = *fn_def.body.statements_mut() =
optimize_stmt_block(body, state, true, true, true).into(); optimize_stmt_block(body, state, true, true, true).into();
fn_def fn_def

View File

@ -287,9 +287,8 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
{ {
reg_range!(lib | "range" => i8, u8, i16, u16, i32, u32, i64, u64); reg_range!(lib | "range" => i8, u8, i16, u16, i32, u32, i64, u64);
if cfg!(not(target_arch = "wasm32")) { #[cfg(not(target_arch = "wasm32"))]
reg_range!(lib | "range" => i128, u128); reg_range!(lib | "range" => i128, u128);
}
} }
reg_range!(lib | step "range" => INT); reg_range!(lib | step "range" => INT);
@ -299,9 +298,8 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
{ {
reg_range!(lib | step "range" => i8, u8, i16, u16, i32, u32, i64, u64); reg_range!(lib | step "range" => i8, u8, i16, u16, i32, u32, i64, u64);
if cfg!(not(target_arch = "wasm32")) { #[cfg(not(target_arch = "wasm32"))]
reg_range!(lib | step "range" => i128, u128); reg_range!(lib | step "range" => i128, u128);
}
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]

View File

@ -478,7 +478,7 @@ fn parse_index_chain(
let idx_expr = parse_expr(input, state, lib, settings.level_up())?; let idx_expr = parse_expr(input, state, lib, settings.level_up())?;
// Check type of indexing - must be integer or string // Check type of indexing - must be integer or string
match &idx_expr { match idx_expr {
Expr::IntegerConstant(_, pos) => match lhs { Expr::IntegerConstant(_, pos) => match lhs {
Expr::IntegerConstant(_, _) Expr::IntegerConstant(_, _)
| Expr::Array(_, _) | Expr::Array(_, _)
@ -489,7 +489,7 @@ fn parse_index_chain(
return Err(PERR::MalformedIndexExpr( return Err(PERR::MalformedIndexExpr(
"Object map access expects string index, not a number".into(), "Object map access expects string index, not a number".into(),
) )
.into_err(*pos)) .into_err(pos))
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
@ -1314,14 +1314,14 @@ fn parse_primary(
// Cache the hash key for namespace-qualified variables // Cache the hash key for namespace-qualified variables
match root_expr { match root_expr {
Expr::Variable(_, _, ref mut x) if x.1.is_some() => Some(x), Expr::Variable(_, _, ref mut x) if x.1.is_some() => Some(x.as_mut()),
Expr::Index(ref mut x, _) | Expr::Dot(ref mut x, _) => match &mut x.lhs { Expr::Index(ref mut x, _) | Expr::Dot(ref mut x, _) => match x.lhs {
Expr::Variable(_, _, x) if x.1.is_some() => Some(x), Expr::Variable(_, _, ref mut x) if x.1.is_some() => Some(x.as_mut()),
_ => None, _ => None,
}, },
_ => None, _ => None,
} }
.map(|x| match x.as_mut() { .map(|x| match x {
(_, Some((hash, namespace)), name) => { (_, Some((hash, namespace)), name) => {
*hash = calc_qualified_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0); *hash = calc_qualified_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0);
@ -1467,17 +1467,17 @@ fn make_assignment_stmt<'a>(
let op_info = op.map(|v| OpAssignment::new(v)); let op_info = op.map(|v| OpAssignment::new(v));
match &lhs { match lhs {
// const_expr = rhs // const_expr = rhs
expr if expr.is_constant() => { ref expr if expr.is_constant() => {
Err(PERR::AssignmentToConstant("".into()).into_err(lhs.position())) Err(PERR::AssignmentToConstant("".into()).into_err(lhs.position()))
} }
// var (non-indexed) = rhs // var (non-indexed) = rhs
Expr::Variable(None, _, x) if x.0.is_none() => { Expr::Variable(None, _, ref x) if x.0.is_none() => {
Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos)) Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos))
} }
// var (indexed) = rhs // var (indexed) = rhs
Expr::Variable(i, var_pos, x) => { Expr::Variable(i, var_pos, ref x) => {
let (index, _, name) = x.as_ref(); let (index, _, name) = x.as_ref();
let index = i.map_or_else( let index = i.map_or_else(
|| { || {
@ -1495,20 +1495,20 @@ fn make_assignment_stmt<'a>(
} }
// Constant values cannot be assigned to // Constant values cannot be assigned to
AccessMode::ReadOnly => { AccessMode::ReadOnly => {
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*var_pos)) Err(PERR::AssignmentToConstant(name.to_string()).into_err(var_pos))
} }
} }
} }
// xxx[???]... = rhs, xxx.prop... = rhs // xxx[???]... = rhs, xxx.prop... = rhs
Expr::Index(x, _) | Expr::Dot(x, _) => { Expr::Index(ref x, _) | Expr::Dot(ref x, _) => {
match check_lvalue(&x.rhs, matches!(lhs, Expr::Dot(_, _))) { match check_lvalue(&x.rhs, matches!(lhs, Expr::Dot(_, _))) {
None => match &x.lhs { None => match x.lhs {
// var[???] = rhs, var.??? = rhs // var[???] = rhs, var.??? = rhs
Expr::Variable(_, _, _) => { Expr::Variable(_, _, _) => {
Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos)) Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos))
} }
// expr[???] = rhs, expr.??? = rhs // expr[???] = rhs, expr.??? = rhs
expr => { ref expr => {
Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(expr.position())) Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(expr.position()))
} }
}, },
@ -2993,7 +2993,7 @@ fn parse_anon_fn(
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
let mut params: StaticVec<_> = Default::default(); let mut params_list: StaticVec<_> = Default::default();
if input.next().expect(NEVER_ENDS).0 != Token::Or { if input.next().expect(NEVER_ENDS).0 != Token::Or {
if !match_token(input, Token::Pipe).0 { if !match_token(input, Token::Pipe).0 {
@ -3001,12 +3001,12 @@ fn parse_anon_fn(
match input.next().expect(NEVER_ENDS) { match input.next().expect(NEVER_ENDS) {
(Token::Pipe, _) => break, (Token::Pipe, _) => break,
(Token::Identifier(s), pos) => { (Token::Identifier(s), pos) => {
if params.iter().any(|(p, _)| p == &s) { if params_list.iter().any(|(p, _)| p == &s) {
return Err(PERR::FnDuplicatedParam("".to_string(), s).into_err(pos)); return Err(PERR::FnDuplicatedParam("".to_string(), s).into_err(pos));
} }
let s = state.get_identifier(s); let s = state.get_identifier(s);
state.stack.push((s.clone(), AccessMode::ReadWrite)); state.stack.push((s.clone(), AccessMode::ReadWrite));
params.push((s, pos)) params_list.push((s, pos))
} }
(Token::LexError(err), pos) => return Err(err.into_err(pos)), (Token::LexError(err), pos) => return Err(err.into_err(pos)),
(_, pos) => { (_, pos) => {
@ -3040,29 +3040,26 @@ fn parse_anon_fn(
// External variables may need to be processed in a consistent order, // External variables may need to be processed in a consistent order,
// so extract them into a list. // so extract them into a list.
let externals: StaticVec<Identifier> = { #[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "no_closure"))] let externals: StaticVec<Identifier> = state
{ .external_vars
state .iter()
.external_vars .map(|(name, _)| name.clone())
.iter() .collect();
.map(|(name, _)| name.clone())
.collect()
}
#[cfg(feature = "no_closure")]
Default::default()
};
let mut params: StaticVec<_> = if cfg!(not(feature = "no_closure")) { let mut params = StaticVec::with_capacity(
externals params_list.len()
.iter() + if cfg!(not(feature = "no_closure")) {
.cloned() externals.len()
.chain(params.into_iter().map(|(v, _)| v)) } else {
.collect() 0
} else { },
params.into_iter().map(|(v, _)| v).collect() );
};
params.shrink_to_fit(); #[cfg(not(feature = "no_closure"))]
params.extend(externals.iter().cloned());
params.extend(params_list.into_iter().map(|(v, _)| v));
// Create unique function name by hashing the script body plus the parameters. // Create unique function name by hashing the script body plus the parameters.
let hasher = &mut get_hasher(); let hasher = &mut get_hasher();