Revise built-in macros.

This commit is contained in:
Stephen Chung 2022-12-26 11:46:11 +08:00
parent 52d23522e6
commit d47bfa431a
3 changed files with 181 additions and 181 deletions

View File

@ -140,14 +140,14 @@ impl Engine {
let args = &mut [&mut *lock_guard, &mut new_val];
if self.fast_operators() {
if let Some((func, ctx)) =
if let Some((func, need_context)) =
get_builtin_op_assignment_fn(op_assign_token.clone(), args[0], args[1])
{
// Built-in found
let op = op_assign_token.literal_syntax();
auto_restore! { let orig_level = global.level; global.level += 1 }
let context = if ctx {
let context = if need_context {
Some((self, op, None, &*global, *op_pos).into())
} else {
None

View File

@ -91,65 +91,65 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
let type2 = y.type_id();
macro_rules! impl_op {
($xx:ident $op:tt $yy:ident) => { (|_, args| {
($xx:ident $op:tt $yy:ident) => { Some((|_, args| {
let x = &*args[0].read_lock::<$xx>().unwrap();
let y = &*args[1].read_lock::<$yy>().unwrap();
Ok((x $op y).into())
}, false) };
($xx:ident . $func:ident ( $yy:ty )) => { (|_, args| {
}, false)) };
($xx:ident . $func:ident ( $yy:ty )) => { Some((|_, args| {
let x = &*args[0].read_lock::<$xx>().unwrap();
let y = &*args[1].read_lock::<$yy>().unwrap();
Ok(x.$func(y).into())
}, false) };
($xx:ident . $func:ident ( $yy:ident . $yyy:ident () )) => { (|_, args| {
}, false)) };
($xx:ident . $func:ident ( $yy:ident . $yyy:ident () )) => { Some((|_, args| {
let x = &*args[0].read_lock::<$xx>().unwrap();
let y = &*args[1].read_lock::<$yy>().unwrap();
Ok(x.$func(y.$yyy()).into())
}, false) };
($func:ident ( $op:tt )) => { (|_, args| {
}, false)) };
($func:ident ( $op:tt )) => { Some((|_, args| {
let (x, y) = $func(args);
Ok((x $op y).into())
}, false) };
($base:ty => $xx:ident $op:tt $yy:ident) => { (|_, args| {
}, false)) };
($base:ty => $xx:ident $op:tt $yy:ident) => { Some((|_, args| {
let x = args[0].$xx().unwrap() as $base;
let y = args[1].$yy().unwrap() as $base;
Ok((x $op y).into())
}, false) };
($base:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty)) => { (|_, args| {
}, false)) };
($base:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty)) => { Some((|_, args| {
let x = args[0].$xx().unwrap() as $base;
let y = args[1].$yy().unwrap() as $base;
Ok(x.$func(y as $yyy).into())
}, false) };
($base:ty => Ok($func:ident ( $xx:ident, $yy:ident ))) => { (|_, args| {
}, false)) };
($base:ty => Ok($func:ident ( $xx:ident, $yy:ident ))) => { Some((|_, args| {
let x = args[0].$xx().unwrap() as $base;
let y = args[1].$yy().unwrap() as $base;
Ok($func(x, y).into())
}, false) };
($base:ty => $func:ident ( $xx:ident, $yy:ident )) => { (|_, args| {
}, false)) };
($base:ty => $func:ident ( $xx:ident, $yy:ident )) => { Some((|_, args| {
let x = args[0].$xx().unwrap() as $base;
let y = args[1].$yy().unwrap() as $base;
$func(x, y).map(Into::into)
}, false) };
(from $base:ty => $xx:ident $op:tt $yy:ident) => { (|_, args| {
}, false)) };
(from $base:ty => $xx:ident $op:tt $yy:ident) => { Some((|_, args| {
let x = <$base>::from(args[0].$xx().unwrap());
let y = <$base>::from(args[1].$yy().unwrap());
Ok((x $op y).into())
}, false) };
(from $base:ty => $xx:ident . $func:ident ( $yy:ident )) => { (|_, args| {
}, false)) };
(from $base:ty => $xx:ident . $func:ident ( $yy:ident )) => { Some((|_, args| {
let x = <$base>::from(args[0].$xx().unwrap());
let y = <$base>::from(args[1].$yy().unwrap());
Ok(x.$func(y).into())
}, false) };
(from $base:ty => Ok($func:ident ( $xx:ident, $yy:ident ))) => { (|_, args| {
}, false)) };
(from $base:ty => Ok($func:ident ( $xx:ident, $yy:ident ))) => { Some((|_, args| {
let x = <$base>::from(args[0].$xx().unwrap());
let y = <$base>::from(args[1].$yy().unwrap());
Ok($func(x, y).into())
}, false) };
(from $base:ty => $func:ident ( $xx:ident, $yy:ident )) => { (|_, args| {
}, false)) };
(from $base:ty => $func:ident ( $xx:ident, $yy:ident )) => { Some((|_, args| {
let x = <$base>::from(args[0].$xx().unwrap());
let y = <$base>::from(args[1].$yy().unwrap());
$func(x, y).map(Into::into)
}, false) };
}, false)) };
}
// Check for common patterns
@ -161,25 +161,25 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
#[cfg(not(feature = "unchecked"))]
match op {
Plus => return Some(impl_op!(INT => add(as_int, as_int))),
Minus => return Some(impl_op!(INT => subtract(as_int, as_int))),
Multiply => return Some(impl_op!(INT => multiply(as_int, as_int))),
Divide => return Some(impl_op!(INT => divide(as_int, as_int))),
Modulo => return Some(impl_op!(INT => modulo(as_int, as_int))),
PowerOf => return Some(impl_op!(INT => power(as_int, as_int))),
RightShift => return Some(impl_op!(INT => Ok(shift_right(as_int, as_int)))),
LeftShift => return Some(impl_op!(INT => Ok(shift_left(as_int, as_int)))),
Plus => return impl_op!(INT => add(as_int, as_int)),
Minus => return impl_op!(INT => subtract(as_int, as_int)),
Multiply => return impl_op!(INT => multiply(as_int, as_int)),
Divide => return impl_op!(INT => divide(as_int, as_int)),
Modulo => return impl_op!(INT => modulo(as_int, as_int)),
PowerOf => return impl_op!(INT => power(as_int, as_int)),
RightShift => return impl_op!(INT => Ok(shift_right(as_int, as_int))),
LeftShift => return impl_op!(INT => Ok(shift_left(as_int, as_int))),
_ => (),
}
#[cfg(feature = "unchecked")]
match op {
Plus => return Some(impl_op!(INT => as_int + as_int)),
Minus => return Some(impl_op!(INT => as_int - as_int)),
Multiply => return Some(impl_op!(INT => as_int * as_int)),
Divide => return Some(impl_op!(INT => as_int / as_int)),
Modulo => return Some(impl_op!(INT => as_int % as_int)),
PowerOf => return Some(impl_op!(INT => as_int.pow(as_int as u32))),
Plus => return impl_op!(INT => as_int + as_int),
Minus => return impl_op!(INT => as_int - as_int),
Multiply => return impl_op!(INT => as_int * as_int),
Divide => return impl_op!(INT => as_int / as_int),
Modulo => return impl_op!(INT => as_int % as_int),
PowerOf => return impl_op!(INT => as_int.pow(as_int as u32)),
RightShift => {
return Some((
|_, args| {
@ -204,32 +204,32 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
}
return match op {
EqualsTo => Some(impl_op!(INT => as_int == as_int)),
NotEqualsTo => Some(impl_op!(INT => as_int != as_int)),
GreaterThan => Some(impl_op!(INT => as_int > as_int)),
GreaterThanEqualsTo => Some(impl_op!(INT => as_int >= as_int)),
LessThan => Some(impl_op!(INT => as_int < as_int)),
LessThanEqualsTo => Some(impl_op!(INT => as_int <= as_int)),
Ampersand => Some(impl_op!(INT => as_int & as_int)),
Pipe => Some(impl_op!(INT => as_int | as_int)),
XOr => Some(impl_op!(INT => as_int ^ as_int)),
ExclusiveRange => Some(impl_op!(INT => as_int .. as_int)),
InclusiveRange => Some(impl_op!(INT => as_int ..= as_int)),
EqualsTo => impl_op!(INT => as_int == as_int),
NotEqualsTo => impl_op!(INT => as_int != as_int),
GreaterThan => impl_op!(INT => as_int > as_int),
GreaterThanEqualsTo => impl_op!(INT => as_int >= as_int),
LessThan => impl_op!(INT => as_int < as_int),
LessThanEqualsTo => impl_op!(INT => as_int <= as_int),
Ampersand => impl_op!(INT => as_int & as_int),
Pipe => impl_op!(INT => as_int | as_int),
XOr => impl_op!(INT => as_int ^ as_int),
ExclusiveRange => impl_op!(INT => as_int .. as_int),
InclusiveRange => impl_op!(INT => as_int ..= as_int),
_ => None,
};
}
if type1 == TypeId::of::<bool>() {
return match op {
EqualsTo => Some(impl_op!(bool => as_bool == as_bool)),
NotEqualsTo => Some(impl_op!(bool => as_bool != as_bool)),
GreaterThan => Some(impl_op!(bool => as_bool > as_bool)),
GreaterThanEqualsTo => Some(impl_op!(bool => as_bool >= as_bool)),
LessThan => Some(impl_op!(bool => as_bool < as_bool)),
LessThanEqualsTo => Some(impl_op!(bool => as_bool <= as_bool)),
Ampersand => Some(impl_op!(bool => as_bool & as_bool)),
Pipe => Some(impl_op!(bool => as_bool | as_bool)),
XOr => Some(impl_op!(bool => as_bool ^ as_bool)),
EqualsTo => impl_op!(bool => as_bool == as_bool),
NotEqualsTo => impl_op!(bool => as_bool != as_bool),
GreaterThan => impl_op!(bool => as_bool > as_bool),
GreaterThanEqualsTo => impl_op!(bool => as_bool >= as_bool),
LessThan => impl_op!(bool => as_bool < as_bool),
LessThanEqualsTo => impl_op!(bool => as_bool <= as_bool),
Ampersand => impl_op!(bool => as_bool & as_bool),
Pipe => impl_op!(bool => as_bool | as_bool),
XOr => impl_op!(bool => as_bool ^ as_bool),
_ => None,
};
}
@ -250,13 +250,13 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
},
CHECKED_BUILD,
)),
Minus => Some(impl_op!(ImmutableString - ImmutableString)),
EqualsTo => Some(impl_op!(ImmutableString == ImmutableString)),
NotEqualsTo => Some(impl_op!(ImmutableString != ImmutableString)),
GreaterThan => Some(impl_op!(ImmutableString > ImmutableString)),
GreaterThanEqualsTo => Some(impl_op!(ImmutableString >= ImmutableString)),
LessThan => Some(impl_op!(ImmutableString < ImmutableString)),
LessThanEqualsTo => Some(impl_op!(ImmutableString <= ImmutableString)),
Minus => impl_op!(ImmutableString - ImmutableString),
EqualsTo => impl_op!(ImmutableString == ImmutableString),
NotEqualsTo => impl_op!(ImmutableString != ImmutableString),
GreaterThan => impl_op!(ImmutableString > ImmutableString),
GreaterThanEqualsTo => impl_op!(ImmutableString >= ImmutableString),
LessThan => impl_op!(ImmutableString < ImmutableString),
LessThanEqualsTo => impl_op!(ImmutableString <= ImmutableString),
_ => None,
};
}
@ -279,12 +279,12 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
},
CHECKED_BUILD,
)),
EqualsTo => Some(impl_op!(char => as_char == as_char)),
NotEqualsTo => Some(impl_op!(char => as_char != as_char)),
GreaterThan => Some(impl_op!(char => as_char > as_char)),
GreaterThanEqualsTo => Some(impl_op!(char => as_char >= as_char)),
LessThan => Some(impl_op!(char => as_char < as_char)),
LessThanEqualsTo => Some(impl_op!(char => as_char <= as_char)),
EqualsTo => impl_op!(char => as_char == as_char),
NotEqualsTo => impl_op!(char => as_char != as_char),
GreaterThan => impl_op!(char => as_char > as_char),
GreaterThanEqualsTo => impl_op!(char => as_char >= as_char),
LessThan => impl_op!(char => as_char < as_char),
LessThanEqualsTo => impl_op!(char => as_char <= as_char),
_ => None,
};
}
@ -316,8 +316,8 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
},
CHECKED_BUILD,
)),
EqualsTo => Some(impl_op!(Blob == Blob)),
NotEqualsTo => Some(impl_op!(Blob != Blob)),
EqualsTo => impl_op!(Blob == Blob),
NotEqualsTo => impl_op!(Blob != Blob),
_ => None,
};
}
@ -338,18 +338,18 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
($x:ty, $xx:ident, $y:ty, $yy:ident) => {
if (type1, type2) == (TypeId::of::<$x>(), TypeId::of::<$y>()) {
return match op {
Plus => Some(impl_op!(FLOAT => $xx + $yy)),
Minus => Some(impl_op!(FLOAT => $xx - $yy)),
Multiply => Some(impl_op!(FLOAT => $xx * $yy)),
Divide => Some(impl_op!(FLOAT => $xx / $yy)),
Modulo => Some(impl_op!(FLOAT => $xx % $yy)),
PowerOf => Some(impl_op!(FLOAT => $xx.powf($yy as FLOAT))),
EqualsTo => Some(impl_op!(FLOAT => $xx == $yy)),
NotEqualsTo => Some(impl_op!(FLOAT => $xx != $yy)),
GreaterThan => Some(impl_op!(FLOAT => $xx > $yy)),
GreaterThanEqualsTo => Some(impl_op!(FLOAT => $xx >= $yy)),
LessThan => Some(impl_op!(FLOAT => $xx < $yy)),
LessThanEqualsTo => Some(impl_op!(FLOAT => $xx <= $yy)),
Plus => impl_op!(FLOAT => $xx + $yy),
Minus => impl_op!(FLOAT => $xx - $yy),
Multiply => impl_op!(FLOAT => $xx * $yy),
Divide => impl_op!(FLOAT => $xx / $yy),
Modulo => impl_op!(FLOAT => $xx % $yy),
PowerOf => impl_op!(FLOAT => $xx.powf($yy as FLOAT)),
EqualsTo => impl_op!(FLOAT => $xx == $yy),
NotEqualsTo => impl_op!(FLOAT => $xx != $yy),
GreaterThan => impl_op!(FLOAT => $xx > $yy),
GreaterThanEqualsTo => impl_op!(FLOAT => $xx >= $yy),
LessThan => impl_op!(FLOAT => $xx < $yy),
LessThanEqualsTo => impl_op!(FLOAT => $xx <= $yy),
_ => None,
};
}
@ -373,12 +373,12 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
#[cfg(not(feature = "unchecked"))]
match op {
Plus => return Some(impl_op!(from Decimal => add($xx, $yy))),
Minus => return Some(impl_op!(from Decimal => subtract($xx, $yy))),
Multiply => return Some(impl_op!(from Decimal => multiply($xx, $yy))),
Divide => return Some(impl_op!(from Decimal => divide($xx, $yy))),
Modulo => return Some(impl_op!(from Decimal => modulo($xx, $yy))),
PowerOf => return Some(impl_op!(from Decimal => power($xx, $yy))),
Plus => return impl_op!(from Decimal => add($xx, $yy)),
Minus => return impl_op!(from Decimal => subtract($xx, $yy)),
Multiply => return impl_op!(from Decimal => multiply($xx, $yy)),
Divide => return impl_op!(from Decimal => divide($xx, $yy)),
Modulo => return impl_op!(from Decimal => modulo($xx, $yy)),
PowerOf => return impl_op!(from Decimal => power($xx, $yy)),
_ => ()
}
@ -387,22 +387,22 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
#[cfg(feature = "unchecked")]
match op {
Plus => return Some(impl_op!(from Decimal => $xx + $yy)),
Minus => return Some(impl_op!(from Decimal => $xx - $yy)),
Multiply => return Some(impl_op!(from Decimal => $xx * $yy)),
Divide => return Some(impl_op!(from Decimal => $xx / $yy)),
Modulo => return Some(impl_op!(from Decimal => $xx % $yy)),
PowerOf => return Some(impl_op!(from Decimal => $xx.powd($yy))),
Plus => return impl_op!(from Decimal => $xx + $yy),
Minus => return impl_op!(from Decimal => $xx - $yy),
Multiply => return impl_op!(from Decimal => $xx * $yy),
Divide => return impl_op!(from Decimal => $xx / $yy),
Modulo => return impl_op!(from Decimal => $xx % $yy),
PowerOf => return impl_op!(from Decimal => $xx.powd($yy)),
_ => ()
}
return match op {
EqualsTo => Some(impl_op!(from Decimal => $xx == $yy)),
NotEqualsTo => Some(impl_op!(from Decimal => $xx != $yy)),
GreaterThan => Some(impl_op!(from Decimal => $xx > $yy)),
GreaterThanEqualsTo => Some(impl_op!(from Decimal => $xx >= $yy)),
LessThan => Some(impl_op!(from Decimal => $xx < $yy)),
LessThanEqualsTo => Some(impl_op!(from Decimal => $xx <= $yy)),
EqualsTo => impl_op!(from Decimal => $xx == $yy),
NotEqualsTo => impl_op!(from Decimal => $xx != $yy),
GreaterThan => impl_op!(from Decimal => $xx > $yy),
GreaterThanEqualsTo => impl_op!(from Decimal => $xx >= $yy),
LessThan => impl_op!(from Decimal => $xx < $yy),
LessThanEqualsTo => impl_op!(from Decimal => $xx <= $yy),
_ => None
};
}
@ -444,12 +444,12 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
},
CHECKED_BUILD,
)),
EqualsTo => Some(impl_op!(get_s1s2(==))),
NotEqualsTo => Some(impl_op!(get_s1s2(!=))),
GreaterThan => Some(impl_op!(get_s1s2(>))),
GreaterThanEqualsTo => Some(impl_op!(get_s1s2(>=))),
LessThan => Some(impl_op!(get_s1s2(<))),
LessThanEqualsTo => Some(impl_op!(get_s1s2(<=))),
EqualsTo => impl_op!(get_s1s2(==)),
NotEqualsTo => impl_op!(get_s1s2(!=)),
GreaterThan => impl_op!(get_s1s2(>)),
GreaterThanEqualsTo => impl_op!(get_s1s2(>=)),
LessThan => impl_op!(get_s1s2(<)),
LessThanEqualsTo => impl_op!(get_s1s2(<=)),
_ => None,
};
}
@ -486,12 +486,12 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
},
false,
)),
EqualsTo => Some(impl_op!(get_s1s2(==))),
NotEqualsTo => Some(impl_op!(get_s1s2(!=))),
GreaterThan => Some(impl_op!(get_s1s2(>))),
GreaterThanEqualsTo => Some(impl_op!(get_s1s2(>=))),
LessThan => Some(impl_op!(get_s1s2(<))),
LessThanEqualsTo => Some(impl_op!(get_s1s2(<=))),
EqualsTo => impl_op!(get_s1s2(==)),
NotEqualsTo => impl_op!(get_s1s2(!=)),
GreaterThan => impl_op!(get_s1s2(>)),
GreaterThanEqualsTo => impl_op!(get_s1s2(>=)),
LessThan => impl_op!(get_s1s2(<)),
LessThanEqualsTo => impl_op!(get_s1s2(<=)),
_ => None,
};
}
@ -568,16 +568,16 @@ pub fn get_builtin_binary_op_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Option<F
// Handle ranges here because ranges are implemented as custom type
if type1 == TypeId::of::<ExclusiveRange>() && type1 == type2 {
return match op {
EqualsTo => Some(impl_op!(ExclusiveRange == ExclusiveRange)),
NotEqualsTo => Some(impl_op!(ExclusiveRange != ExclusiveRange)),
EqualsTo => impl_op!(ExclusiveRange == ExclusiveRange),
NotEqualsTo => impl_op!(ExclusiveRange != ExclusiveRange),
_ => None,
};
}
if type1 == TypeId::of::<InclusiveRange>() && type1 == type2 {
return match op {
EqualsTo => Some(impl_op!(InclusiveRange == InclusiveRange)),
NotEqualsTo => Some(impl_op!(InclusiveRange != InclusiveRange)),
EqualsTo => impl_op!(InclusiveRange == InclusiveRange),
NotEqualsTo => impl_op!(InclusiveRange != InclusiveRange),
_ => None,
};
}
@ -626,54 +626,54 @@ pub fn get_builtin_op_assignment_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Opti
let type2 = y.type_id();
macro_rules! impl_op {
($x:ty = x $op:tt $yy:ident) => { (|_, args| {
($x:ty = x $op:tt $yy:ident) => { Some((|_, args| {
let x = args[0].$yy().unwrap();
let y = args[1].$yy().unwrap() as $x;
Ok((*args[0].write_lock::<$x>().unwrap() = x $op y).into())
}, false) };
($x:ident $op:tt $yy:ident) => { (|_, args| {
}, false)) };
($x:ident $op:tt $yy:ident) => { Some((|_, args| {
let y = args[1].$yy().unwrap() as $x;
Ok((*args[0].write_lock::<$x>().unwrap() $op y).into())
}, false) };
($x:ident $op:tt $yy:ident as $yyy:ty) => { (|_, args| {
}, false)) };
($x:ident $op:tt $yy:ident as $yyy:ty) => { Some((|_, args| {
let y = args[1].$yy().unwrap() as $yyy;
Ok((*args[0].write_lock::<$x>().unwrap() $op y).into())
}, false) };
($x:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty )) => { (|_, args| {
}, false)) };
($x:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty )) => { Some((|_, args| {
let x = args[0].$xx().unwrap();
let y = args[1].$yy().unwrap() as $x;
Ok((*args[0].write_lock::<$x>().unwrap() = x.$func(y as $yyy)).into())
}, false) };
($x:ty => Ok($func:ident ( $xx:ident, $yy:ident ))) => { (|_, args| {
}, false)) };
($x:ty => Ok($func:ident ( $xx:ident, $yy:ident ))) => { Some((|_, args| {
let x = args[0].$xx().unwrap();
let y = args[1].$yy().unwrap() as $x;
let v: Dynamic = $func(x, y).into();
Ok((*args[0].write_lock().unwrap() = v).into())
}, false) };
($x:ty => $func:ident ( $xx:ident, $yy:ident )) => { (|_, args| {
}, false)) };
($x:ty => $func:ident ( $xx:ident, $yy:ident )) => { Some((|_, args| {
let x = args[0].$xx().unwrap();
let y = args[1].$yy().unwrap() as $x;
Ok((*args[0].write_lock().unwrap() = $func(x, y)?).into())
}, false) };
(from $x:ident $op:tt $yy:ident) => { (|_, args| {
}, false)) };
(from $x:ident $op:tt $yy:ident) => { Some((|_, args| {
let y = <$x>::from(args[1].$yy().unwrap());
Ok((*args[0].write_lock::<$x>().unwrap() $op y).into())
}, false) };
(from $x:ty => $xx:ident . $func:ident ( $yy:ident )) => { (|_, args| {
}, false)) };
(from $x:ty => $xx:ident . $func:ident ( $yy:ident )) => { Some((|_, args| {
let x = args[0].$xx().unwrap();
let y = <$x>::from(args[1].$yy().unwrap());
Ok((*args[0].write_lock::<$x>().unwrap() = x.$func(y)).into())
}, false) };
(from $x:ty => Ok($func:ident ( $xx:ident, $yy:ident ))) => { (|_, args| {
}, false)) };
(from $x:ty => Ok($func:ident ( $xx:ident, $yy:ident ))) => { Some((|_, args| {
let x = args[0].$xx().unwrap();
let y = <$x>::from(args[1].$yy().unwrap());
Ok((*args[0].write_lock().unwrap() = $func(x, y).into()).into())
}, false) };
(from $x:ty => $func:ident ( $xx:ident, $yy:ident )) => { (|_, args| {
}, false)) };
(from $x:ty => $func:ident ( $xx:ident, $yy:ident )) => { Some((|_, args| {
let x = args[0].$xx().unwrap();
let y = <$x>::from(args[1].$yy().unwrap());
Ok((*args[0].write_lock().unwrap() = $func(x, y)?).into())
}, false) };
}, false)) };
}
// Check for common patterns
@ -685,25 +685,25 @@ pub fn get_builtin_op_assignment_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Opti
#[cfg(not(feature = "unchecked"))]
match op {
PlusAssign => return Some(impl_op!(INT => add(as_int, as_int))),
MinusAssign => return Some(impl_op!(INT => subtract(as_int, as_int))),
MultiplyAssign => return Some(impl_op!(INT => multiply(as_int, as_int))),
DivideAssign => return Some(impl_op!(INT => divide(as_int, as_int))),
ModuloAssign => return Some(impl_op!(INT => modulo(as_int, as_int))),
PowerOfAssign => return Some(impl_op!(INT => power(as_int, as_int))),
RightShiftAssign => return Some(impl_op!(INT => Ok(shift_right(as_int, as_int)))),
LeftShiftAssign => return Some(impl_op!(INT => Ok(shift_left(as_int, as_int)))),
PlusAssign => return impl_op!(INT => add(as_int, as_int)),
MinusAssign => return impl_op!(INT => subtract(as_int, as_int)),
MultiplyAssign => return impl_op!(INT => multiply(as_int, as_int)),
DivideAssign => return impl_op!(INT => divide(as_int, as_int)),
ModuloAssign => return impl_op!(INT => modulo(as_int, as_int)),
PowerOfAssign => return impl_op!(INT => power(as_int, as_int)),
RightShiftAssign => return impl_op!(INT => Ok(shift_right(as_int, as_int))),
LeftShiftAssign => return impl_op!(INT => Ok(shift_left(as_int, as_int))),
_ => (),
}
#[cfg(feature = "unchecked")]
match op {
PlusAssign => return Some(impl_op!(INT += as_int)),
MinusAssign => return Some(impl_op!(INT -= as_int)),
MultiplyAssign => return Some(impl_op!(INT *= as_int)),
DivideAssign => return Some(impl_op!(INT /= as_int)),
ModuloAssign => return Some(impl_op!(INT %= as_int)),
PowerOfAssign => return Some(impl_op!(INT => as_int.pow(as_int as u32))),
PlusAssign => return impl_op!(INT += as_int),
MinusAssign => return impl_op!(INT -= as_int),
MultiplyAssign => return impl_op!(INT *= as_int),
DivideAssign => return impl_op!(INT /= as_int),
ModuloAssign => return impl_op!(INT %= as_int),
PowerOfAssign => return impl_op!(INT => as_int.pow(as_int as u32)),
RightShiftAssign => {
return Some((
|_, args| {
@ -730,17 +730,17 @@ pub fn get_builtin_op_assignment_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Opti
}
return match op {
AndAssign => Some(impl_op!(INT &= as_int)),
OrAssign => Some(impl_op!(INT |= as_int)),
XOrAssign => Some(impl_op!(INT ^= as_int)),
AndAssign => impl_op!(INT &= as_int),
OrAssign => impl_op!(INT |= as_int),
XOrAssign => impl_op!(INT ^= as_int),
_ => None,
};
}
if type1 == TypeId::of::<bool>() {
return match op {
AndAssign => Some(impl_op!(bool = x && as_bool)),
OrAssign => Some(impl_op!(bool = x || as_bool)),
AndAssign => impl_op!(bool = x && as_bool),
OrAssign => impl_op!(bool = x || as_bool),
_ => None,
};
}
@ -861,12 +861,12 @@ pub fn get_builtin_op_assignment_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Opti
($x:ident, $xx:ident, $y:ty, $yy:ident) => {
if (type1, type2) == (TypeId::of::<$x>(), TypeId::of::<$y>()) {
return match op {
PlusAssign => Some(impl_op!($x += $yy)),
MinusAssign => Some(impl_op!($x -= $yy)),
MultiplyAssign => Some(impl_op!($x *= $yy)),
DivideAssign => Some(impl_op!($x /= $yy)),
ModuloAssign => Some(impl_op!($x %= $yy)),
PowerOfAssign => Some(impl_op!($x => $xx.powf($yy as $x))),
PlusAssign => impl_op!($x += $yy),
MinusAssign => impl_op!($x -= $yy),
MultiplyAssign => impl_op!($x *= $yy),
DivideAssign => impl_op!($x /= $yy),
ModuloAssign => impl_op!($x %= $yy),
PowerOfAssign => impl_op!($x => $xx.powf($yy as $x)),
_ => None,
};
}
@ -889,12 +889,12 @@ pub fn get_builtin_op_assignment_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Opti
#[cfg(not(feature = "unchecked"))]
return match op {
PlusAssign => Some(impl_op!(from $x => add($xx, $yy))),
MinusAssign => Some(impl_op!(from $x => subtract($xx, $yy))),
MultiplyAssign => Some(impl_op!(from $x => multiply($xx, $yy))),
DivideAssign => Some(impl_op!(from $x => divide($xx, $yy))),
ModuloAssign => Some(impl_op!(from $x => modulo($xx, $yy))),
PowerOfAssign => Some(impl_op!(from $x => power($xx, $yy))),
PlusAssign => impl_op!(from $x => add($xx, $yy)),
MinusAssign => impl_op!(from $x => subtract($xx, $yy)),
MultiplyAssign => impl_op!(from $x => multiply($xx, $yy)),
DivideAssign => impl_op!(from $x => divide($xx, $yy)),
ModuloAssign => impl_op!(from $x => modulo($xx, $yy)),
PowerOfAssign => impl_op!(from $x => power($xx, $yy)),
_ => None,
};
@ -903,12 +903,12 @@ pub fn get_builtin_op_assignment_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Opti
#[cfg(feature = "unchecked")]
return match op {
PlusAssign => Some(impl_op!(from $x += $yy)),
MinusAssign => Some(impl_op!(from $x -= $yy)),
MultiplyAssign => Some(impl_op!(from $x *= $yy)),
DivideAssign => Some(impl_op!(from $x /= $yy)),
ModuloAssign => Some(impl_op!(from $x %= $yy)),
PowerOfAssign => Some(impl_op!(from $x => $xx.powd($yy))),
PlusAssign => impl_op!(from $x += $yy),
MinusAssign => impl_op!(from $x -= $yy),
MultiplyAssign => impl_op!(from $x *= $yy),
DivideAssign => impl_op!(from $x /= $yy),
ModuloAssign => impl_op!(from $x %= $yy),
PowerOfAssign => impl_op!(from $x => $xx.powd($yy)),
_ => None,
};
}
@ -939,7 +939,7 @@ pub fn get_builtin_op_assignment_fn(op: Token, x: &Dynamic, y: &Dynamic) -> Opti
},
CHECKED_BUILD,
)),
MinusAssign => Some(impl_op!(ImmutableString -= as_char as char)),
MinusAssign => impl_op!(ImmutableString -= as_char as char),
_ => None,
};
}

View File

@ -1611,13 +1611,13 @@ impl Engine {
let operands = &mut [&mut lhs, &mut rhs];
if let Some((func, ctx)) =
if let Some((func, need_context)) =
get_builtin_binary_op_fn(op_token.clone(), operands[0], operands[1])
{
// Built-in found
auto_restore! { let orig_level = global.level; global.level += 1 }
let context = if ctx {
let context = if need_context {
Some((self, name.as_str(), None, &*global, pos).into())
} else {
None