Fix range precedences and add comparison operators.
This commit is contained in:
parent
eda80488d5
commit
59a9ff0b0f
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
use super::call::FnCallArgs;
|
use super::call::FnCallArgs;
|
||||||
use crate::engine::OP_CONTAINS;
|
use crate::engine::OP_CONTAINS;
|
||||||
use crate::{Dynamic, ImmutableString, NativeCallContext, RhaiResult, INT};
|
use crate::{
|
||||||
|
Dynamic, ExclusiveRange, ImmutableString, InclusiveRange, NativeCallContext, RhaiResult, INT,
|
||||||
|
};
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -55,24 +57,6 @@ pub fn get_builtin_binary_op_fn(
|
|||||||
let type1 = x.type_id();
|
let type1 = x.type_id();
|
||||||
let type2 = y.type_id();
|
let type2 = y.type_id();
|
||||||
|
|
||||||
// One of the operands is a custom type, so it is never built-in
|
|
||||||
if x.is_variant() || y.is_variant() {
|
|
||||||
return if is_numeric(type1) && is_numeric(type2) {
|
|
||||||
// Disallow comparisons between different numeric types
|
|
||||||
None
|
|
||||||
} else if type1 != type2 {
|
|
||||||
// If the types are not the same, default to not compare
|
|
||||||
match op {
|
|
||||||
"!=" => Some(|_, _| Ok(Dynamic::TRUE)),
|
|
||||||
"==" | ">" | ">=" | "<" | "<=" => Some(|_, _| Ok(Dynamic::FALSE)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Disallow comparisons between the same type
|
|
||||||
None
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let types_pair = (type1, type2);
|
let types_pair = (type1, type2);
|
||||||
|
|
||||||
macro_rules! impl_op {
|
macro_rules! impl_op {
|
||||||
@ -301,6 +285,64 @@ pub fn get_builtin_binary_op_fn(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Non-compatible ranges
|
||||||
|
if types_pair
|
||||||
|
== (
|
||||||
|
TypeId::of::<ExclusiveRange>(),
|
||||||
|
TypeId::of::<InclusiveRange>(),
|
||||||
|
)
|
||||||
|
|| types_pair
|
||||||
|
== (
|
||||||
|
TypeId::of::<InclusiveRange>(),
|
||||||
|
TypeId::of::<ExclusiveRange>(),
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return match op {
|
||||||
|
"!=" => Some(|_, _| Ok(Dynamic::TRUE)),
|
||||||
|
"==" => Some(|_, _| Ok(Dynamic::FALSE)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle ranges here because ranges are implemented as custom type
|
||||||
|
if type1 == TypeId::of::<ExclusiveRange>() {
|
||||||
|
if type1 == type2 {
|
||||||
|
return match op {
|
||||||
|
"==" => Some(impl_op!(ExclusiveRange == ExclusiveRange)),
|
||||||
|
"!=" => Some(impl_op!(ExclusiveRange != ExclusiveRange)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if type1 == TypeId::of::<InclusiveRange>() {
|
||||||
|
if type1 == type2 {
|
||||||
|
return match op {
|
||||||
|
"==" => Some(impl_op!(InclusiveRange == InclusiveRange)),
|
||||||
|
"!=" => Some(impl_op!(InclusiveRange != InclusiveRange)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// One of the operands is a custom type, so it is never built-in
|
||||||
|
if x.is_variant() || y.is_variant() {
|
||||||
|
return if is_numeric(type1) && is_numeric(type2) {
|
||||||
|
// Disallow comparisons between different numeric types
|
||||||
|
None
|
||||||
|
} else if type1 != type2 {
|
||||||
|
// If the types are not the same, default to not compare
|
||||||
|
match op {
|
||||||
|
"!=" => Some(|_, _| Ok(Dynamic::TRUE)),
|
||||||
|
"==" | ">" | ">=" | "<" | "<=" => Some(|_, _| Ok(Dynamic::FALSE)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Disallow comparisons between the same type
|
||||||
|
None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Default comparison operators for different types
|
// Default comparison operators for different types
|
||||||
if type2 != type1 {
|
if type2 != type1 {
|
||||||
return match op {
|
return match op {
|
||||||
|
@ -530,15 +530,15 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
|
|||||||
#[export_module]
|
#[export_module]
|
||||||
mod range_functions {
|
mod range_functions {
|
||||||
#[rhai_fn(get = "start", name = "start", pure)]
|
#[rhai_fn(get = "start", name = "start", pure)]
|
||||||
pub fn range_start(range: &mut ExclusiveRange) -> INT {
|
pub fn start(range: &mut ExclusiveRange) -> INT {
|
||||||
range.start
|
range.start
|
||||||
}
|
}
|
||||||
#[rhai_fn(get = "end", name = "end", pure)]
|
#[rhai_fn(get = "end", name = "end", pure)]
|
||||||
pub fn range_end(range: &mut ExclusiveRange) -> INT {
|
pub fn end(range: &mut ExclusiveRange) -> INT {
|
||||||
range.end
|
range.end
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "contains", pure)]
|
#[rhai_fn(name = "contains", pure)]
|
||||||
pub fn range_contains(range: &mut ExclusiveRange, value: INT) -> bool {
|
pub fn contains(range: &mut ExclusiveRange, value: INT) -> bool {
|
||||||
range.contains(&value)
|
range.contains(&value)
|
||||||
}
|
}
|
||||||
#[rhai_fn(get = "is_inclusive", name = "is_inclusive", pure)]
|
#[rhai_fn(get = "is_inclusive", name = "is_inclusive", pure)]
|
||||||
@ -546,20 +546,28 @@ mod range_functions {
|
|||||||
let _range = range;
|
let _range = range;
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
#[rhai_fn(get = "is_empty", name = "is_empty", pure)]
|
||||||
|
pub fn is_empty(range: &mut ExclusiveRange) -> bool {
|
||||||
|
range.is_empty()
|
||||||
|
}
|
||||||
#[rhai_fn(get = "start", name = "start", pure)]
|
#[rhai_fn(get = "start", name = "start", pure)]
|
||||||
pub fn range_inclusive_start(range: &mut InclusiveRange) -> INT {
|
pub fn start_inclusive(range: &mut InclusiveRange) -> INT {
|
||||||
*range.start()
|
*range.start()
|
||||||
}
|
}
|
||||||
#[rhai_fn(get = "end", name = "end", pure)]
|
#[rhai_fn(get = "end", name = "end", pure)]
|
||||||
pub fn range_inclusive_end(range: &mut InclusiveRange) -> INT {
|
pub fn end_inclusive(range: &mut InclusiveRange) -> INT {
|
||||||
*range.end()
|
*range.end()
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "contains", pure)]
|
#[rhai_fn(name = "contains", pure)]
|
||||||
pub fn range_inclusive_contains(range: &mut InclusiveRange, value: INT) -> bool {
|
pub fn contains_inclusive(range: &mut InclusiveRange, value: INT) -> bool {
|
||||||
range.contains(&value)
|
range.contains(&value)
|
||||||
}
|
}
|
||||||
|
#[rhai_fn(get = "is_empty", name = "is_empty", pure)]
|
||||||
|
pub fn is_empty_inclusive(range: &mut InclusiveRange) -> bool {
|
||||||
|
range.is_empty()
|
||||||
|
}
|
||||||
#[rhai_fn(get = "is_inclusive", name = "is_inclusive", pure)]
|
#[rhai_fn(get = "is_inclusive", name = "is_inclusive", pure)]
|
||||||
pub fn range_inclusive_is_inclusive(range: &mut InclusiveRange) -> bool {
|
pub fn is_inclusive_inclusive(range: &mut InclusiveRange) -> bool {
|
||||||
let _range = range;
|
let _range = range;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -878,8 +878,6 @@ impl Token {
|
|||||||
| LeftShiftAssign | RightShiftAssign | AndAssign | OrAssign | XOrAssign
|
| LeftShiftAssign | RightShiftAssign | AndAssign | OrAssign | XOrAssign
|
||||||
| ModuloAssign => 0,
|
| ModuloAssign => 0,
|
||||||
|
|
||||||
ExclusiveRange | InclusiveRange => 10,
|
|
||||||
|
|
||||||
Or | XOr | Pipe => 30,
|
Or | XOr | Pipe => 30,
|
||||||
|
|
||||||
And | Ampersand => 60,
|
And | Ampersand => 60,
|
||||||
@ -890,6 +888,8 @@ impl Token {
|
|||||||
|
|
||||||
LessThan | LessThanEqualsTo | GreaterThan | GreaterThanEqualsTo => 130,
|
LessThan | LessThanEqualsTo | GreaterThan | GreaterThanEqualsTo => 130,
|
||||||
|
|
||||||
|
ExclusiveRange | InclusiveRange => 140,
|
||||||
|
|
||||||
Plus | Minus => 150,
|
Plus | Minus => 150,
|
||||||
|
|
||||||
Divide | Multiply | Modulo => 180,
|
Divide | Multiply | Modulo => 180,
|
||||||
|
Loading…
Reference in New Issue
Block a user