Add short-circuits to op-assignments.
This commit is contained in:
parent
bb404a415d
commit
906ab3a295
@ -14,6 +14,7 @@ Bug fixes
|
|||||||
* Expressions such as `!inside` now parses correctly instead of as `!in` followed by `side`.
|
* Expressions such as `!inside` now parses correctly instead of as `!in` followed by `side`.
|
||||||
* Custom syntax starting with symbols now works correctly and no longer raises a parse error.
|
* Custom syntax starting with symbols now works correctly and no longer raises a parse error.
|
||||||
* Comparing different custom types now works correctly when the appropriate comparison operators are registered.
|
* Comparing different custom types now works correctly when the appropriate comparison operators are registered.
|
||||||
|
* Op-assignments to bit flags or bit ranges now work correctly.
|
||||||
|
|
||||||
Potentially breaking changes
|
Potentially breaking changes
|
||||||
----------------------------
|
----------------------------
|
||||||
|
122
src/eval/stmt.rs
122
src/eval/stmt.rs
@ -7,6 +7,7 @@ use crate::ast::{
|
|||||||
SwitchCasesCollection,
|
SwitchCasesCollection,
|
||||||
};
|
};
|
||||||
use crate::func::{get_builtin_op_assignment_fn, get_hasher};
|
use crate::func::{get_builtin_op_assignment_fn, get_hasher};
|
||||||
|
use crate::tokenizer::Token;
|
||||||
use crate::types::dynamic::{AccessMode, Union};
|
use crate::types::dynamic::{AccessMode, Union};
|
||||||
use crate::{Dynamic, Engine, RhaiResult, RhaiResultOf, Scope, ERR, INT};
|
use crate::{Dynamic, Engine, RhaiResult, RhaiResultOf, Scope, ERR, INT};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
@ -130,38 +131,117 @@ impl Engine {
|
|||||||
|
|
||||||
if let Some((hash_x, hash, op_x, op_x_str, op, op_str)) = op_info.get_op_assignment_info() {
|
if let Some((hash_x, hash, op_x, op_x_str, op, op_str)) = op_info.get_op_assignment_info() {
|
||||||
let mut lock_guard = target.write_lock::<Dynamic>().unwrap();
|
let mut lock_guard = target.write_lock::<Dynamic>().unwrap();
|
||||||
let args = &mut [&mut *lock_guard, &mut new_val];
|
let mut done = false;
|
||||||
|
|
||||||
|
// Short-circuit built-in op-assignments if under Fast Operators mode
|
||||||
if self.fast_operators() {
|
if self.fast_operators() {
|
||||||
if let Some((func, need_context)) =
|
#[allow(clippy::wildcard_imports)]
|
||||||
get_builtin_op_assignment_fn(op_x, args[0], args[1])
|
use Token::*;
|
||||||
{
|
|
||||||
// Built-in found
|
|
||||||
auto_restore! { let orig_level = global.level; global.level += 1 }
|
|
||||||
|
|
||||||
let context = need_context
|
done = true;
|
||||||
.then(|| (self, op_x_str, global.source(), &*global, pos).into());
|
|
||||||
return func(context, args).map(|_| ());
|
// For extremely simple primary data operations, do it directly
|
||||||
|
// to avoid the overhead of calling a function.
|
||||||
|
match (&mut lock_guard.0, &mut new_val.0) {
|
||||||
|
(Union::Bool(b1, ..), Union::Bool(b2, ..)) => match op_x {
|
||||||
|
AndAssign => *b1 = *b1 && *b2,
|
||||||
|
OrAssign => *b1 = *b1 || *b2,
|
||||||
|
XOrAssign => *b1 = *b1 ^ *b2,
|
||||||
|
_ => done = false,
|
||||||
|
},
|
||||||
|
(Union::Int(n1, ..), Union::Int(n2, ..)) => {
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
#[allow(clippy::wildcard_imports)]
|
||||||
|
use crate::packages::arithmetic::arith_basic::INT::functions::*;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
match op_x {
|
||||||
|
PlusAssign => {
|
||||||
|
*n1 = add(*n1, *n2).map_err(|err| err.fill_position(pos))?
|
||||||
|
}
|
||||||
|
MinusAssign => {
|
||||||
|
*n1 = subtract(*n1, *n2).map_err(|err| err.fill_position(pos))?
|
||||||
|
}
|
||||||
|
MultiplyAssign => {
|
||||||
|
*n1 = multiply(*n1, *n2).map_err(|err| err.fill_position(pos))?
|
||||||
|
}
|
||||||
|
DivideAssign => {
|
||||||
|
*n1 = divide(*n1, *n2).map_err(|err| err.fill_position(pos))?
|
||||||
|
}
|
||||||
|
ModuloAssign => {
|
||||||
|
*n1 = modulo(*n1, *n2).map_err(|err| err.fill_position(pos))?
|
||||||
|
}
|
||||||
|
_ => done = false,
|
||||||
|
}
|
||||||
|
#[cfg(feature = "unchecked")]
|
||||||
|
match op_x {
|
||||||
|
PlusAssign => *n1 += *n2,
|
||||||
|
MinusAssign => *n1 -= *n2,
|
||||||
|
MultiplyAssign => *n1 *= *n2,
|
||||||
|
DivideAssign => *n1 /= *n2,
|
||||||
|
ModuloAssign => *n1 %= *n2,
|
||||||
|
_ => done = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
(Union::Float(f1, ..), Union::Float(f2, ..)) => match op_x {
|
||||||
|
PlusAssign => **f1 += **f2,
|
||||||
|
MinusAssign => **f1 -= **f2,
|
||||||
|
MultiplyAssign => **f1 *= **f2,
|
||||||
|
DivideAssign => **f1 /= **f2,
|
||||||
|
ModuloAssign => **f1 %= **f2,
|
||||||
|
_ => done = false,
|
||||||
|
},
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
(Union::Float(f1, ..), Union::Int(n2, ..)) => match op_x {
|
||||||
|
PlusAssign => **f1 += *n2 as crate::FLOAT,
|
||||||
|
MinusAssign => **f1 -= *n2 as crate::FLOAT,
|
||||||
|
MultiplyAssign => **f1 *= *n2 as crate::FLOAT,
|
||||||
|
DivideAssign => **f1 /= *n2 as crate::FLOAT,
|
||||||
|
ModuloAssign => **f1 %= *n2 as crate::FLOAT,
|
||||||
|
_ => done = false,
|
||||||
|
},
|
||||||
|
_ => done = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !done {
|
||||||
|
if let Some((func, need_context)) =
|
||||||
|
get_builtin_op_assignment_fn(op_x, &*lock_guard, &new_val)
|
||||||
|
{
|
||||||
|
// We may not need to bump the level because built-in's do not need it.
|
||||||
|
//auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
|
|
||||||
|
let args = &mut [&mut *lock_guard, &mut new_val];
|
||||||
|
let context = need_context
|
||||||
|
.then(|| (self, op_x_str, global.source(), &*global, pos).into());
|
||||||
|
let _ = func(context, args).map_err(|err| err.fill_position(pos))?;
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let opx = Some(op_x);
|
if !done {
|
||||||
|
let opx = Some(op_x);
|
||||||
|
let args = &mut [&mut *lock_guard, &mut new_val];
|
||||||
|
|
||||||
match self.exec_native_fn_call(global, caches, op_x_str, opx, hash_x, args, true, pos) {
|
match self
|
||||||
Ok(_) => (),
|
.exec_native_fn_call(global, caches, op_x_str, opx, hash_x, args, true, pos)
|
||||||
Err(err) if matches!(*err, ERR::ErrorFunctionNotFound(ref f, ..) if f.starts_with(op_x_str)) =>
|
|
||||||
{
|
{
|
||||||
// Expand to `var = var op rhs`
|
Ok(_) => (),
|
||||||
let op = Some(op);
|
Err(err) if matches!(*err, ERR::ErrorFunctionNotFound(ref f, ..) if f.starts_with(op_x_str)) =>
|
||||||
|
{
|
||||||
|
// Expand to `var = var op rhs`
|
||||||
|
let op = Some(op);
|
||||||
|
|
||||||
*args[0] = self
|
*args[0] = self
|
||||||
.exec_native_fn_call(global, caches, op_str, op, hash, args, true, pos)?
|
.exec_native_fn_call(global, caches, op_str, op, hash, args, true, pos)?
|
||||||
.0;
|
.0;
|
||||||
|
}
|
||||||
|
Err(err) => return Err(err),
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err),
|
|
||||||
}
|
|
||||||
|
|
||||||
self.check_data_size(&*args[0], root.position())?;
|
self.check_data_size(&*args[0], root.position())?;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Normal assignment
|
// Normal assignment
|
||||||
match target {
|
match target {
|
||||||
|
@ -684,6 +684,7 @@ pub fn get_builtin_op_assignment_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Opt
|
|||||||
return match op {
|
return match op {
|
||||||
AndAssign => impl_op!(bool = x && as_bool),
|
AndAssign => impl_op!(bool = x && as_bool),
|
||||||
OrAssign => impl_op!(bool = x || as_bool),
|
OrAssign => impl_op!(bool = x || as_bool),
|
||||||
|
XOrAssign => impl_op!(bool = x ^ as_bool),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
180
src/func/call.rs
180
src/func/call.rs
@ -1547,6 +1547,9 @@ impl Engine {
|
|||||||
/// # Main Entry-Point (`FnCallExpr`)
|
/// # Main Entry-Point (`FnCallExpr`)
|
||||||
///
|
///
|
||||||
/// Evaluate a function call expression.
|
/// Evaluate a function call expression.
|
||||||
|
///
|
||||||
|
/// This method tries to short-circuit function resolution under Fast Operators mode if the
|
||||||
|
/// function call is an operator.
|
||||||
pub(crate) fn eval_fn_call_expr(
|
pub(crate) fn eval_fn_call_expr(
|
||||||
&self,
|
&self,
|
||||||
global: &mut GlobalRuntimeState,
|
global: &mut GlobalRuntimeState,
|
||||||
@ -1570,28 +1573,29 @@ impl Engine {
|
|||||||
let op_token = op_token.as_ref();
|
let op_token = op_token.as_ref();
|
||||||
|
|
||||||
// Short-circuit native unary operator call if under Fast Operators mode
|
// Short-circuit native unary operator call if under Fast Operators mode
|
||||||
if op_token == Some(&Token::Bang) && self.fast_operators() && args.len() == 1 {
|
if self.fast_operators() && args.len() == 1 && op_token == Some(&Token::Bang) {
|
||||||
let mut value = self
|
let mut value = self
|
||||||
.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), &args[0])?
|
.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), &args[0])?
|
||||||
.0
|
.0
|
||||||
.flatten();
|
.flatten();
|
||||||
|
|
||||||
match value.0 {
|
return match value.0 {
|
||||||
Union::Bool(b, ..) => return Ok((!b).into()),
|
Union::Bool(b, ..) => Ok((!b).into()),
|
||||||
_ => (),
|
_ => {
|
||||||
}
|
let operand = &mut [&mut value];
|
||||||
|
self.exec_fn_call(
|
||||||
return value.as_bool().map(|r| (!r).into()).or_else(|_| {
|
global, caches, None, name, op_token, *hashes, operand, false, false, pos,
|
||||||
let operand = &mut [&mut value];
|
)
|
||||||
self.exec_fn_call(
|
.map(|(v, ..)| v)
|
||||||
global, caches, None, name, op_token, *hashes, operand, false, false, pos,
|
}
|
||||||
)
|
};
|
||||||
.map(|(v, ..)| v)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Short-circuit native binary operator call if under Fast Operators mode
|
// Short-circuit native binary operator call if under Fast Operators mode
|
||||||
if op_token.is_some() && self.fast_operators() && args.len() == 2 {
|
if op_token.is_some() && self.fast_operators() && args.len() == 2 {
|
||||||
|
#[allow(clippy::wildcard_imports)]
|
||||||
|
use Token::*;
|
||||||
|
|
||||||
let mut lhs = self
|
let mut lhs = self
|
||||||
.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), &args[0])?
|
.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), &args[0])?
|
||||||
.0
|
.0
|
||||||
@ -1606,23 +1610,19 @@ impl Engine {
|
|||||||
// to avoid the overhead of calling a function.
|
// to avoid the overhead of calling a function.
|
||||||
match (&lhs.0, &rhs.0) {
|
match (&lhs.0, &rhs.0) {
|
||||||
(Union::Unit(..), Union::Unit(..)) => match op_token.unwrap() {
|
(Union::Unit(..), Union::Unit(..)) => match op_token.unwrap() {
|
||||||
Token::EqualsTo => return Ok(Dynamic::TRUE),
|
EqualsTo => return Ok(Dynamic::TRUE),
|
||||||
Token::NotEqualsTo
|
NotEqualsTo | GreaterThan | GreaterThanEqualsTo | LessThan
|
||||||
| Token::GreaterThan
|
| LessThanEqualsTo => return Ok(Dynamic::FALSE),
|
||||||
| Token::GreaterThanEqualsTo
|
|
||||||
| Token::LessThan
|
|
||||||
| Token::LessThanEqualsTo => return Ok(Dynamic::FALSE),
|
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
(Union::Bool(b1, ..), Union::Bool(b2, ..)) => match op_token.unwrap() {
|
(Union::Bool(b1, ..), Union::Bool(b2, ..)) => match op_token.unwrap() {
|
||||||
Token::EqualsTo => return Ok((*b1 == *b2).into()),
|
EqualsTo => return Ok((*b1 == *b2).into()),
|
||||||
Token::NotEqualsTo => return Ok((*b1 != *b2).into()),
|
NotEqualsTo => return Ok((*b1 != *b2).into()),
|
||||||
Token::GreaterThan
|
GreaterThan | GreaterThanEqualsTo | LessThan | LessThanEqualsTo => {
|
||||||
| Token::GreaterThanEqualsTo
|
return Ok(Dynamic::FALSE)
|
||||||
| Token::LessThan
|
}
|
||||||
| Token::LessThanEqualsTo => return Ok(Dynamic::FALSE),
|
Pipe => return Ok((*b1 || *b2).into()),
|
||||||
Token::Pipe => return Ok((*b1 || *b2).into()),
|
Ampersand => return Ok((*b1 && *b2).into()),
|
||||||
Token::Ampersand => return Ok((*b1 && *b2).into()),
|
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
(Union::Int(n1, ..), Union::Int(n2, ..)) => {
|
(Union::Int(n1, ..), Union::Int(n2, ..)) => {
|
||||||
@ -1632,87 +1632,87 @@ impl Engine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
match op_token.unwrap() {
|
match op_token.unwrap() {
|
||||||
Token::EqualsTo => return Ok((*n1 == *n2).into()),
|
EqualsTo => return Ok((*n1 == *n2).into()),
|
||||||
Token::NotEqualsTo => return Ok((*n1 != *n2).into()),
|
NotEqualsTo => return Ok((*n1 != *n2).into()),
|
||||||
Token::GreaterThan => return Ok((*n1 > *n2).into()),
|
GreaterThan => return Ok((*n1 > *n2).into()),
|
||||||
Token::GreaterThanEqualsTo => return Ok((*n1 >= *n2).into()),
|
GreaterThanEqualsTo => return Ok((*n1 >= *n2).into()),
|
||||||
Token::LessThan => return Ok((*n1 < *n2).into()),
|
LessThan => return Ok((*n1 < *n2).into()),
|
||||||
Token::LessThanEqualsTo => return Ok((*n1 <= *n2).into()),
|
LessThanEqualsTo => return Ok((*n1 <= *n2).into()),
|
||||||
Token::Plus => return add(*n1, *n2).map(Into::into),
|
Plus => return add(*n1, *n2).map(Into::into),
|
||||||
Token::Minus => return subtract(*n1, *n2).map(Into::into),
|
Minus => return subtract(*n1, *n2).map(Into::into),
|
||||||
Token::Multiply => return multiply(*n1, *n2).map(Into::into),
|
Multiply => return multiply(*n1, *n2).map(Into::into),
|
||||||
Token::Divide => return divide(*n1, *n2).map(Into::into),
|
Divide => return divide(*n1, *n2).map(Into::into),
|
||||||
Token::Modulo => return modulo(*n1, *n2).map(Into::into),
|
Modulo => return modulo(*n1, *n2).map(Into::into),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
#[cfg(feature = "unchecked")]
|
#[cfg(feature = "unchecked")]
|
||||||
match op_token.unwrap() {
|
match op_token.unwrap() {
|
||||||
Token::EqualsTo => return Ok((*n1 == *n2).into()),
|
EqualsTo => return Ok((*n1 == *n2).into()),
|
||||||
Token::NotEqualsTo => return Ok((*n1 != *n2).into()),
|
NotEqualsTo => return Ok((*n1 != *n2).into()),
|
||||||
Token::GreaterThan => return Ok((*n1 > *n2).into()),
|
GreaterThan => return Ok((*n1 > *n2).into()),
|
||||||
Token::GreaterThanEqualsTo => return Ok((*n1 >= *n2).into()),
|
GreaterThanEqualsTo => return Ok((*n1 >= *n2).into()),
|
||||||
Token::LessThan => return Ok((*n1 < *n2).into()),
|
LessThan => return Ok((*n1 < *n2).into()),
|
||||||
Token::LessThanEqualsTo => return Ok((*n1 <= *n2).into()),
|
LessThanEqualsTo => return Ok((*n1 <= *n2).into()),
|
||||||
Token::Plus => return Ok((*n1 + *n2).into()),
|
Plus => return Ok((*n1 + *n2).into()),
|
||||||
Token::Minus => return Ok((*n1 - *n2).into()),
|
Minus => return Ok((*n1 - *n2).into()),
|
||||||
Token::Multiply => return Ok((*n1 * *n2).into()),
|
Multiply => return Ok((*n1 * *n2).into()),
|
||||||
Token::Divide => return Ok((*n1 / *n2).into()),
|
Divide => return Ok((*n1 / *n2).into()),
|
||||||
Token::Modulo => return Ok((*n1 % *n2).into()),
|
Modulo => return Ok((*n1 % *n2).into()),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
(Union::Float(f1, ..), Union::Float(f2, ..)) => match op_token.unwrap() {
|
(Union::Float(f1, ..), Union::Float(f2, ..)) => match op_token.unwrap() {
|
||||||
Token::EqualsTo => return Ok((**f1 == **f2).into()),
|
EqualsTo => return Ok((**f1 == **f2).into()),
|
||||||
Token::NotEqualsTo => return Ok((**f1 != **f2).into()),
|
NotEqualsTo => return Ok((**f1 != **f2).into()),
|
||||||
Token::GreaterThan => return Ok((**f1 > **f2).into()),
|
GreaterThan => return Ok((**f1 > **f2).into()),
|
||||||
Token::GreaterThanEqualsTo => return Ok((**f1 >= **f2).into()),
|
GreaterThanEqualsTo => return Ok((**f1 >= **f2).into()),
|
||||||
Token::LessThan => return Ok((**f1 < **f2).into()),
|
LessThan => return Ok((**f1 < **f2).into()),
|
||||||
Token::LessThanEqualsTo => return Ok((**f1 <= **f2).into()),
|
LessThanEqualsTo => return Ok((**f1 <= **f2).into()),
|
||||||
Token::Plus => return Ok((**f1 + **f2).into()),
|
Plus => return Ok((**f1 + **f2).into()),
|
||||||
Token::Minus => return Ok((**f1 - **f2).into()),
|
Minus => return Ok((**f1 - **f2).into()),
|
||||||
Token::Multiply => return Ok((**f1 * **f2).into()),
|
Multiply => return Ok((**f1 * **f2).into()),
|
||||||
Token::Divide => return Ok((**f1 / **f2).into()),
|
Divide => return Ok((**f1 / **f2).into()),
|
||||||
Token::Modulo => return Ok((**f1 % **f2).into()),
|
Modulo => return Ok((**f1 % **f2).into()),
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
(Union::Float(f1, ..), Union::Int(n2, ..)) => match op_token.unwrap() {
|
(Union::Float(f1, ..), Union::Int(n2, ..)) => match op_token.unwrap() {
|
||||||
Token::EqualsTo => return Ok((**f1 == (*n2 as crate::FLOAT)).into()),
|
EqualsTo => return Ok((**f1 == (*n2 as crate::FLOAT)).into()),
|
||||||
Token::NotEqualsTo => return Ok((**f1 != (*n2 as crate::FLOAT)).into()),
|
NotEqualsTo => return Ok((**f1 != (*n2 as crate::FLOAT)).into()),
|
||||||
Token::GreaterThan => return Ok((**f1 > (*n2 as crate::FLOAT)).into()),
|
GreaterThan => return Ok((**f1 > (*n2 as crate::FLOAT)).into()),
|
||||||
Token::GreaterThanEqualsTo => return Ok((**f1 >= (*n2 as crate::FLOAT)).into()),
|
GreaterThanEqualsTo => return Ok((**f1 >= (*n2 as crate::FLOAT)).into()),
|
||||||
Token::LessThan => return Ok((**f1 < (*n2 as crate::FLOAT)).into()),
|
LessThan => return Ok((**f1 < (*n2 as crate::FLOAT)).into()),
|
||||||
Token::LessThanEqualsTo => return Ok((**f1 <= (*n2 as crate::FLOAT)).into()),
|
LessThanEqualsTo => return Ok((**f1 <= (*n2 as crate::FLOAT)).into()),
|
||||||
Token::Plus => return Ok((**f1 + (*n2 as crate::FLOAT)).into()),
|
Plus => return Ok((**f1 + (*n2 as crate::FLOAT)).into()),
|
||||||
Token::Minus => return Ok((**f1 - (*n2 as crate::FLOAT)).into()),
|
Minus => return Ok((**f1 - (*n2 as crate::FLOAT)).into()),
|
||||||
Token::Multiply => return Ok((**f1 * (*n2 as crate::FLOAT)).into()),
|
Multiply => return Ok((**f1 * (*n2 as crate::FLOAT)).into()),
|
||||||
Token::Divide => return Ok((**f1 / (*n2 as crate::FLOAT)).into()),
|
Divide => return Ok((**f1 / (*n2 as crate::FLOAT)).into()),
|
||||||
Token::Modulo => return Ok((**f1 % (*n2 as crate::FLOAT)).into()),
|
Modulo => return Ok((**f1 % (*n2 as crate::FLOAT)).into()),
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
(Union::Int(n1, ..), Union::Float(f2, ..)) => match op_token.unwrap() {
|
(Union::Int(n1, ..), Union::Float(f2, ..)) => match op_token.unwrap() {
|
||||||
Token::EqualsTo => return Ok(((*n1 as crate::FLOAT) == **f2).into()),
|
EqualsTo => return Ok(((*n1 as crate::FLOAT) == **f2).into()),
|
||||||
Token::NotEqualsTo => return Ok(((*n1 as crate::FLOAT) != **f2).into()),
|
NotEqualsTo => return Ok(((*n1 as crate::FLOAT) != **f2).into()),
|
||||||
Token::GreaterThan => return Ok(((*n1 as crate::FLOAT) > **f2).into()),
|
GreaterThan => return Ok(((*n1 as crate::FLOAT) > **f2).into()),
|
||||||
Token::GreaterThanEqualsTo => return Ok(((*n1 as crate::FLOAT) >= **f2).into()),
|
GreaterThanEqualsTo => return Ok(((*n1 as crate::FLOAT) >= **f2).into()),
|
||||||
Token::LessThan => return Ok(((*n1 as crate::FLOAT) < **f2).into()),
|
LessThan => return Ok(((*n1 as crate::FLOAT) < **f2).into()),
|
||||||
Token::LessThanEqualsTo => return Ok(((*n1 as crate::FLOAT) <= **f2).into()),
|
LessThanEqualsTo => return Ok(((*n1 as crate::FLOAT) <= **f2).into()),
|
||||||
Token::Plus => return Ok(((*n1 as crate::FLOAT) + **f2).into()),
|
Plus => return Ok(((*n1 as crate::FLOAT) + **f2).into()),
|
||||||
Token::Minus => return Ok(((*n1 as crate::FLOAT) - **f2).into()),
|
Minus => return Ok(((*n1 as crate::FLOAT) - **f2).into()),
|
||||||
Token::Multiply => return Ok(((*n1 as crate::FLOAT) * **f2).into()),
|
Multiply => return Ok(((*n1 as crate::FLOAT) * **f2).into()),
|
||||||
Token::Divide => return Ok(((*n1 as crate::FLOAT) / **f2).into()),
|
Divide => return Ok(((*n1 as crate::FLOAT) / **f2).into()),
|
||||||
Token::Modulo => return Ok(((*n1 as crate::FLOAT) % **f2).into()),
|
Modulo => return Ok(((*n1 as crate::FLOAT) % **f2).into()),
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
(Union::Str(s1, ..), Union::Str(s2, ..)) => match op_token.unwrap() {
|
(Union::Str(s1, ..), Union::Str(s2, ..)) => match op_token.unwrap() {
|
||||||
Token::EqualsTo => return Ok((s1 == s2).into()),
|
EqualsTo => return Ok((s1 == s2).into()),
|
||||||
Token::NotEqualsTo => return Ok((s1 != s2).into()),
|
NotEqualsTo => return Ok((s1 != s2).into()),
|
||||||
Token::GreaterThan => return Ok((s1 > s2).into()),
|
GreaterThan => return Ok((s1 > s2).into()),
|
||||||
Token::GreaterThanEqualsTo => return Ok((s1 >= s2).into()),
|
GreaterThanEqualsTo => return Ok((s1 >= s2).into()),
|
||||||
Token::LessThan => return Ok((s1 < s2).into()),
|
LessThan => return Ok((s1 < s2).into()),
|
||||||
Token::LessThanEqualsTo => return Ok((s1 <= s2).into()),
|
LessThanEqualsTo => return Ok((s1 <= s2).into()),
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
@ -1723,8 +1723,8 @@ impl Engine {
|
|||||||
if let Some((func, need_context)) =
|
if let Some((func, need_context)) =
|
||||||
get_builtin_binary_op_fn(op_token.as_ref().unwrap(), operands[0], operands[1])
|
get_builtin_binary_op_fn(op_token.as_ref().unwrap(), operands[0], operands[1])
|
||||||
{
|
{
|
||||||
// Built-in found
|
// We may not need to bump the level because built-in's do not need it.
|
||||||
auto_restore! { let orig_level = global.level; global.level += 1 }
|
//auto_restore! { let orig_level = global.level; global.level += 1 }
|
||||||
|
|
||||||
let context =
|
let context =
|
||||||
need_context.then(|| (self, name.as_str(), None, &*global, pos).into());
|
need_context.then(|| (self, name.as_str(), None, &*global, pos).into());
|
||||||
|
Loading…
Reference in New Issue
Block a user