Merge branch 'v1.1-fixes'
This commit is contained in:
commit
61cc3d0bf2
20
CHANGELOG.md
20
CHANGELOG.md
@ -28,6 +28,26 @@ Deprecated API's
|
|||||||
* `From<EvalAltResult>` for `Result<T, Box<EvalAltResult>>` is deprecated so it will no longer be possible to do `EvalAltResult::ErrorXXXXX.into()` to convert to a `Result`; instead, `Err(EvalAltResult:ErrorXXXXX.into())` must be used. Code is clearer if errors are explicitly wrapped in `Err`.
|
* `From<EvalAltResult>` for `Result<T, Box<EvalAltResult>>` is deprecated so it will no longer be possible to do `EvalAltResult::ErrorXXXXX.into()` to convert to a `Result`; instead, `Err(EvalAltResult:ErrorXXXXX.into())` must be used. Code is clearer if errors are explicitly wrapped in `Err`.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.1.3
|
||||||
|
=============
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Reverses a regression on string `+` operations.
|
||||||
|
* The global namespace is now searched before packages, which is the correct behavior.
|
||||||
|
|
||||||
|
|
||||||
|
Version 1.1.2
|
||||||
|
=============
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
* `0.0` now prints correctly (used to print `0e0`).
|
||||||
|
* Unary operators are now properly recognized as an expression statement.
|
||||||
|
|
||||||
|
|
||||||
Version 1.1.1
|
Version 1.1.1
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
@ -1826,7 +1826,9 @@ impl<F: Float + fmt::Debug> fmt::Debug for FloatWrapper<F> {
|
|||||||
impl<F: Float + fmt::Display + fmt::LowerExp + From<f32>> fmt::Display for FloatWrapper<F> {
|
impl<F: Float + fmt::Display + fmt::LowerExp + From<f32>> fmt::Display for FloatWrapper<F> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let abs = self.0.abs();
|
let abs = self.0.abs();
|
||||||
if abs > Self::MAX_NATURAL_FLOAT_FOR_DISPLAY.into()
|
if abs.fract().is_zero() {
|
||||||
|
f.write_str("0.0")
|
||||||
|
} else if abs > Self::MAX_NATURAL_FLOAT_FOR_DISPLAY.into()
|
||||||
|| abs < Self::MIN_NATURAL_FLOAT_FOR_DISPLAY.into()
|
|| abs < Self::MIN_NATURAL_FLOAT_FOR_DISPLAY.into()
|
||||||
{
|
{
|
||||||
write!(f, "{:e}", self.0)
|
write!(f, "{:e}", self.0)
|
||||||
|
@ -26,16 +26,16 @@ impl Engine {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn global_namespace(&self) -> &Module {
|
pub(crate) fn global_namespace(&self) -> &Module {
|
||||||
self.global_modules
|
self.global_modules
|
||||||
.last()
|
.first()
|
||||||
.expect("global_modules contains at least one module")
|
.expect("global_modules contains at least one module")
|
||||||
}
|
}
|
||||||
/// Get a mutable reference to the global namespace module
|
/// Get a mutable reference to the global namespace module
|
||||||
/// (which is the last module in `global_modules`).
|
/// (which is the first module in `global_modules`).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn global_namespace_mut(&mut self) -> &mut Module {
|
pub(crate) fn global_namespace_mut(&mut self) -> &mut Module {
|
||||||
Shared::get_mut(
|
Shared::get_mut(
|
||||||
self.global_modules
|
self.global_modules
|
||||||
.last_mut()
|
.first_mut()
|
||||||
.expect("global_modules contains at least one module"),
|
.expect("global_modules contains at least one module"),
|
||||||
)
|
)
|
||||||
.expect("global namespace module is never shared")
|
.expect("global namespace module is never shared")
|
||||||
@ -894,8 +894,9 @@ impl Engine {
|
|||||||
/// modules are searched in reverse order.
|
/// modules are searched in reverse order.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_global_module(&mut self, module: Shared<Module>) -> &mut Self {
|
pub fn register_global_module(&mut self, module: Shared<Module>) -> &mut Self {
|
||||||
// Insert the module into the front
|
// Insert the module into the front.
|
||||||
self.global_modules.insert(0, module);
|
// The first module is always the global namespace.
|
||||||
|
self.global_modules.insert(1, module);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Register a shared [`Module`] as a static module namespace with the [`Engine`].
|
/// Register a shared [`Module`] as a static module namespace with the [`Engine`].
|
||||||
|
@ -620,7 +620,7 @@ impl Engine {
|
|||||||
|
|
||||||
// First check script-defined functions
|
// First check script-defined functions
|
||||||
let result = lib.iter().any(|&m| m.contains_fn(hash_script))
|
let result = lib.iter().any(|&m| m.contains_fn(hash_script))
|
||||||
// Then check packages
|
// Then check the global namespace and packages
|
||||||
|| self.global_modules.iter().any(|m| m.contains_fn(hash_script))
|
|| self.global_modules.iter().any(|m| m.contains_fn(hash_script))
|
||||||
// Then check imported modules
|
// Then check imported modules
|
||||||
|| mods.map_or(false, |m| m.contains_fn(hash_script))
|
|| mods.map_or(false, |m| m.contains_fn(hash_script))
|
||||||
|
@ -131,6 +131,8 @@ pub struct Module {
|
|||||||
id: Option<Identifier>,
|
id: Option<Identifier>,
|
||||||
/// Is this module internal?
|
/// Is this module internal?
|
||||||
pub(crate) internal: bool,
|
pub(crate) internal: bool,
|
||||||
|
/// Is this module part of a standard library?
|
||||||
|
pub(crate) standard: bool,
|
||||||
/// Sub-modules.
|
/// Sub-modules.
|
||||||
modules: BTreeMap<Identifier, Shared<Module>>,
|
modules: BTreeMap<Identifier, Shared<Module>>,
|
||||||
/// [`Module`] variables.
|
/// [`Module`] variables.
|
||||||
@ -246,6 +248,7 @@ impl Module {
|
|||||||
Self {
|
Self {
|
||||||
id: None,
|
id: None,
|
||||||
internal: false,
|
internal: false,
|
||||||
|
standard: false,
|
||||||
modules: Default::default(),
|
modules: Default::default(),
|
||||||
variables: Default::default(),
|
variables: Default::default(),
|
||||||
all_variables: Default::default(),
|
all_variables: Default::default(),
|
||||||
|
@ -145,12 +145,13 @@ impl<'a> OptimizerState<'a> {
|
|||||||
.map(|(v, _)| v)
|
.map(|(v, _)| v)
|
||||||
}
|
}
|
||||||
// Has a system function a Rust-native override?
|
// Has a system function a Rust-native override?
|
||||||
pub fn has_native_fn(&self, hash_script: u64, arg_types: &[TypeId]) -> bool {
|
pub fn has_native_fn_override(&self, hash_script: u64, arg_types: &[TypeId]) -> bool {
|
||||||
let hash_params = calc_fn_params_hash(arg_types.iter().cloned());
|
let hash_params = calc_fn_params_hash(arg_types.iter().cloned());
|
||||||
let hash = combine_hashes(hash_script, hash_params);
|
let hash = combine_hashes(hash_script, hash_params);
|
||||||
|
|
||||||
// First check packages
|
// First check the global namespace and packages, but skip modules that are standard because
|
||||||
self.engine.global_modules.iter().any(|m| m.contains_fn(hash))
|
// they should never conflict with system functions.
|
||||||
|
self.engine.global_modules.iter().filter(|m| !m.standard).any(|m| m.contains_fn(hash))
|
||||||
// Then check sub-modules
|
// Then check sub-modules
|
||||||
|| self.engine.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash))
|
|| self.engine.global_sub_modules.values().any(|m| m.contains_qualified_fn(hash))
|
||||||
}
|
}
|
||||||
@ -997,7 +998,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Overloaded operators can override built-in.
|
// Overloaded operators can override built-in.
|
||||||
_ if x.args.len() == 2 && !state.has_native_fn(x.hashes.native, arg_types.as_ref()) => {
|
_ if x.args.len() == 2 && !state.has_native_fn_override(x.hashes.native, arg_types.as_ref()) => {
|
||||||
if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
|
if let Some(result) = get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
|
||||||
.and_then(|f| {
|
.and_then(|f| {
|
||||||
let context = (state.engine, x.name.as_ref(), state.lib, Position::NONE).into();
|
let context = (state.engine, x.name.as_ref(), state.lib, Position::NONE).into();
|
||||||
|
@ -177,6 +177,8 @@ macro_rules! reg_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def_package!(crate:ArithmeticPackage:"Basic arithmetic", lib, {
|
def_package!(crate:ArithmeticPackage:"Basic arithmetic", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "int", int_functions);
|
combine_with_exported_module!(lib, "int", int_functions);
|
||||||
reg_functions!(lib += signed_basic; INT);
|
reg_functions!(lib += signed_basic; INT);
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ use std::prelude::v1::*;
|
|||||||
use std::{any::TypeId, cmp::Ordering, mem};
|
use std::{any::TypeId, cmp::Ordering, mem};
|
||||||
|
|
||||||
def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
|
def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "array", array_functions);
|
combine_with_exported_module!(lib, "array", array_functions);
|
||||||
|
|
||||||
// Register array iterator
|
// Register array iterator
|
||||||
|
@ -4,6 +4,8 @@ use crate::{def_package, FnPtr, ImmutableString, NativeCallContext};
|
|||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
|
||||||
def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
|
def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
|
combine_with_exported_module!(lib, "FnPtr", fn_ptr_functions);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -298,6 +298,8 @@ macro_rules! reg_range {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
|
def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
reg_range!(lib | "range" => INT);
|
reg_range!(lib | "range" => INT);
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
@ -43,5 +43,7 @@ mod core_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def_package!(crate:LanguageCorePackage:"Language core functions.", lib, {
|
def_package!(crate:LanguageCorePackage:"Language core functions.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "language_core", core_functions);
|
combine_with_exported_module!(lib, "language_core", core_functions);
|
||||||
});
|
});
|
||||||
|
@ -38,6 +38,8 @@ macro_rules! reg_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def_package!(crate:LogicPackage:"Logical operators.", lib, {
|
def_package!(crate:LogicPackage:"Logical operators.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,8 @@ use std::prelude::v1::*;
|
|||||||
use crate::Array;
|
use crate::Array;
|
||||||
|
|
||||||
def_package!(crate:BasicMapPackage:"Basic object map utilities.", lib, {
|
def_package!(crate:BasicMapPackage:"Basic object map utilities.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "map", map_functions);
|
combine_with_exported_module!(lib, "map", map_functions);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -62,6 +62,8 @@ macro_rules! reg_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, {
|
def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
// Integer functions
|
// Integer functions
|
||||||
combine_with_exported_module!(lib, "int", int_functions);
|
combine_with_exported_module!(lib, "int", int_functions);
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ use std::prelude::v1::*;
|
|||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
|
|
||||||
def_package!(crate:CorePackage:"_Core_ package containing basic facilities.", lib, {
|
def_package!(crate:CorePackage:"_Core_ package containing basic facilities.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
LanguageCorePackage::init(lib);
|
LanguageCorePackage::init(lib);
|
||||||
ArithmeticPackage::init(lib);
|
ArithmeticPackage::init(lib);
|
||||||
LogicPackage::init(lib);
|
LogicPackage::init(lib);
|
||||||
|
@ -13,6 +13,8 @@ use std::prelude::v1::*;
|
|||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
|
|
||||||
def_package!(crate:StandardPackage:"_Standard_ package containing all built-in features.", lib, {
|
def_package!(crate:StandardPackage:"_Standard_ package containing all built-in features.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
CorePackage::init(lib);
|
CorePackage::init(lib);
|
||||||
BasicMathPackage::init(lib);
|
BasicMathPackage::init(lib);
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
@ -16,6 +16,8 @@ pub const FUNC_TO_STRING: &str = "to_string";
|
|||||||
pub const FUNC_TO_DEBUG: &str = "to_debug";
|
pub const FUNC_TO_DEBUG: &str = "to_debug";
|
||||||
|
|
||||||
def_package!(crate:BasicStringPackage:"Basic string utilities, including printing.", lib, {
|
def_package!(crate:BasicStringPackage:"Basic string utilities, including printing.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "print_debug", print_debug_functions);
|
combine_with_exported_module!(lib, "print_debug", print_debug_functions);
|
||||||
combine_with_exported_module!(lib, "number_formatting", number_formatting);
|
combine_with_exported_module!(lib, "number_formatting", number_formatting);
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,8 @@ use std::{any::TypeId, mem};
|
|||||||
use super::string_basic::{print_with_func, FUNC_TO_STRING};
|
use super::string_basic::{print_with_func, FUNC_TO_STRING};
|
||||||
|
|
||||||
def_package!(crate:MoreStringPackage:"Additional string utilities, including string building.", lib, {
|
def_package!(crate:MoreStringPackage:"Additional string utilities, including string building.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
combine_with_exported_module!(lib, "string", string_functions);
|
combine_with_exported_module!(lib, "string", string_functions);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -45,19 +47,28 @@ mod string_functions {
|
|||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "append")]
|
#[rhai_fn(name = "+", name = "append")]
|
||||||
pub fn add_append_str(string1: ImmutableString, string2: ImmutableString) -> ImmutableString {
|
pub fn add_append_str(string1: ImmutableString, string2: ImmutableString) -> ImmutableString {
|
||||||
string1 + string2
|
string1 + string2
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "append")]
|
#[rhai_fn(name = "+", name = "append")]
|
||||||
pub fn add_append_char(string: ImmutableString, character: char) -> ImmutableString {
|
pub fn add_append_char(string: ImmutableString, character: char) -> ImmutableString {
|
||||||
string + character
|
string + character
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "append")]
|
#[rhai_fn(name = "+")]
|
||||||
|
pub fn add_prepend_char(character: char, string: ImmutableString) -> ImmutableString {
|
||||||
|
format!("{}{}", character, string).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rhai_fn(name = "+", name = "append")]
|
||||||
pub fn add_append_unit(string: ImmutableString, item: ()) -> ImmutableString {
|
pub fn add_append_unit(string: ImmutableString, item: ()) -> ImmutableString {
|
||||||
let _item = item;
|
let _item = item;
|
||||||
string
|
string
|
||||||
}
|
}
|
||||||
|
#[rhai_fn(name = "+")]
|
||||||
|
pub fn add_prepend_unit(_item: (), string: ImmutableString) -> ImmutableString {
|
||||||
|
string
|
||||||
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "len", get = "len")]
|
#[rhai_fn(name = "len", get = "len")]
|
||||||
pub fn len(string: &str) -> INT {
|
pub fn len(string: &str) -> INT {
|
||||||
|
@ -16,6 +16,8 @@ use std::time::{Duration, Instant};
|
|||||||
use instant::{Duration, Instant};
|
use instant::{Duration, Instant};
|
||||||
|
|
||||||
def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, {
|
def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, {
|
||||||
|
lib.standard = true;
|
||||||
|
|
||||||
// Register date/time functions
|
// Register date/time functions
|
||||||
combine_with_exported_module!(lib, "time", time_functions);
|
combine_with_exported_module!(lib, "time", time_functions);
|
||||||
});
|
});
|
||||||
|
57
src/token.rs
57
src/token.rs
@ -805,55 +805,56 @@ impl Token {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
LexError(_) |
|
LexError(_) |
|
||||||
LeftBrace | // {+expr} - is unary
|
SemiColon | // ; - is unary
|
||||||
// RightBrace | {expr} - expr not unary & is closing
|
Comma | // ( ... , -expr ) - is unary
|
||||||
LeftParen | // (-expr) - is unary
|
//Period |
|
||||||
// RightParen | (expr) - expr not unary & is closing
|
LeftBrace | // { -expr } - is unary
|
||||||
LeftBracket | // [-expr] - is unary
|
// RightBrace | { expr } - expr not unary & is closing
|
||||||
// RightBracket | [expr] - expr not unary & is closing
|
LeftParen | // ( -expr ) - is unary
|
||||||
|
// RightParen | // ( expr ) - expr not unary & is closing
|
||||||
|
LeftBracket | // [ -expr ] - is unary
|
||||||
|
// RightBracket | // [ expr ] - expr not unary & is closing
|
||||||
Plus |
|
Plus |
|
||||||
|
PlusAssign |
|
||||||
UnaryPlus |
|
UnaryPlus |
|
||||||
Minus |
|
Minus |
|
||||||
|
MinusAssign |
|
||||||
UnaryMinus |
|
UnaryMinus |
|
||||||
Multiply |
|
Multiply |
|
||||||
|
MultiplyAssign |
|
||||||
Divide |
|
Divide |
|
||||||
Comma |
|
DivideAssign |
|
||||||
Period |
|
Modulo |
|
||||||
|
ModuloAssign |
|
||||||
|
PowerOf |
|
||||||
|
PowerOfAssign |
|
||||||
|
LeftShift |
|
||||||
|
LeftShiftAssign |
|
||||||
|
RightShift |
|
||||||
|
RightShiftAssign |
|
||||||
Equals |
|
Equals |
|
||||||
|
EqualsTo |
|
||||||
|
NotEqualsTo |
|
||||||
LessThan |
|
LessThan |
|
||||||
GreaterThan |
|
GreaterThan |
|
||||||
Bang |
|
Bang |
|
||||||
LessThanEqualsTo |
|
LessThanEqualsTo |
|
||||||
GreaterThanEqualsTo |
|
GreaterThanEqualsTo |
|
||||||
EqualsTo |
|
|
||||||
NotEqualsTo |
|
|
||||||
Pipe |
|
Pipe |
|
||||||
Or |
|
|
||||||
Ampersand |
|
Ampersand |
|
||||||
And |
|
|
||||||
If |
|
If |
|
||||||
Do |
|
//Do |
|
||||||
While |
|
While |
|
||||||
Until |
|
Until |
|
||||||
PlusAssign |
|
In |
|
||||||
MinusAssign |
|
And |
|
||||||
MultiplyAssign |
|
|
||||||
DivideAssign |
|
|
||||||
LeftShiftAssign |
|
|
||||||
RightShiftAssign |
|
|
||||||
PowerOf |
|
|
||||||
PowerOfAssign |
|
|
||||||
AndAssign |
|
AndAssign |
|
||||||
|
Or |
|
||||||
OrAssign |
|
OrAssign |
|
||||||
XOrAssign |
|
|
||||||
LeftShift |
|
|
||||||
RightShift |
|
|
||||||
XOr |
|
XOr |
|
||||||
Modulo |
|
XOrAssign |
|
||||||
ModuloAssign |
|
|
||||||
Return |
|
Return |
|
||||||
Throw |
|
Throw => true,
|
||||||
In => true,
|
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use rhai::{Dynamic, Engine, EvalAltResult, NativeCallContext, INT};
|
use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString, NativeCallContext, INT};
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -49,3 +49,41 @@ fn test_native_context_fn_name() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_native_overload() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<String>(r#"let x = "hello, "; let y = "world"; x + y"#)?,
|
||||||
|
"hello, world"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<String>(r#"let x = "hello"; let y = (); x + y"#)?,
|
||||||
|
"hello"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Overload the `+` operator for strings
|
||||||
|
|
||||||
|
engine
|
||||||
|
.register_fn(
|
||||||
|
"+",
|
||||||
|
|s1: ImmutableString, s2: ImmutableString| -> ImmutableString {
|
||||||
|
format!("{}***{}", s1, s2).into()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.register_fn("+", |s1: ImmutableString, _: ()| -> ImmutableString {
|
||||||
|
format!("{} Foo!", s1).into()
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<String>(r#"let x = "hello"; let y = "world"; x + y"#)?,
|
||||||
|
"hello***world"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<String>(r#"let x = "hello"; let y = (); x + y"#)?,
|
||||||
|
"hello Foo!"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user