From dcf5eaf64dd202360405fbff694bbf736bfc142d Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 31 Mar 2020 10:00:17 +0800 Subject: [PATCH] Add `to_string` to prepare for string interpolation. --- README.md | 35 ++++++++++++++++++-------------- src/builtin.rs | 50 ++++++++++++++++++++++++++++++---------------- src/engine.rs | 1 + tests/chars.rs | 2 +- tests/increment.rs | 2 +- tests/string.rs | 22 ++++++++------------ 6 files changed, 64 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 2a73dfb8..719aa523 100644 --- a/README.md +++ b/README.md @@ -261,21 +261,23 @@ Values and types ---------------- [`type_of()`]: #values-and-types +[`to_string()`]: #values-and-types The following primitive types are supported natively: -| Category | Equivalent Rust types | `type_of()` name | -| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------- | -| **Integer number** | `u8`, `i8`, `u16`, `i16`,
`u32`, `i32` (default for [`only_i32`]),
`u64`, `i64` _(default)_ | _same as type_ | -| **Floating-point number** (disabled with [`no_float`]) | `f32`, `f64` _(default)_ | _same as type_ | -| **Boolean value** | `bool` | `"bool"` | -| **Unicode character** | `char` | `"char"` | -| **Unicode string** | `String` (_not_ `&str`) | `"string"` | -| **Array** (disabled with [`no_index`]) | `rhai::Array` | `"array"` | -| **Object map** (disabled with [`no_object`]) | `rhai::Map` | `"map"` | -| **Dynamic value** (i.e. can be anything) | `rhai::Dynamic` | _the actual type_ | -| **System number** (current configuration) | `rhai::INT` (`i32` or `i64`),
`rhai::FLOAT` (`f32` or `f64`) | _same as type_ | -| **Nothing/void/nil/null** (or whatever you want to call it) | `()` | `"()"` | +| Category | Equivalent Rust types | `type_of()` | `to_string()` | +| ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------- | --------------------- | +| **Integer number** | `u8`, `i8`, `u16`, `i16`,
`u32`, `i32` (default for [`only_i32`]),
`u64`, `i64` _(default)_ | `"i32"`, `"u64"` etc. | `"42"`, `"123"` etc. | +| **Floating-point number** (disabled with [`no_float`]) | `f32`, `f64` _(default)_ | `"f32"` or `"f64"` | `"123.4567"` etc. | +| **Boolean value** | `bool` | `"bool"` | `"true"` or `"false"` | +| **Unicode character** | `char` | `"char"` | `"A"`, `"x"` etc. | +| **Unicode string** | `String` (_not_ `&str`) | `"string"` | `"hello"` etc. | +| **Array** (disabled with [`no_index`]) | `rhai::Array` | `"array"` | `"[ ? ? ? ]"` | +| **Object map** (disabled with [`no_object`]) | `rhai::Map` | `"map"` | `#{ "a": 1, "b": 2 }` | +| **Dynamic value** (i.e. can be anything) | `rhai::Dynamic` | _the actual type_ | _actual value_ | +| **System integer** (current configuration) | `rhai::INT` (`i32` or `i64`) | `"i32"` or `"i64"` | `"42"`, `"123"` etc. | +| **System floating-point** (current configuration, disabled with [`no_float`]) | `rhai::FLOAT` (`f32` or `f64`) | `"f32"` or `"f64"` | `"123.456"` etc. | +| **Nothing/void/nil/null** (or whatever you want to call it) | `()` | `"()"` | `""` _(empty string)_ | [`Dynamic`]: #values-and-types [`()`]: #values-and-types @@ -289,7 +291,9 @@ This is useful on some 32-bit systems where using 64-bit integers incurs a perfo If no floating-point is needed or supported, use the [`no_float`] feature to remove it. -There is a `type_of` function to detect the actual type of a value. This is useful because all variables are `Dynamic`. +The `to_string` function converts a standard type into a string for display purposes. + +The `type_of` function detects the actual type of a value. This is useful because all variables are `Dynamic`. ```rust // Use 'type_of()' to get the actual types of values @@ -315,8 +319,9 @@ Value conversions [`to_int`]: #value-conversions [`to_float`]: #value-conversions -There is a `to_float` function to convert a supported number to an `f64`, and a `to_int` function to convert a supported number to `i64` and that's about it. -For other conversions, register custom conversion functions. +The `to_float` function converts a supported number to `FLOAT` (`f32` or `f64`), +and the `to_int` function converts a supported number to `INT` (`i32` or `i64`). +That's about it. For other conversions, register custom conversion functions. ```rust let x = 42; diff --git a/src/builtin.rs b/src/builtin.rs index 754acec0..ae5feb13 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -2,7 +2,7 @@ //! _standard library_ of utility functions. use crate::any::Any; -use crate::engine::Engine; +use crate::engine::{Engine, FUNC_TO_STRING, KEYWORD_DEBUG, KEYWORD_PRINT}; use crate::fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn}; use crate::parser::{Position, INT}; use crate::result::EvalAltResult; @@ -561,10 +561,10 @@ impl Engine<'_> { self.register_fn("==", |_: (), _: ()| true); // () == () // Register print and debug - fn debug(x: T) -> String { + fn to_debug(x: T) -> String { format!("{:?}", x) } - fn print(x: T) -> String { + fn to_string(x: T) -> String { format!("{}", x) } @@ -577,30 +577,39 @@ impl Engine<'_> { ) } - reg_fn1!(self, "print", print, String, INT, bool, char, String); - self.register_fn("print", || "".to_string()); - self.register_fn("print", |_: ()| "".to_string()); - reg_fn1!(self, "debug", debug, String, INT, bool, char, String, ()); + reg_fn1!(self, KEYWORD_PRINT, to_string, String, INT, bool); + reg_fn1!(self, FUNC_TO_STRING, to_string, String, INT, bool); + reg_fn1!(self, KEYWORD_PRINT, to_string, String, char, String); + reg_fn1!(self, FUNC_TO_STRING, to_string, String, char, String); + self.register_fn(KEYWORD_PRINT, || "".to_string()); + self.register_fn(KEYWORD_PRINT, |_: ()| "".to_string()); + self.register_fn(FUNC_TO_STRING, |_: ()| "".to_string()); + reg_fn1!(self, KEYWORD_DEBUG, to_debug, String, INT, bool, ()); + reg_fn1!(self, KEYWORD_DEBUG, to_debug, String, char, String); #[cfg(not(feature = "only_i32"))] #[cfg(not(feature = "only_i64"))] { - reg_fn1!(self, "print", print, String, i8, u8, i16, u16); - reg_fn1!(self, "print", print, String, i32, i64, u32, u64); - reg_fn1!(self, "debug", debug, String, i8, u8, i16, u16); - reg_fn1!(self, "debug", debug, String, i32, i64, u32, u64); + reg_fn1!(self, KEYWORD_PRINT, to_string, String, i8, u8, i16, u16); + reg_fn1!(self, FUNC_TO_STRING, to_string, String, i8, u8, i16, u16); + reg_fn1!(self, KEYWORD_PRINT, to_string, String, i32, i64, u32, u64); + reg_fn1!(self, FUNC_TO_STRING, to_string, String, i32, i64, u32, u64); + reg_fn1!(self, KEYWORD_DEBUG, to_debug, String, i8, u8, i16, u16); + reg_fn1!(self, KEYWORD_DEBUG, to_debug, String, i32, i64, u32, u64); } #[cfg(not(feature = "no_float"))] { - reg_fn1!(self, "print", print, String, f32, f64); - reg_fn1!(self, "debug", debug, String, f32, f64); + reg_fn1!(self, KEYWORD_PRINT, to_string, String, f32, f64); + reg_fn1!(self, FUNC_TO_STRING, to_string, String, f32, f64); + reg_fn1!(self, KEYWORD_DEBUG, to_debug, String, f32, f64); } #[cfg(not(feature = "no_index"))] { - self.register_fn("print", |x: &mut Array| -> String { format!("{:?}", x) }); - self.register_fn("debug", |x: &mut Array| -> String { format!("{:?}", x) }); + reg_fn1!(self, KEYWORD_PRINT, to_debug, String, Array); + reg_fn1!(self, FUNC_TO_STRING, to_debug, String, Array); + reg_fn1!(self, KEYWORD_DEBUG, to_debug, String, Array); // Register array iterator self.register_iterator::(|a| { @@ -610,8 +619,15 @@ impl Engine<'_> { #[cfg(not(feature = "no_object"))] { - self.register_fn("print", |x: &mut Map| -> String { format!("#{:?}", x) }); - self.register_fn("debug", |x: &mut Map| -> String { format!("#{:?}", x) }); + self.register_fn(KEYWORD_PRINT, |x: &mut Map| -> String { + format!("#{:?}", x) + }); + self.register_fn(FUNC_TO_STRING, |x: &mut Map| -> String { + format!("#{:?}", x) + }); + self.register_fn(KEYWORD_DEBUG, |x: &mut Map| -> String { + format!("#{:?}", x) + }); } } diff --git a/src/engine.rs b/src/engine.rs index 4cbff988..67240897 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -42,6 +42,7 @@ pub(crate) const KEYWORD_DEBUG: &str = "debug"; pub(crate) const KEYWORD_DUMP_AST: &str = "dump_ast"; pub(crate) const KEYWORD_TYPE_OF: &str = "type_of"; pub(crate) const KEYWORD_EVAL: &str = "eval"; +pub(crate) const FUNC_TO_STRING: &str = "to_string"; pub(crate) const FUNC_GETTER: &str = "get$"; pub(crate) const FUNC_SETTER: &str = "set$"; diff --git a/tests/chars.rs b/tests/chars.rs index 340cc392..2739401b 100644 --- a/tests/chars.rs +++ b/tests/chars.rs @@ -12,7 +12,7 @@ fn test_chars() -> Result<(), EvalAltResult> { assert_eq!(engine.eval::(r#"let x="hello"; x[2]"#)?, 'l'); assert_eq!( engine.eval::(r#"let y="hello"; y[2]='$'; y"#)?, - "he$lo".to_string() + "he$lo" ); } diff --git a/tests/increment.rs b/tests/increment.rs index 980dda56..72c6eb35 100644 --- a/tests/increment.rs +++ b/tests/increment.rs @@ -7,7 +7,7 @@ fn test_increment() -> Result<(), EvalAltResult> { assert_eq!(engine.eval::("let x = 1; x += 2; x")?, 3); assert_eq!( engine.eval::("let s = \"test\"; s += \"ing\"; s")?, - "testing".to_string() + "testing" ); Ok(()) diff --git a/tests/string.rs b/tests/string.rs index 5d63b88f..92310e33 100644 --- a/tests/string.rs +++ b/tests/string.rs @@ -6,30 +6,24 @@ fn test_string() -> Result<(), EvalAltResult> { assert_eq!( engine.eval::(r#""Test string: \u2764""#)?, - "Test string: ❤".to_string() + "Test string: ❤" ); assert_eq!( engine.eval::(r#""Test string: \x58""#)?, - "Test string: X".to_string() + "Test string: X" ); - assert_eq!( - engine.eval::(r#""foo" + "bar""#)?, - "foobar".to_string() - ); + assert_eq!(engine.eval::(r#""foo" + "bar""#)?, "foobar"); #[cfg(not(feature = "no_stdlib"))] - assert_eq!( - engine.eval::(r#""foo" + 123"#)?, - "foo123".to_string() - ); + assert_eq!(engine.eval::(r#""foo" + 123"#)?, "foo123"); #[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_stdlib"))] - assert_eq!( - engine.eval::(r#""foo" + 123.4556"#)?, - "foo123.4556".to_string() - ); + assert_eq!(engine.eval::(r#""foo" + 123.4556"#)?, "foo123.4556"); + + #[cfg(not(feature = "no_stdlib"))] + assert_eq!(engine.eval::("(42).to_string()")?, "42"); Ok(()) }