Implement print/debug functions via Dynamic parameters.
This commit is contained in:
parent
ba2b0630f7
commit
36420f0b99
@ -475,7 +475,45 @@ impl fmt::Display for Dynamic {
|
|||||||
#[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, _) => f.write_str((*value).type_name()),
|
Union::Variant(value, _) => {
|
||||||
|
let _type_id = (***value).type_id();
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
if _type_id == TypeId::of::<u8>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<u8>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<u16>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<u16>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<u32>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<u32>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<u64>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<u64>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i8>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<i8>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i16>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<i16>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i32>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<i32>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i64>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<i64>().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
if _type_id == TypeId::of::<f32>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<f32>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<f64>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<f64>().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
|
if _type_id == TypeId::of::<u128>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<u128>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i128>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<i128>().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
f.write_str((***value).type_name())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
@ -516,7 +554,53 @@ impl fmt::Debug for Dynamic {
|
|||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
Union::TimeStamp(_, _) => write!(f, "<timestamp>"),
|
Union::TimeStamp(_, _) => write!(f, "<timestamp>"),
|
||||||
|
|
||||||
Union::Variant(value, _) => write!(f, "{}", (*value).type_name()),
|
Union::Variant(value, _) => {
|
||||||
|
let _type_id = (***value).type_id();
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
if _type_id == TypeId::of::<u8>() {
|
||||||
|
return write!(f, "{:?}", (**value).as_any().downcast_ref::<u8>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<u16>() {
|
||||||
|
return write!(f, "{:?}", (**value).as_any().downcast_ref::<u16>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<u32>() {
|
||||||
|
return write!(f, "{:?}", (**value).as_any().downcast_ref::<u32>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<u64>() {
|
||||||
|
return write!(f, "{:?}", (**value).as_any().downcast_ref::<u64>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i8>() {
|
||||||
|
return write!(f, "{:?}", (**value).as_any().downcast_ref::<i8>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i16>() {
|
||||||
|
return write!(f, "{:?}", (**value).as_any().downcast_ref::<i16>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i32>() {
|
||||||
|
return write!(f, "{:?}", (**value).as_any().downcast_ref::<i32>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<i64>() {
|
||||||
|
return write!(f, "{:?}", (**value).as_any().downcast_ref::<i64>().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
if _type_id == TypeId::of::<f32>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<f32>().unwrap());
|
||||||
|
} else if _type_id == TypeId::of::<f64>() {
|
||||||
|
return write!(f, "{}", (**value).as_any().downcast_ref::<f64>().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
|
if _type_id == TypeId::of::<u128>() {
|
||||||
|
return write!(
|
||||||
|
f,
|
||||||
|
"{:?}",
|
||||||
|
(**value).as_any().downcast_ref::<u128>().unwrap()
|
||||||
|
);
|
||||||
|
} else if _type_id == TypeId::of::<i128>() {
|
||||||
|
return write!(
|
||||||
|
f,
|
||||||
|
"{:?}",
|
||||||
|
(**value).as_any().downcast_ref::<i128>().unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "{}", (*value).type_name())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
|
@ -186,9 +186,8 @@ impl Engine {
|
|||||||
.entry(hash_fn)
|
.entry(hash_fn)
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
let num_args = args.len();
|
let num_args = args.len();
|
||||||
let max_bitmask = 1usize << num_args;
|
|
||||||
let mut hash = hash_fn;
|
let mut hash = hash_fn;
|
||||||
let mut bitmask = 1usize;
|
let mut bitmask = 1usize; // Bitmask of which parameter to replace with `Dynamic`
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
//lib.get_fn(hash, pub_only).or_else(||
|
//lib.get_fn(hash, pub_only).or_else(||
|
||||||
@ -210,8 +209,8 @@ impl Engine {
|
|||||||
// Specific version found
|
// Specific version found
|
||||||
Some(f) => return Some(f),
|
Some(f) => return Some(f),
|
||||||
|
|
||||||
// No more permutations with `Dynamic` wildcards
|
// No parameters
|
||||||
_ if bitmask >= max_bitmask => return None,
|
_ if num_args == 0 => return None,
|
||||||
|
|
||||||
// Try all permutations with `Dynamic` wildcards
|
// Try all permutations with `Dynamic` wildcards
|
||||||
_ => {
|
_ => {
|
||||||
@ -219,12 +218,19 @@ impl Engine {
|
|||||||
let arg_types = args.iter().enumerate().map(|(i, a)| {
|
let arg_types = args.iter().enumerate().map(|(i, a)| {
|
||||||
let mask = 1usize << (num_args - i - 1);
|
let mask = 1usize << (num_args - i - 1);
|
||||||
if bitmask & mask != 0 {
|
if bitmask & mask != 0 {
|
||||||
|
// Replace with `Dynamic`
|
||||||
TypeId::of::<Dynamic>()
|
TypeId::of::<Dynamic>()
|
||||||
} else {
|
} else {
|
||||||
a.type_id()
|
a.type_id()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
hash = calc_native_fn_hash(empty(), fn_name, arg_types).unwrap();
|
hash = calc_native_fn_hash(empty(), fn_name, arg_types).unwrap();
|
||||||
|
|
||||||
|
// Stop when all permutations are exhausted
|
||||||
|
if hash == hash_fn {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
bitmask += 1;
|
bitmask += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::engine::{KEYWORD_DEBUG, KEYWORD_PRINT};
|
|
||||||
use crate::plugin::*;
|
use crate::plugin::*;
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{format, string::ToString};
|
||||||
fmt::{Debug, Display},
|
use crate::{def_package, FnPtr, ImmutableString};
|
||||||
format,
|
|
||||||
string::ToString,
|
|
||||||
};
|
|
||||||
use crate::{def_package, FnPtr, ImmutableString, INT};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::Array;
|
use crate::Array;
|
||||||
@ -15,139 +10,12 @@ use crate::Array;
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
use crate::Map;
|
use crate::Map;
|
||||||
|
|
||||||
#[cfg(feature = "decimal")]
|
|
||||||
use rust_decimal::Decimal;
|
|
||||||
|
|
||||||
const FUNC_TO_STRING: &'static str = "to_string";
|
|
||||||
const FUNC_TO_DEBUG: &'static str = "to_debug";
|
const FUNC_TO_DEBUG: &'static str = "to_debug";
|
||||||
|
|
||||||
type Unit = ();
|
|
||||||
|
|
||||||
macro_rules! gen_functions {
|
|
||||||
($root:ident => $fn_name:ident ( $($arg_type:ident),+ )) => {
|
|
||||||
pub mod $root { $(pub mod $arg_type {
|
|
||||||
use super::super::*;
|
|
||||||
|
|
||||||
#[export_fn(pure)]
|
|
||||||
pub fn to_string_func(x: &mut $arg_type) -> ImmutableString {
|
|
||||||
super::super::$fn_name(x)
|
|
||||||
}
|
|
||||||
})* }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! reg_print_functions {
|
|
||||||
($mod_name:ident += $root:ident ; $($arg_type:ident),+) => { $(
|
|
||||||
set_exported_fn!($mod_name, FUNC_TO_STRING, $root::$arg_type::to_string_func);
|
|
||||||
set_exported_fn!($mod_name, KEYWORD_PRINT, $root::$arg_type::to_string_func);
|
|
||||||
)* }
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! reg_debug_functions {
|
|
||||||
($mod_name:ident += $root:ident ; $($arg_type:ident),+) => { $(
|
|
||||||
set_exported_fn!($mod_name, FUNC_TO_DEBUG, $root::$arg_type::to_string_func);
|
|
||||||
set_exported_fn!($mod_name, KEYWORD_DEBUG, $root::$arg_type::to_string_func);
|
|
||||||
)* }
|
|
||||||
}
|
|
||||||
|
|
||||||
def_package!(crate:BasicStringPackage:"Basic string utilities, including printing.", lib, {
|
def_package!(crate:BasicStringPackage:"Basic string utilities, including printing.", lib, {
|
||||||
combine_with_exported_module!(lib, "print_debug", print_debug_functions);
|
combine_with_exported_module!(lib, "print_debug", print_debug_functions);
|
||||||
|
|
||||||
reg_print_functions!(lib += print_basic; INT, bool, char, FnPtr);
|
|
||||||
reg_debug_functions!(lib += debug_basic; INT, bool, Unit, char, ImmutableString);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
{
|
|
||||||
reg_print_functions!(lib += print_numbers; i8, u8, i16, u16, i32, u32, i64, u64);
|
|
||||||
reg_debug_functions!(lib += debug_numbers; i8, u8, i16, u16, i32, u32, i64, u64);
|
|
||||||
|
|
||||||
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
|
||||||
{
|
|
||||||
reg_print_functions!(lib += print_num_128; i128, u128);
|
|
||||||
reg_debug_functions!(lib += debug_num_128; i128, u128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
{
|
|
||||||
reg_print_functions!(lib += print_float_64; f64);
|
|
||||||
reg_debug_functions!(lib += print_float_64; f64);
|
|
||||||
reg_print_functions!(lib += print_float_32; f32);
|
|
||||||
reg_debug_functions!(lib += print_float_32; f32);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "decimal")]
|
|
||||||
{
|
|
||||||
reg_print_functions!(lib += print_decimal; Decimal);
|
|
||||||
reg_debug_functions!(lib += debug_decimal; Decimal);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
fn to_string<T: Display>(x: &mut T) -> ImmutableString {
|
|
||||||
x.to_string().into()
|
|
||||||
}
|
|
||||||
fn to_debug<T: Debug>(x: &mut T) -> ImmutableString {
|
|
||||||
format!("{:?}", x).into()
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
fn print_f64(x: &mut f64) -> ImmutableString {
|
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
use num_traits::Float;
|
|
||||||
|
|
||||||
let abs = x.abs();
|
|
||||||
if abs > 10000000000000.0 || abs < 0.0000000000001 {
|
|
||||||
format!("{:e}", x).into()
|
|
||||||
} else {
|
|
||||||
x.to_string().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
fn print_f32(x: &mut f32) -> ImmutableString {
|
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
use num_traits::Float;
|
|
||||||
|
|
||||||
let abs = x.abs();
|
|
||||||
if abs > 10000000000000.0 || abs < 0.0000000000001 {
|
|
||||||
format!("{:e}", x).into()
|
|
||||||
} else {
|
|
||||||
x.to_string().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_functions!(print_basic => to_string(INT, bool, char, FnPtr));
|
|
||||||
gen_functions!(debug_basic => to_debug(INT, bool, Unit, char, ImmutableString));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
gen_functions!(print_numbers => to_string(i8, u8, i16, u16, i32, u32, i64, u64));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
gen_functions!(debug_numbers => to_debug(i8, u8, i16, u16, i32, u32, i64, u64));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
|
||||||
gen_functions!(print_num_128 => to_string(i128, u128));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
|
||||||
gen_functions!(debug_num_128 => to_debug(i128, u128));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
gen_functions!(print_float_64 => print_f64(f64));
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
gen_functions!(print_float_32 => print_f32(f32));
|
|
||||||
|
|
||||||
#[cfg(feature = "decimal")]
|
|
||||||
gen_functions!(print_decimal => to_string(Decimal));
|
|
||||||
|
|
||||||
#[cfg(feature = "decimal")]
|
|
||||||
gen_functions!(debug_decimal => to_debug(Decimal));
|
|
||||||
|
|
||||||
// Register print and debug
|
// Register print and debug
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
@ -162,6 +30,16 @@ fn print_with_func(fn_name: &str, ctx: &NativeCallContext, value: &mut Dynamic)
|
|||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
mod print_debug_functions {
|
mod print_debug_functions {
|
||||||
|
use crate::ImmutableString;
|
||||||
|
|
||||||
|
#[rhai_fn(name = "print", name = "to_string", pure)]
|
||||||
|
pub fn print_generic(item: &mut Dynamic) -> ImmutableString {
|
||||||
|
item.to_string().into()
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "debug", name = "to_debug", pure)]
|
||||||
|
pub fn debug_generic(item: &mut Dynamic) -> ImmutableString {
|
||||||
|
format!("{:?}", item).into()
|
||||||
|
}
|
||||||
#[rhai_fn(name = "print", name = "debug")]
|
#[rhai_fn(name = "print", name = "debug")]
|
||||||
pub fn print_empty_string() -> ImmutableString {
|
pub fn print_empty_string() -> ImmutableString {
|
||||||
"".to_string().into()
|
"".to_string().into()
|
||||||
@ -176,7 +54,43 @@ mod print_debug_functions {
|
|||||||
}
|
}
|
||||||
#[rhai_fn(name = "debug", pure)]
|
#[rhai_fn(name = "debug", pure)]
|
||||||
pub fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString {
|
pub fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString {
|
||||||
to_string(f)
|
f.to_string().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
pub mod float_functions {
|
||||||
|
#[rhai_fn(name = "print", name = "to_string")]
|
||||||
|
pub fn print_f64(number: f64) -> ImmutableString {
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
use num_traits::Float;
|
||||||
|
|
||||||
|
let abs = number.abs();
|
||||||
|
if abs > 10000000000000.0 || abs < 0.0000000000001 {
|
||||||
|
format!("{:e}", number).into()
|
||||||
|
} else {
|
||||||
|
number.to_string().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "print", name = "to_string")]
|
||||||
|
pub fn print_f32(number: f32) -> ImmutableString {
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
use num_traits::Float;
|
||||||
|
|
||||||
|
let abs = number.abs();
|
||||||
|
if abs > 10000000000000.0 || abs < 0.0000000000001 {
|
||||||
|
format!("{:e}", number).into()
|
||||||
|
} else {
|
||||||
|
number.to_string().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "debug", name = "to_debug")]
|
||||||
|
pub fn debug_f64(number: f64) -> ImmutableString {
|
||||||
|
number.to_string().into()
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "debug", name = "to_debug")]
|
||||||
|
pub fn debug_f32(number: f32) -> ImmutableString {
|
||||||
|
number.to_string().into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
@ -1,6 +1,33 @@
|
|||||||
use rhai::{Engine, EvalAltResult, RegisterFn, INT};
|
use rhai::{Engine, EvalAltResult, RegisterFn, Scope, INT};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
#[cfg(not(feature = "only_i64"))]
|
||||||
|
#[test]
|
||||||
|
fn test_to_string() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
let engine = Engine::new();
|
||||||
|
|
||||||
|
let mut scope = Scope::new();
|
||||||
|
scope.push("x", 42_u8);
|
||||||
|
scope.push("y", 42_i32);
|
||||||
|
scope.push("z", 42_i16);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval_with_scope::<String>(&mut scope, "x.to_string()")?,
|
||||||
|
"42"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval_with_scope::<String>(&mut scope, "y.to_string()")?,
|
||||||
|
"42"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval_with_scope::<String>(&mut scope, "z.to_string()")?,
|
||||||
|
"42"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_print_debug() -> Result<(), Box<EvalAltResult>> {
|
fn test_print_debug() -> Result<(), Box<EvalAltResult>> {
|
||||||
let logbook = Arc::new(RwLock::new(Vec::<String>::new()));
|
let logbook = Arc::new(RwLock::new(Vec::<String>::new()));
|
||||||
|
Loading…
Reference in New Issue
Block a user