2021-02-13 16:01:34 +01:00
|
|
|
#![allow(non_snake_case)]
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
use crate::plugin::*;
|
2021-12-27 05:27:31 +01:00
|
|
|
use crate::{def_package, ExclusiveRange, InclusiveRange, RhaiResultOf, ERR, INT};
|
2021-04-17 09:15:54 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
2020-04-24 06:39:24 +02:00
|
|
|
|
2020-11-04 05:34:34 +01:00
|
|
|
#[cfg(any(
|
|
|
|
not(feature = "no_float"),
|
|
|
|
all(not(feature = "only_i32"), not(feature = "only_i64"))
|
|
|
|
))]
|
2020-08-14 07:43:26 +02:00
|
|
|
macro_rules! gen_cmp_functions {
|
2020-08-20 16:11:41 +02:00
|
|
|
($root:ident => $($arg_type:ident),+) => {
|
2020-08-28 17:13:38 +02:00
|
|
|
mod $root { $(pub mod $arg_type {
|
|
|
|
use super::super::*;
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-08-28 17:13:38 +02:00
|
|
|
#[export_module]
|
|
|
|
pub mod functions {
|
2021-02-24 08:45:29 +01:00
|
|
|
#[rhai_fn(name = "<")] pub fn lt(x: $arg_type, y: $arg_type) -> bool { x < y }
|
|
|
|
#[rhai_fn(name = "<=")] pub fn lte(x: $arg_type, y: $arg_type) -> bool { x <= y }
|
|
|
|
#[rhai_fn(name = ">")] pub fn gt(x: $arg_type, y: $arg_type) -> bool { x > y }
|
|
|
|
#[rhai_fn(name = ">=")] pub fn gte(x: $arg_type, y: $arg_type) -> bool { x >= y }
|
|
|
|
#[rhai_fn(name = "==")] pub fn eq(x: $arg_type, y: $arg_type) -> bool { x == y }
|
|
|
|
#[rhai_fn(name = "!=")] pub fn ne(x: $arg_type, y: $arg_type) -> bool { x != y }
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
2020-08-28 17:13:38 +02:00
|
|
|
})* }
|
2020-08-20 16:11:41 +02:00
|
|
|
};
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
|
|
|
|
2020-11-04 05:34:34 +01:00
|
|
|
#[cfg(any(
|
|
|
|
not(feature = "no_float"),
|
|
|
|
all(not(feature = "only_i32"), not(feature = "only_i64"))
|
|
|
|
))]
|
2020-08-14 07:43:26 +02:00
|
|
|
macro_rules! reg_functions {
|
2020-08-24 16:37:44 +02:00
|
|
|
($mod_name:ident += $root:ident ; $($arg_type:ident),+) => { $(
|
2020-09-13 16:12:11 +02:00
|
|
|
combine_with_exported_module!($mod_name, "logic", $root::$arg_type::functions);
|
2020-08-24 16:37:44 +02:00
|
|
|
)* }
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
def_package! {
|
|
|
|
/// Package of basic logic operators.
|
|
|
|
crate::LogicPackage => |lib| {
|
|
|
|
lib.standard = true;
|
2021-11-05 16:22:05 +01:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
{
|
|
|
|
reg_functions!(lib += numbers; i8, u8, i16, u16, i32, u32, u64);
|
2020-06-17 10:50:46 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
|
|
|
reg_functions!(lib += num_128; i128, u128);
|
|
|
|
}
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
{
|
|
|
|
#[cfg(not(feature = "f32_float"))]
|
|
|
|
reg_functions!(lib += float; f32);
|
|
|
|
combine_with_exported_module!(lib, "f32", f32_functions);
|
2020-11-04 05:34:34 +01:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(feature = "f32_float")]
|
|
|
|
reg_functions!(lib += float; f64);
|
|
|
|
combine_with_exported_module!(lib, "f64", f64_functions);
|
|
|
|
}
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
set_exported_fn!(lib, "!", not);
|
2021-06-02 08:29:18 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
combine_with_exported_module!(lib, "bit_field", bit_field_functions);
|
|
|
|
}
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
|
|
|
|
// Logic operators
|
|
|
|
#[export_fn]
|
|
|
|
fn not(x: bool) -> bool {
|
|
|
|
!x
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
2020-08-20 16:11:41 +02:00
|
|
|
gen_cmp_functions!(numbers => i8, u8, i16, u16, i32, u32, u64);
|
2020-08-14 07:43:26 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
2021-02-19 08:50:48 +01:00
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
2020-08-20 16:11:41 +02:00
|
|
|
gen_cmp_functions!(num_128 => i128, u128);
|
2020-08-14 07:43:26 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2020-11-04 05:34:34 +01:00
|
|
|
#[cfg(not(feature = "f32_float"))]
|
2020-08-20 16:11:41 +02:00
|
|
|
gen_cmp_functions!(float => f32);
|
2020-11-04 05:34:34 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[cfg(feature = "f32_float")]
|
|
|
|
gen_cmp_functions!(float => f64);
|
2021-02-13 16:01:34 +01:00
|
|
|
|
2021-02-18 07:33:27 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[export_module]
|
|
|
|
mod f32_functions {
|
|
|
|
#[rhai_fn(name = "==")]
|
|
|
|
pub fn eq_if(x: INT, y: f32) -> bool {
|
|
|
|
(x as f32) == (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "==")]
|
|
|
|
pub fn eq_fi(x: f32, y: INT) -> bool {
|
|
|
|
(x as f32) == (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "!=")]
|
|
|
|
pub fn neq_if(x: INT, y: f32) -> bool {
|
|
|
|
(x as f32) != (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "!=")]
|
|
|
|
pub fn neq_fi(x: f32, y: INT) -> bool {
|
|
|
|
(x as f32) != (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = ">")]
|
|
|
|
pub fn gt_if(x: INT, y: f32) -> bool {
|
|
|
|
(x as f32) > (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = ">")]
|
|
|
|
pub fn gt_fi(x: f32, y: INT) -> bool {
|
|
|
|
(x as f32) > (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = ">=")]
|
|
|
|
pub fn gte_if(x: INT, y: f32) -> bool {
|
|
|
|
(x as f32) >= (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = ">=")]
|
|
|
|
pub fn gte_fi(x: f32, y: INT) -> bool {
|
|
|
|
(x as f32) >= (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "<")]
|
|
|
|
pub fn lt_if(x: INT, y: f32) -> bool {
|
|
|
|
(x as f32) < (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "<")]
|
|
|
|
pub fn lt_fi(x: f32, y: INT) -> bool {
|
|
|
|
(x as f32) < (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "<=")]
|
|
|
|
pub fn lte_if(x: INT, y: f32) -> bool {
|
|
|
|
(x as f32) <= (y as f32)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "<=")]
|
|
|
|
pub fn lte_fi(x: f32, y: INT) -> bool {
|
|
|
|
(x as f32) <= (y as f32)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[export_module]
|
|
|
|
mod f64_functions {
|
|
|
|
#[rhai_fn(name = "==")]
|
|
|
|
pub fn eq_if(x: INT, y: f64) -> bool {
|
|
|
|
(x as f64) == (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "==")]
|
|
|
|
pub fn eq_fi(x: f64, y: INT) -> bool {
|
|
|
|
(x as f64) == (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "!=")]
|
|
|
|
pub fn neq_if(x: INT, y: f64) -> bool {
|
|
|
|
(x as f64) != (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "!=")]
|
|
|
|
pub fn neq_fi(x: f64, y: INT) -> bool {
|
|
|
|
(x as f64) != (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = ">")]
|
|
|
|
pub fn gt_if(x: INT, y: f64) -> bool {
|
|
|
|
(x as f64) > (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = ">")]
|
|
|
|
pub fn gt_fi(x: f64, y: INT) -> bool {
|
|
|
|
(x as f64) > (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = ">=")]
|
|
|
|
pub fn gte_if(x: INT, y: f64) -> bool {
|
|
|
|
(x as f64) >= (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = ">=")]
|
|
|
|
pub fn gte_fi(x: f64, y: INT) -> bool {
|
|
|
|
(x as f64) >= (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "<")]
|
|
|
|
pub fn lt_if(x: INT, y: f64) -> bool {
|
|
|
|
(x as f64) < (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "<")]
|
|
|
|
pub fn lt_fi(x: f64, y: INT) -> bool {
|
|
|
|
(x as f64) < (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "<=")]
|
|
|
|
pub fn lte_if(x: INT, y: f64) -> bool {
|
|
|
|
(x as f64) <= (y as f64)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "<=")]
|
|
|
|
pub fn lte_fi(x: f64, y: INT) -> bool {
|
|
|
|
(x as f64) <= (y as f64)
|
|
|
|
}
|
|
|
|
}
|
2021-06-02 08:29:18 +02:00
|
|
|
|
|
|
|
#[export_module]
|
|
|
|
mod bit_field_functions {
|
|
|
|
const BITS: usize = std::mem::size_of::<INT>() * 8;
|
|
|
|
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn get_bit(value: INT, index: INT) -> RhaiResultOf<bool> {
|
2021-06-02 08:29:18 +02:00
|
|
|
if index >= 0 {
|
|
|
|
let offset = index as usize;
|
|
|
|
|
|
|
|
if offset >= BITS {
|
2021-12-27 05:27:31 +01:00
|
|
|
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
2021-06-02 08:29:18 +02:00
|
|
|
} else {
|
|
|
|
Ok((value & (1 << offset)) != 0)
|
|
|
|
}
|
|
|
|
} else if let Some(abs_index) = index.checked_abs() {
|
|
|
|
let offset = abs_index as usize;
|
|
|
|
|
|
|
|
// Count from end if negative
|
|
|
|
if offset > BITS {
|
2021-12-27 05:27:31 +01:00
|
|
|
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
2021-06-02 08:29:18 +02:00
|
|
|
} else {
|
|
|
|
Ok((value & (1 << (BITS - offset))) != 0)
|
|
|
|
}
|
|
|
|
} else {
|
2021-12-27 05:27:31 +01:00
|
|
|
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
2021-06-02 08:29:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn set_bit(value: &mut INT, index: INT, new_value: bool) -> RhaiResultOf<()> {
|
2021-06-02 08:29:18 +02:00
|
|
|
if index >= 0 {
|
|
|
|
let offset = index as usize;
|
|
|
|
|
|
|
|
if offset >= BITS {
|
2021-12-27 05:27:31 +01:00
|
|
|
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
2021-06-02 08:29:18 +02:00
|
|
|
} else {
|
|
|
|
let mask = 1 << offset;
|
|
|
|
if new_value {
|
|
|
|
*value |= mask;
|
|
|
|
} else {
|
|
|
|
*value &= !mask;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
} else if let Some(abs_index) = index.checked_abs() {
|
|
|
|
let offset = abs_index as usize;
|
|
|
|
|
|
|
|
// Count from end if negative
|
|
|
|
if offset > BITS {
|
2021-12-27 05:27:31 +01:00
|
|
|
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
2021-06-02 08:29:18 +02:00
|
|
|
} else {
|
|
|
|
let mask = 1 << offset;
|
|
|
|
if new_value {
|
|
|
|
*value |= mask;
|
|
|
|
} else {
|
|
|
|
*value &= !mask;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
} else {
|
2021-12-27 05:27:31 +01:00
|
|
|
Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into())
|
2021-06-02 08:29:18 +02:00
|
|
|
}
|
|
|
|
}
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "get_bits", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn get_bits_range(value: INT, range: ExclusiveRange) -> RhaiResultOf<INT> {
|
2021-12-15 05:06:17 +01:00
|
|
|
let from = INT::max(range.start, 0);
|
|
|
|
let to = INT::max(range.end, from);
|
|
|
|
get_bits(value, from, to - from)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "get_bits", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn get_bits_range_inclusive(value: INT, range: InclusiveRange) -> RhaiResultOf<INT> {
|
2021-12-15 05:06:17 +01:00
|
|
|
let from = INT::max(*range.start(), 0);
|
|
|
|
let to = INT::max(*range.end(), from - 1);
|
|
|
|
get_bits(value, from, to - from + 1)
|
|
|
|
}
|
2021-06-02 08:29:18 +02:00
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn get_bits(value: INT, index: INT, bits: INT) -> RhaiResultOf<INT> {
|
2021-06-02 08:29:18 +02:00
|
|
|
if bits < 1 {
|
|
|
|
return Ok(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
let offset = if index >= 0 {
|
|
|
|
let offset = index as usize;
|
|
|
|
|
|
|
|
if offset >= BITS {
|
2021-12-27 05:27:31 +01:00
|
|
|
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
2021-06-02 08:29:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
offset
|
|
|
|
} else if let Some(abs_index) = index.checked_abs() {
|
|
|
|
let offset = abs_index as usize;
|
|
|
|
|
|
|
|
// Count from end if negative
|
|
|
|
if offset > BITS {
|
2021-12-27 05:27:31 +01:00
|
|
|
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
2021-06-02 08:29:18 +02:00
|
|
|
}
|
|
|
|
BITS - offset
|
|
|
|
} else {
|
2021-12-27 05:27:31 +01:00
|
|
|
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
2021-06-02 08:29:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
let bits = if offset + bits as usize > BITS {
|
|
|
|
BITS - offset
|
|
|
|
} else {
|
|
|
|
bits as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut base = 1;
|
|
|
|
let mut mask = 0;
|
|
|
|
|
|
|
|
for _ in 0..bits {
|
|
|
|
mask |= base;
|
|
|
|
base <<= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(((value & (mask << index)) >> index) & mask)
|
|
|
|
}
|
2021-12-15 05:06:17 +01:00
|
|
|
#[rhai_fn(name = "set_bits", return_raw)]
|
|
|
|
pub fn set_bits_range(
|
|
|
|
value: &mut INT,
|
|
|
|
range: ExclusiveRange,
|
|
|
|
new_value: INT,
|
2021-12-25 16:49:14 +01:00
|
|
|
) -> RhaiResultOf<()> {
|
2021-12-15 05:06:17 +01:00
|
|
|
let from = INT::max(range.start, 0);
|
|
|
|
let to = INT::max(range.end, from);
|
|
|
|
set_bits(value, from, to - from, new_value)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "set_bits", return_raw)]
|
|
|
|
pub fn set_bits_range_inclusive(
|
|
|
|
value: &mut INT,
|
|
|
|
range: InclusiveRange,
|
|
|
|
new_value: INT,
|
2021-12-25 16:49:14 +01:00
|
|
|
) -> RhaiResultOf<()> {
|
2021-12-15 05:06:17 +01:00
|
|
|
let from = INT::max(*range.start(), 0);
|
|
|
|
let to = INT::max(*range.end(), from - 1);
|
|
|
|
set_bits(value, from, to - from + 1, new_value)
|
|
|
|
}
|
2021-06-02 08:29:18 +02:00
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn set_bits(value: &mut INT, index: INT, bits: INT, new_value: INT) -> RhaiResultOf<()> {
|
2021-06-02 08:29:18 +02:00
|
|
|
if bits < 1 {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
let offset = if index >= 0 {
|
|
|
|
let offset = index as usize;
|
|
|
|
|
|
|
|
if offset >= BITS {
|
2021-12-27 05:27:31 +01:00
|
|
|
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
2021-06-02 08:29:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
offset
|
|
|
|
} else if let Some(abs_index) = index.checked_abs() {
|
|
|
|
let offset = abs_index as usize;
|
|
|
|
|
|
|
|
// Count from end if negative
|
|
|
|
if offset > BITS {
|
2021-12-27 05:27:31 +01:00
|
|
|
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
2021-06-02 08:29:18 +02:00
|
|
|
}
|
|
|
|
BITS - offset
|
|
|
|
} else {
|
2021-12-27 05:27:31 +01:00
|
|
|
return Err(ERR::ErrorBitFieldBounds(BITS, index, Position::NONE).into());
|
2021-06-02 08:29:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
let bits = if offset + bits as usize > BITS {
|
|
|
|
BITS - offset
|
|
|
|
} else {
|
|
|
|
bits as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut base = 1;
|
|
|
|
let mut mask = 0;
|
|
|
|
|
|
|
|
for _ in 0..bits {
|
|
|
|
mask |= base;
|
|
|
|
base <<= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*value &= !(mask << index);
|
|
|
|
*value |= (new_value & mask) << index;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|