Add constant NO_POS.

This commit is contained in:
Stephen Chung 2020-11-02 12:50:27 +08:00
parent 6f3ce96d9d
commit d7d6f74dfd
29 changed files with 253 additions and 292 deletions

View File

@ -22,6 +22,7 @@ Breaking changes
* `EvalAltResult::ErrorAssignmentToUnknownLHS` is moved to `ParseError::AssignmentToInvalidLHS`. `ParseError::AssignmentToCopy` is removed.
* `EvalAltResult::ErrorDataTooLarge` is simplified.
* `Engine::on_progress` closure signature now returns `Option<Dynamic>` with the termination value passed on to `EvalAltResult::ErrorTerminated`.
* `ParseErrorType::BadInput` now wraps a `LexError` instead of a text string.
New features
------------

View File

@ -294,9 +294,8 @@ engine.register_custom_syntax_raw(
"update" | "check" | "add" | "remove" => Ok(Some("$ident$".to_string())),
"cleanup" => Ok(None),
cmd => Err(ParseError(Box::new(ParseErrorType::BadInput(
format!("Improper command: {}", cmd))),
Position::none(),
)),
LexError::ImproperSymbol(format!("Improper command: {}", cmd))
)), NO_POS)),
},
// perform command arg ...
3 => match (stream[1].as_str(), stream[2].as_str()) {
@ -308,9 +307,10 @@ engine.register_custom_syntax_raw(
("add", arg) => Ok(None),
("remove", arg) => Ok(None),
(cmd, arg) => Err(ParseError(Box::new(ParseErrorType::BadInput(
format!("Invalid argument for command {}: {}", cmd, arg))),
Position::none(),
)),
LexError::ImproperSymbol(
format!("Invalid argument for command {}: {}", cmd, arg)
)
)), NO_POS)),
},
_ => unreachable!(),
},
@ -336,7 +336,7 @@ where:
The return value is `Result<Option<String>, ParseError>` where:
| Value | Description |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Ok(None)` | parsing complete and there are no more symbols to match |
| `Ok(Some(symbol))` | next symbol to match, which can also be `"$expr$"`, `"$ident$"` or `"$block$"` |
| `Err(ParseError)` | error that is reflected back to the [`Engine`].<br/>Normally this is `ParseError(ParseErrorType::BadInput(message), Position::none())` to indicate that there is a syntax error, but it can be any `ParseError`. |
| `Err(ParseError)` | error that is reflected back to the [`Engine`].<br/>Normally this is `ParseError(ParseErrorType::BadInput(LexError::ImproperSymbol(message)), NO_POS)` to indicate that there is a syntax error, but it can be any `ParseError`. |

View File

@ -21,11 +21,11 @@ engine.on_var(|name, index, context| {
"MYSTIC_NUMBER" => Ok(Some((42 as INT).into())),
// Override a variable - make it not found even if it exists!
"DO_NOT_USE" => Err(Box::new(
EvalAltResult::ErrorVariableNotFound(name.to_string(), Position::none())
EvalAltResult::ErrorVariableNotFound(name.to_string(), NO_POS)
)),
// Silently maps 'chameleon' into 'innocent'.
"chameleon" => context.scope.get_value("innocent").map(Some).ok_or_else(|| Box::new(
EvalAltResult::ErrorVariableNotFound(name.to_string(), Position::none())
EvalAltResult::ErrorVariableNotFound(name.to_string(), NO_POS)
)),
// Return Ok(None) to continue with the normal variable resolution process.
_ => Ok(None)
@ -83,7 +83,7 @@ where:
The return value is `Result<Option<Dynamic>, Box<EvalAltResult>>` where:
| Value | Description |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Ok(None)` | normal variable resolution process should continue, i.e. continue searching through the [`Scope`] |
| `Ok(Some(Dynamic))` | value of the variable, treated as a constant |
| `Err(Box<EvalAltResult>)` | error that is reflected back to the [`Engine`].<br/>Normally this is `EvalAltResult::ErrorVariableNotFound(var_name, Position::none())` to indicate that the variable does not exist, but it can be any `EvalAltResult`. |
| `Err(Box<EvalAltResult>)` | error that is reflected back to the [`Engine`].<br/>Normally this is `EvalAltResult::ErrorVariableNotFound(var_name, NO_POS)` to indicate that the variable does not exist, but it can be any `EvalAltResult`. |

View File

@ -117,7 +117,7 @@ pub fn greet(context: NativeCallContext, callback: FnPtr)
The native call context is also useful in another scenario: protecting a function from malicious scripts.
```rust
use rhai::{Dynamic, Array, NativeCallContext, EvalAltResult, Position};
use rhai::{Dynamic, Array, NativeCallContext, EvalAltResult, NO_POS};
use rhai::plugin::*; // a "prelude" import for macros
// This function builds an array of arbitrary size, but is protected
@ -137,7 +137,7 @@ pub fn grow(context: NativeCallContext, size: i64)
"Size to grow".to_string(),
context.engine().max_array_size(),
size as usize,
Position::none(),
NO_POS,
).into();
}

View File

@ -376,7 +376,7 @@ mod my_module {
The native call context is also useful in another scenario: protecting a function from malicious scripts.
```rust
use rhai::{Dynamic, Array, NativeCallContext, EvalAltResult, Position};
use rhai::{Dynamic, Array, NativeCallContext, EvalAltResult, NO_POS};
use rhai::plugin::*; // a "prelude" import for macros
#[export_module]
@ -397,7 +397,7 @@ mod my_module {
"Size to grow".to_string(),
context.engine().max_array_size(),
size as usize,
Position::none(),
NO_POS,
).into();
}

View File

@ -11,7 +11,7 @@ use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
use crate::result::EvalAltResult;
use crate::scope::{EntryType as ScopeEntryType, Scope};
use crate::syntax::CustomSyntax;
use crate::token::Position;
use crate::token::{Position, NO_POS};
use crate::{calc_native_fn_hash, StaticVec};
#[cfg(not(feature = "no_index"))]
@ -351,7 +351,7 @@ impl<'a> Target<'a> {
#[cfg(not(feature = "no_index"))]
Self::StringChar(_, _, ch) => {
let char_value = ch.clone();
self.set_value((char_value, Position::none())).unwrap();
self.set_value((char_value, NO_POS)).unwrap();
}
}
}
@ -993,7 +993,7 @@ impl Engine {
{
EvalAltResult::ErrorIndexingType(
self.map_type_name(val_type_name).into(),
Position::none(),
NO_POS,
)
}
err => err,
@ -1463,20 +1463,16 @@ impl Engine {
.map(|(v, _)| v.into())
.map_err(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.ends_with(']') => {
Box::new(EvalAltResult::ErrorIndexingType(
type_name.into(),
Position::none(),
))
Box::new(EvalAltResult::ErrorIndexingType(type_name.into(), NO_POS))
}
_ => err,
})
}
_ => EvalAltResult::ErrorIndexingType(
self.map_type_name(val.type_name()).into(),
Position::none(),
)
.into(),
_ => {
EvalAltResult::ErrorIndexingType(self.map_type_name(val.type_name()).into(), NO_POS)
.into()
}
}
}
@ -2036,7 +2032,7 @@ impl Engine {
let value = if let EvalAltResult::ErrorRuntime(ref x, _) = err {
x.clone()
} else {
err.set_position(Position::none());
err.set_position(NO_POS);
err.to_string().into()
};
@ -2298,25 +2294,17 @@ impl Engine {
let (_arr, _map, s) = calc_size(result.as_ref().unwrap());
if s > self.max_string_size() {
return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(),
Position::none(),
)
.into();
return EvalAltResult::ErrorDataTooLarge("Length of string".to_string(), NO_POS).into();
}
#[cfg(not(feature = "no_index"))]
if _arr > self.max_array_size() {
return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), Position::none())
.into();
return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), NO_POS).into();
}
#[cfg(not(feature = "no_object"))]
if _map > self.max_map_size() {
return EvalAltResult::ErrorDataTooLarge(
"Size of object map".to_string(),
Position::none(),
)
return EvalAltResult::ErrorDataTooLarge("Size of object map".to_string(), NO_POS)
.into();
}
@ -2331,14 +2319,14 @@ impl Engine {
#[cfg(not(feature = "unchecked"))]
// Guard against too many operations
if self.max_operations() > 0 && state.operations > self.max_operations() {
return EvalAltResult::ErrorTooManyOperations(Position::none()).into();
return EvalAltResult::ErrorTooManyOperations(NO_POS).into();
}
// Report progress - only in steps
if let Some(progress) = &self.progress {
if let Some(token) = progress(&state.operations) {
// Terminate script if progress returns a termination token
return EvalAltResult::ErrorTerminated(token, Position::none()).into();
return EvalAltResult::ErrorTerminated(token, NO_POS).into();
}
}

View File

@ -8,7 +8,7 @@ use crate::optimize::OptimizationLevel;
use crate::parse_error::ParseError;
use crate::result::EvalAltResult;
use crate::scope::Scope;
use crate::token::Position;
use crate::token::{Position, NO_POS};
#[cfg(not(feature = "no_index"))]
use crate::{
@ -1391,7 +1391,7 @@ impl Engine {
EvalAltResult::ErrorMismatchOutputType(
self.map_type_name(type_name::<T>()).into(),
typ.into(),
Position::none(),
NO_POS,
)
.into()
});
@ -1527,7 +1527,7 @@ impl Engine {
EvalAltResult::ErrorMismatchOutputType(
self.map_type_name(type_name::<T>()).into(),
typ.into(),
Position::none(),
NO_POS,
)
.into()
});
@ -1617,7 +1617,7 @@ impl Engine {
) -> Result<Dynamic, Box<EvalAltResult>> {
let fn_def = lib
.get_script_fn(name, args.len(), true)
.ok_or_else(|| EvalAltResult::ErrorFunctionNotFound(name.into(), Position::none()))?;
.ok_or_else(|| EvalAltResult::ErrorFunctionNotFound(name.into(), NO_POS))?;
let mut state = Default::default();
let mut mods = Default::default();

View File

@ -14,7 +14,7 @@ use crate::parse_error::ParseErrorType;
use crate::result::EvalAltResult;
use crate::scope::Scope;
use crate::stdlib::ops::Deref;
use crate::token::Position;
use crate::token::NO_POS;
use crate::utils::ImmutableString;
use crate::{calc_native_fn_hash, calc_script_fn_hash, StaticVec, INT};
@ -159,7 +159,7 @@ pub fn ensure_no_data_race(
{
return EvalAltResult::ErrorDataRace(
format!("argument #{} of function '{}'", n + 1 + skip, fn_name),
Position::none(),
NO_POS,
)
.into();
}
@ -223,7 +223,7 @@ impl Engine {
EvalAltResult::ErrorMismatchOutputType(
self.map_type_name(type_name::<ImmutableString>()).into(),
typ.into(),
Position::none(),
NO_POS,
)
})?)
.into(),
@ -234,7 +234,7 @@ impl Engine {
EvalAltResult::ErrorMismatchOutputType(
self.map_type_name(type_name::<ImmutableString>()).into(),
typ.into(),
Position::none(),
NO_POS,
)
})?)
.into(),
@ -265,7 +265,7 @@ impl Engine {
prop,
self.map_type_name(args[0].type_name())
),
Position::none(),
NO_POS,
)
.into();
}
@ -279,7 +279,7 @@ impl Engine {
self.map_type_name(args[0].type_name()),
self.map_type_name(args[1].type_name()),
),
Position::none(),
NO_POS,
)
.into();
}
@ -293,7 +293,7 @@ impl Engine {
self.map_type_name(args[0].type_name()),
self.map_type_name(args[1].type_name()),
),
Position::none(),
NO_POS,
)
.into();
}
@ -307,7 +307,7 @@ impl Engine {
self.map_type_name(args[0].type_name()),
self.map_type_name(args[1].type_name()),
),
Position::none(),
NO_POS,
)
.into();
}
@ -326,7 +326,7 @@ impl Engine {
.collect::<Vec<_>>()
.join(", ")
),
Position::none(),
NO_POS,
)
.into()
}
@ -357,9 +357,7 @@ impl Engine {
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "unchecked"))]
if level > self.max_call_levels() {
return Err(Box::new(
EvalAltResult::ErrorStackOverflow(Position::none()),
));
return Err(Box::new(EvalAltResult::ErrorStackOverflow(NO_POS)));
}
let orig_scope_level = state.scope_level;
@ -396,8 +394,8 @@ impl Engine {
// Evaluate the function at one higher level of call depth
let stmt = &fn_def.body;
let result = self
.eval_stmt(scope, mods, state, unified_lib, this_ptr, stmt, level + 1)
let result =
self.eval_stmt(scope, mods, state, unified_lib, this_ptr, stmt, level + 1)
.or_else(|err| match *err {
// Convert return statement to return value
EvalAltResult::Return(x, _) => Ok(x),
@ -405,18 +403,14 @@ impl Engine {
EvalAltResult::ErrorInFunctionCall(
format!("{} > {}", fn_def.name, name),
err,
Position::none(),
NO_POS,
)
.into()
}
// System errors are passed straight-through
err if err.is_system_exception() => Err(Box::new(err)),
// Other errors are wrapped in `ErrorInFunctionCall`
_ => EvalAltResult::ErrorInFunctionCall(
fn_def.name.to_string(),
err,
Position::none(),
)
_ => EvalAltResult::ErrorInFunctionCall(fn_def.name.to_string(), err, NO_POS)
.into(),
});
@ -519,7 +513,7 @@ impl Engine {
fn_name, fn_name
)
.into(),
Position::none(),
NO_POS,
)
.into()
}
@ -656,9 +650,7 @@ impl Engine {
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "unchecked"))]
if _level > self.max_call_levels() {
return Err(Box::new(
EvalAltResult::ErrorStackOverflow(Position::none()),
));
return Err(Box::new(EvalAltResult::ErrorStackOverflow(NO_POS)));
}
// Compile the script text
@ -1218,7 +1210,7 @@ impl Engine {
.collect::<Vec<_>>()
.join(", ")
),
Position::none(),
NO_POS,
)
.into(),
}

View File

@ -6,7 +6,7 @@ use crate::engine::{Engine, EvalContext};
use crate::module::Module;
use crate::plugin::PluginFunction;
use crate::result::EvalAltResult;
use crate::token::{is_valid_identifier, Position};
use crate::token::{is_valid_identifier, NO_POS};
use crate::utils::ImmutableString;
use crate::{calc_script_fn_hash, StaticVec};
@ -215,7 +215,7 @@ impl TryFrom<ImmutableString> for FnPtr {
if is_valid_identifier(value.chars()) {
Ok(Self(value, Default::default()))
} else {
EvalAltResult::ErrorFunctionNotFound(value.into(), Position::none()).into()
EvalAltResult::ErrorFunctionNotFound(value.into(), NO_POS).into()
}
}
}

View File

@ -115,11 +115,11 @@ pub use engine::{Engine, EvalContext};
pub use fn_native::{FnPtr, NativeCallContext};
pub use fn_register::{RegisterFn, RegisterResultFn};
pub use module::Module;
pub use parse_error::{ParseError, ParseErrorType};
pub use parse_error::{LexError, ParseError, ParseErrorType};
pub use result::EvalAltResult;
pub use scope::Scope;
pub use syntax::Expression;
pub use token::Position;
pub use token::{Position, NO_POS};
pub use utils::ImmutableString;
#[cfg(feature = "internals")]

View File

@ -5,7 +5,7 @@ use crate::dynamic::{Dynamic, Variant};
use crate::fn_native::{CallableFunction, FnCallArgs, IteratorFn, NativeCallContext, SendSync};
use crate::fn_register::by_value as cast_arg;
use crate::result::EvalAltResult;
use crate::token::{Position, Token};
use crate::token::{Token, NO_POS};
use crate::utils::{ImmutableString, StraightHasherBuilder};
use crate::{calc_native_fn_hash, calc_script_fn_hash, StaticVec};
@ -271,11 +271,11 @@ impl Module {
hash_var: u64,
) -> Result<&mut Dynamic, Box<EvalAltResult>> {
if hash_var == 0 {
Err(EvalAltResult::ErrorVariableNotFound(String::new(), Position::none()).into())
Err(EvalAltResult::ErrorVariableNotFound(String::new(), NO_POS).into())
} else {
self.all_variables.get_mut(&hash_var).ok_or_else(|| {
EvalAltResult::ErrorVariableNotFound(String::new(), Position::none()).into()
})
self.all_variables
.get_mut(&hash_var)
.ok_or_else(|| EvalAltResult::ErrorVariableNotFound(String::new(), NO_POS).into())
}
}

View File

@ -10,7 +10,7 @@ use crate::fn_call::run_builtin_binary_op;
use crate::module::Module;
use crate::parser::map_dynamic_to_expr;
use crate::scope::Scope;
use crate::token::{is_valid_identifier, Position};
use crate::token::{is_valid_identifier, NO_POS};
use crate::{calc_native_fn_hash, StaticVec};
#[cfg(not(feature = "no_function"))]
@ -726,7 +726,7 @@ fn optimize(
.iter()
.filter(|(_, typ, _)| *typ)
.for_each(|(name, _, value)| {
if let Some(val) = map_dynamic_to_expr(value, Position::none()) {
if let Some(val) = map_dynamic_to_expr(value, NO_POS) {
state.push_constant(name, val);
}
});

View File

@ -4,7 +4,7 @@ use crate::def_package;
use crate::plugin::*;
use crate::INT;
use crate::{result::EvalAltResult, token::Position};
use crate::{result::EvalAltResult, token::NO_POS};
#[cfg(not(feature = "no_float"))]
use crate::FLOAT;
@ -17,7 +17,7 @@ use crate::stdlib::{format, string::String};
#[inline(always)]
pub fn make_err(msg: impl Into<String>) -> Box<EvalAltResult> {
EvalAltResult::ErrorArithmetic(msg.into(), Position::none()).into()
EvalAltResult::ErrorArithmetic(msg.into(), NO_POS).into()
}
macro_rules! gen_arithmetic_functions {

View File

@ -7,7 +7,7 @@ use crate::engine::Array;
use crate::fn_native::{FnPtr, NativeCallContext};
use crate::plugin::*;
use crate::result::EvalAltResult;
use crate::token::Position;
use crate::token::NO_POS;
use crate::utils::ImmutableString;
use crate::INT;
@ -46,7 +46,7 @@ macro_rules! gen_array_functions {
#[cfg(not(feature = "unchecked"))]
if _ctx.engine().max_array_size() > 0 && len > 0 && (len as usize) > _ctx.engine().max_array_size() {
return EvalAltResult::ErrorDataTooLarge(
"Size of array".to_string(), Position::none()
"Size of array".to_string(), NO_POS
).into();
}
@ -219,7 +219,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"map".to_string(),
err,
Position::none(),
NO_POS,
))
})?,
);
@ -250,7 +250,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"filter".to_string(),
err,
Position::none(),
NO_POS,
))
})?
.as_bool()
@ -283,7 +283,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"filter".to_string(),
err,
Position::none(),
NO_POS,
))
})?
.as_bool()
@ -316,7 +316,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"filter".to_string(),
err,
Position::none(),
NO_POS,
))
})?
.as_bool()
@ -351,7 +351,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"reduce".to_string(),
err,
Position::none(),
NO_POS,
))
})?;
}
@ -369,7 +369,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"reduce".to_string(),
err,
Position::none(),
NO_POS,
))
})?;
@ -388,7 +388,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"reduce".to_string(),
err,
Position::none(),
NO_POS,
))
})?;
}
@ -418,7 +418,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"reduce".to_string(),
err,
Position::none(),
NO_POS,
))
})?;
}
@ -436,7 +436,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"reduce".to_string(),
err,
Position::none(),
NO_POS,
))
})?;
@ -455,7 +455,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"reduce".to_string(),
err,
Position::none(),
NO_POS,
))
})?;
}
@ -525,7 +525,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"filter".to_string(),
err,
Position::none(),
NO_POS,
))
})?
.as_bool()
@ -584,7 +584,7 @@ mod array_functions {
Box::new(EvalAltResult::ErrorInFunctionCall(
"filter".to_string(),
err,
Position::none(),
NO_POS,
))
})?
.as_bool()

View File

@ -2,7 +2,7 @@
use crate::def_package;
use crate::plugin::*;
use crate::token::Position;
use crate::token::NO_POS;
use crate::INT;
#[cfg(not(feature = "no_float"))]
@ -85,10 +85,7 @@ mod int_functions {
#[rhai_fn(name = "parse_int", return_raw)]
pub fn parse_int_radix(s: &str, radix: INT) -> Result<Dynamic, Box<EvalAltResult>> {
if radix < 2 || radix > 36 {
return EvalAltResult::ErrorArithmetic(
format!("Invalid radix: '{}'", radix),
Position::none(),
)
return EvalAltResult::ErrorArithmetic(format!("Invalid radix: '{}'", radix), NO_POS)
.into();
}
@ -97,7 +94,7 @@ mod int_functions {
.map_err(|err| {
EvalAltResult::ErrorArithmetic(
format!("Error parsing integer number '{}': {}", s, err),
Position::none(),
NO_POS,
)
.into()
})
@ -206,10 +203,7 @@ mod float_functions {
#[rhai_fn(name = "to_int", return_raw)]
pub fn f32_to_int(x: f32) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f32) {
EvalAltResult::ErrorArithmetic(
format!("Integer overflow: to_int({})", x),
Position::none(),
)
EvalAltResult::ErrorArithmetic(format!("Integer overflow: to_int({})", x), NO_POS)
.into()
} else {
Ok((x.trunc() as INT).into())
@ -218,10 +212,7 @@ mod float_functions {
#[rhai_fn(name = "to_int", return_raw)]
pub fn f64_to_int(x: f64) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f64) {
EvalAltResult::ErrorArithmetic(
format!("Integer overflow: to_int({})", x),
Position::none(),
)
EvalAltResult::ErrorArithmetic(format!("Integer overflow: to_int({})", x), NO_POS)
.into()
} else {
Ok((x.trunc() as INT).into())
@ -235,7 +226,7 @@ mod float_functions {
.map_err(|err| {
EvalAltResult::ErrorArithmetic(
format!("Error parsing floating-point number '{}': {}", s, err),
Position::none(),
NO_POS,
)
.into()
})

View File

@ -9,7 +9,7 @@ use crate::StaticVec;
use crate::INT;
#[cfg(not(feature = "unchecked"))]
use crate::{result::EvalAltResult, token::Position};
use crate::{result::EvalAltResult, token::NO_POS};
use crate::stdlib::{
any::TypeId, boxed::Box, format, mem, string::String, string::ToString, vec::Vec,
@ -259,11 +259,7 @@ mod string_functions {
// Check if string will be over max size limit
#[cfg(not(feature = "unchecked"))]
if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() {
return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(),
Position::none(),
)
.into();
return EvalAltResult::ErrorDataTooLarge("Length of string".to_string(), NO_POS).into();
}
if len > 0 {
@ -281,7 +277,7 @@ mod string_functions {
{
return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(),
Position::none(),
NO_POS,
)
.into();
}
@ -300,11 +296,7 @@ mod string_functions {
// Check if string will be over max size limit
#[cfg(not(feature = "unchecked"))]
if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() {
return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(),
Position::none(),
)
.into();
return EvalAltResult::ErrorDataTooLarge("Length of string".to_string(), NO_POS).into();
}
if len > 0 {
@ -329,7 +321,7 @@ mod string_functions {
{
return EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(),
Position::none(),
NO_POS,
)
.into();
}

View File

@ -1,7 +1,7 @@
//! Module containing error definitions for the parsing process.
use crate::result::EvalAltResult;
use crate::token::Position;
use crate::token::{Position, NO_POS};
use crate::stdlib::{
boxed::Box,
@ -43,26 +43,34 @@ impl fmt::Display for LexError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::UnexpectedInput(s) => write!(f, "Unexpected '{}'", s),
Self::MalformedEscapeSequence(s) => write!(f, "Invalid escape sequence: '{}'", s),
Self::MalformedNumber(s) => write!(f, "Invalid number: '{}'", s),
Self::MalformedChar(s) => write!(f, "Invalid character: '{}'", s),
Self::MalformedIdentifier(s) => write!(f, "Variable name is not proper: '{}'", s),
Self::UnterminatedString => write!(f, "Open string is not terminated"),
Self::StringTooLong(max) => write!(
f,
"Length of string literal exceeds the maximum limit ({})",
max
),
Self::MalformedEscapeSequence(s) => write!(f, "{}: '{}'", self.desc(), s),
Self::MalformedNumber(s) => write!(f, "{}: '{}'", self.desc(), s),
Self::MalformedChar(s) => write!(f, "{}: '{}'", self.desc(), s),
Self::MalformedIdentifier(s) => write!(f, "{}: '{}'", self.desc(), s),
Self::UnterminatedString => f.write_str(self.desc()),
Self::StringTooLong(max) => write!(f, "{} ({})", self.desc(), max),
Self::ImproperSymbol(s) => f.write_str(s),
}
}
}
impl LexError {
/// Convert a `LexError` into a `ParseError`.
pub(crate) fn desc(&self) -> &str {
match self {
Self::UnexpectedInput(_) => "Unexpected character encountered",
Self::UnterminatedString => "Open string is not terminated",
Self::StringTooLong(_) => "Length of string literal exceeds the maximum limit",
Self::MalformedEscapeSequence(_) => "Invalid escape sequence",
Self::MalformedNumber(_) => "Invalid number",
Self::MalformedChar(_) => "Invalid character",
Self::MalformedIdentifier(_) => "Variable name is not proper",
Self::ImproperSymbol(_) => "Invalid symbol encountered",
}
}
/// Convert a `&LexError` into a `ParseError`.
#[inline(always)]
pub fn into_err(&self, pos: Position) -> ParseError {
ParseError(Box::new(self.into()), pos)
ParseError(Box::new(self.clone().into()), pos)
}
}
@ -74,10 +82,10 @@ impl LexError {
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
#[non_exhaustive]
pub enum ParseErrorType {
/// Error in the script text. Wrapped value is the error message.
BadInput(String),
/// The script ends prematurely.
UnexpectedEOF,
/// Error in the script text. Wrapped value is the lex error.
BadInput(LexError),
/// An unknown operator is encountered. Wrapped value is the operator.
UnknownOperator(String),
/// Expecting a particular token but not finding one. Wrapped values are the token and description.
@ -164,8 +172,8 @@ impl ParseErrorType {
pub(crate) fn desc(&self) -> &str {
match self {
Self::BadInput(p) => p,
Self::UnexpectedEOF => "Script is incomplete",
Self::BadInput(p) => p.desc(),
Self::UnknownOperator(_) => "Unknown operator",
Self::MissingToken(_, _) => "Expecting a certain token that is missing",
Self::MalformedCallExpr(_) => "Invalid expression in function call arguments",
@ -196,9 +204,9 @@ impl ParseErrorType {
impl fmt::Display for ParseErrorType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::BadInput(s) | ParseErrorType::MalformedCallExpr(s) => {
f.write_str(if s.is_empty() { self.desc() } else { s })
}
Self::BadInput(err) => write!(f, "{}", err),
Self::MalformedCallExpr(s) => f.write_str(if s.is_empty() { self.desc() } else { s }),
Self::UnknownOperator(s) => write!(f, "{}: '{}'", self.desc(), s),
Self::MalformedIndexExpr(s) | Self::MalformedInExpr(s) | Self::MalformedCapture(s) => {
@ -247,14 +255,14 @@ impl fmt::Display for ParseErrorType {
}
}
impl From<&LexError> for ParseErrorType {
impl From<LexError> for ParseErrorType {
#[inline(always)]
fn from(err: &LexError) -> Self {
fn from(err: LexError) -> Self {
match err {
LexError::StringTooLong(max) => {
Self::LiteralTooLarge("Length of string literal".to_string(), *max)
Self::LiteralTooLarge("Length of string literal".to_string(), max)
}
_ => Self::BadInput(err.to_string()),
_ => Self::BadInput(err),
}
}
}
@ -282,7 +290,7 @@ impl fmt::Display for ParseError {
impl From<ParseErrorType> for Box<EvalAltResult> {
#[inline(always)]
fn from(err: ParseErrorType) -> Self {
Box::new(EvalAltResult::ErrorParsing(err, Position::none()))
Box::new(EvalAltResult::ErrorParsing(err, NO_POS))
}
}

View File

@ -10,7 +10,9 @@ use crate::optimize::{optimize_into_ast, OptimizationLevel};
use crate::parse_error::{LexError, ParseError, ParseErrorType};
use crate::scope::{EntryType as ScopeEntryType, Scope};
use crate::syntax::CustomSyntax;
use crate::token::{is_keyword_function, is_valid_identifier, Position, Token, TokenStream};
use crate::token::{
is_keyword_function, is_valid_identifier, Position, Token, TokenStream, NO_POS,
};
use crate::utils::StraightHasherBuilder;
use crate::{calc_script_fn_hash, StaticVec};
@ -816,10 +818,11 @@ fn parse_primary(
// Access to `this` as a variable is OK
Token::Reserved(s) if s == KEYWORD_THIS && *next_token != Token::LeftParen => {
if !settings.is_function_scope {
return Err(
PERR::BadInput(format!("'{}' can only be used in functions", s))
.into_err(settings.pos),
);
return Err(PERR::BadInput(LexError::ImproperSymbol(format!(
"'{}' can only be used in functions",
s
)))
.into_err(settings.pos));
} else {
Expr::Variable(Box::new((Ident::new(s, settings.pos), None, 0, None)))
}
@ -840,7 +843,8 @@ fn parse_primary(
_ => {
return Err(
PERR::BadInput(format!("Unexpected '{}'", token.syntax())).into_err(settings.pos)
PERR::BadInput(LexError::UnexpectedInput(token.syntax().to_string()))
.into_err(settings.pos),
);
}
};
@ -862,7 +866,9 @@ fn parse_primary(
return Err(if !match_token(input, Token::LeftParen).0 {
LexError::UnexpectedInput(Token::Bang.syntax().to_string()).into_err(token_pos)
} else {
PERR::BadInput("'!' cannot be used to call module functions".to_string())
PERR::BadInput(LexError::ImproperSymbol(
"'!' cannot be used to call module functions".to_string(),
))
.into_err(token_pos)
});
}
@ -1140,9 +1146,10 @@ fn make_assignment_stmt<'a>(
Err(PERR::AssignmentToConstant("".into()).into_err(lhs.position()))
}
// ??? && ??? = rhs, ??? || ??? = rhs
Expr::And(_, _) | Expr::Or(_, _) => {
Err(PERR::BadInput("Possibly a typo of '=='?".to_string()).into_err(pos))
}
Expr::And(_, _) | Expr::Or(_, _) => Err(PERR::BadInput(LexError::ImproperSymbol(
"Possibly a typo of '=='?".to_string(),
))
.into_err(pos)),
// expr = rhs
_ => Err(PERR::AssignmentToInvalidLHS("".to_string()).into_err(lhs.position())),
}
@ -1238,10 +1245,10 @@ fn make_dot_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result<Expr, ParseEr
(_, Expr::FnCall(x, pos))
if x.args.len() == 0 && [KEYWORD_FN_PTR, KEYWORD_EVAL].contains(&x.name.as_ref()) =>
{
return Err(PERR::BadInput(format!(
return Err(PERR::BadInput(LexError::ImproperSymbol(format!(
"'{}' should not be called in method style. Try {}(...);",
x.name, x.name
))
)))
.into_err(pos));
}
// lhs.func!(...)
@ -1734,9 +1741,10 @@ fn ensure_not_statement_expr(input: &mut TokenStream, type_name: &str) -> Result
/// Make sure that the expression is not a mis-typed assignment (i.e. `a = b` instead of `a == b`).
fn ensure_not_assignment(input: &mut TokenStream) -> Result<(), ParseError> {
match input.peek().unwrap() {
(Token::Equals, pos) => {
Err(PERR::BadInput("Possibly a typo of '=='?".to_string()).into_err(*pos))
}
(Token::Equals, pos) => Err(PERR::BadInput(LexError::ImproperSymbol(
"Possibly a typo of '=='?".to_string(),
))
.into_err(*pos)),
(Token::PlusAssign, pos)
| (Token::MinusAssign, pos)
| (Token::MultiplyAssign, pos)
@ -1747,9 +1755,9 @@ fn ensure_not_assignment(input: &mut TokenStream) -> Result<(), ParseError> {
| (Token::PowerOfAssign, pos)
| (Token::AndAssign, pos)
| (Token::OrAssign, pos)
| (Token::XOrAssign, pos) => Err(PERR::BadInput(
| (Token::XOrAssign, pos) => Err(PERR::BadInput(LexError::ImproperSymbol(
"Expecting a boolean expression, not an assignment".to_string(),
)
))
.into_err(*pos)),
_ => Ok(()),
@ -2683,7 +2691,7 @@ impl Engine {
is_function_scope: false,
is_breakable: false,
level: 0,
pos: Position::none(),
pos: NO_POS,
};
let expr = parse_expr(input, &mut state, &mut functions, settings)?;
@ -2694,7 +2702,8 @@ impl Engine {
// Return error if the expression doesn't end
(token, pos) => {
return Err(
PERR::BadInput(format!("Unexpected '{}'", token.syntax())).into_err(*pos)
PERR::BadInput(LexError::UnexpectedInput(token.syntax().to_string()))
.into_err(*pos),
)
}
}
@ -2732,7 +2741,7 @@ impl Engine {
is_function_scope: false,
is_breakable: false,
level: 0,
pos: Position::none(),
pos: NO_POS,
};
let stmt = match parse_stmt(input, &mut state, &mut functions, settings)? {

View File

@ -2,7 +2,7 @@
use crate::dynamic::Dynamic;
use crate::parse_error::ParseErrorType;
use crate::token::Position;
use crate::token::{Position, NO_POS};
use crate::utils::ImmutableString;
use crate::INT;
@ -252,7 +252,7 @@ impl fmt::Display for EvalAltResult {
impl<T: AsRef<str>> From<T> for EvalAltResult {
#[inline(always)]
fn from(err: T) -> Self {
Self::ErrorRuntime(err.as_ref().to_string().into(), Position::none())
Self::ErrorRuntime(err.as_ref().to_string().into(), NO_POS)
}
}
@ -261,7 +261,7 @@ impl<T: AsRef<str>> From<T> for Box<EvalAltResult> {
fn from(err: T) -> Self {
Box::new(EvalAltResult::ErrorRuntime(
err.as_ref().to_string().into(),
Position::none(),
NO_POS,
))
}
}
@ -324,7 +324,7 @@ impl EvalAltResult {
/// Get the `Position` of this error.
pub fn position(&self) -> Position {
match self {
Self::ErrorSystem(_, _) => Position::none(),
Self::ErrorSystem(_, _) => NO_POS,
Self::ErrorParsing(_, pos)
| Self::ErrorFunctionNotFound(_, pos)

View File

@ -4,7 +4,7 @@ use super::str::ImmutableStringDeserializer;
use crate::dynamic::{Dynamic, Union};
use crate::parse_error::ParseErrorType;
use crate::result::EvalAltResult;
use crate::token::Position;
use crate::token::NO_POS;
use crate::utils::ImmutableString;
use serde::de::{
@ -45,11 +45,7 @@ impl<'de> DynamicDeserializer<'de> {
}
/// Shortcut for a type conversion error.
fn type_error_str<T>(&self, error: &str) -> Result<T, Box<EvalAltResult>> {
EvalAltResult::ErrorMismatchOutputType(
error.into(),
self.value.type_name().into(),
Position::none(),
)
EvalAltResult::ErrorMismatchOutputType(error.into(), self.value.type_name().into(), NO_POS)
.into()
}
fn deserialize_int<V: Visitor<'de>>(
@ -127,7 +123,10 @@ pub fn from_dynamic<'de, T: Deserialize<'de>>(
impl Error for Box<EvalAltResult> {
fn custom<T: fmt::Display>(err: T) -> Self {
EvalAltResult::ErrorParsing(ParseErrorType::BadInput(err.to_string()), Position::none())
EvalAltResult::ErrorParsing(ParseErrorType::BadInput(
LexError::ImproperSymbol(err.to_string()),
NO_POS,
))
.into()
}
}

View File

@ -2,7 +2,7 @@
use crate::dynamic::Dynamic;
use crate::result::EvalAltResult;
use crate::token::Position;
use crate::token::NO_POS;
#[cfg(not(feature = "no_index"))]
use crate::engine::Array;
@ -99,7 +99,7 @@ pub fn to_dynamic<T: Serialize>(value: T) -> Result<Dynamic, Box<EvalAltResult>>
impl Error for Box<EvalAltResult> {
fn custom<T: fmt::Display>(err: T) -> Self {
EvalAltResult::ErrorRuntime(err.to_string().into(), Position::none()).into()
EvalAltResult::ErrorRuntime(err.to_string().into(), NO_POS).into()
}
}
@ -295,11 +295,7 @@ impl Serializer for &mut DynamicSerializer {
make_variant(_variant, content)
}
#[cfg(feature = "no_object")]
return EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
"map".into(),
Position::none(),
)
return EvalAltResult::ErrorMismatchOutputType("Dynamic".into(), "map".into(), NO_POS)
.into();
}
@ -307,11 +303,7 @@ impl Serializer for &mut DynamicSerializer {
#[cfg(not(feature = "no_index"))]
return Ok(DynamicSerializer::new(Array::new().into()));
#[cfg(feature = "no_index")]
return EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
"array".into(),
Position::none(),
)
return EvalAltResult::ErrorMismatchOutputType("Dynamic".into(), "array".into(), NO_POS)
.into();
}
@ -345,12 +337,7 @@ impl Serializer for &mut DynamicSerializer {
let err_type = "map";
#[cfg(not(feature = "no_object"))]
let err_type = "array";
EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
err_type.into(),
Position::none(),
)
.into()
EvalAltResult::ErrorMismatchOutputType("Dynamic".into(), err_type.into(), NO_POS).into()
}
}
@ -358,11 +345,7 @@ impl Serializer for &mut DynamicSerializer {
#[cfg(not(feature = "no_object"))]
return Ok(DynamicSerializer::new(Map::new().into()));
#[cfg(feature = "no_object")]
return EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
"map".into(),
Position::none(),
)
return EvalAltResult::ErrorMismatchOutputType("Dynamic".into(), "map".into(), NO_POS)
.into();
}
@ -387,11 +370,7 @@ impl Serializer for &mut DynamicSerializer {
map: Map::with_capacity(_len),
});
#[cfg(feature = "no_object")]
return EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
"map".into(),
Position::none(),
)
return EvalAltResult::ErrorMismatchOutputType("Dynamic".into(), "map".into(), NO_POS)
.into();
}
}
@ -501,11 +480,7 @@ impl SerializeMap for DynamicSerializer {
let key = mem::take(&mut self._key)
.take_immutable_string()
.map_err(|typ| {
EvalAltResult::ErrorMismatchOutputType(
"string".into(),
typ.into(),
Position::none(),
)
EvalAltResult::ErrorMismatchOutputType("string".into(), typ.into(), NO_POS)
})?;
let _value = _value.serialize(&mut *self)?;
let map = self._value.downcast_mut::<Map>().unwrap();
@ -525,11 +500,7 @@ impl SerializeMap for DynamicSerializer {
{
let _key: Dynamic = _key.serialize(&mut *self)?;
let _key = _key.take_immutable_string().map_err(|typ| {
EvalAltResult::ErrorMismatchOutputType(
"string".into(),
typ.into(),
Position::none(),
)
EvalAltResult::ErrorMismatchOutputType("string".into(), typ.into(), NO_POS)
})?;
let _value = _value.serialize(&mut *self)?;
let map = self._value.downcast_mut::<Map>().unwrap();

View File

@ -1,7 +1,7 @@
//! Implement deserialization support of `ImmutableString` for [`serde`](https://crates.io/crates/serde).
use crate::result::EvalAltResult;
use crate::token::Position;
use crate::token::NO_POS;
use crate::utils::ImmutableString;
use serde::de::{Deserializer, Visitor};
@ -20,11 +20,7 @@ impl<'a> ImmutableStringDeserializer<'a> {
}
/// Shortcut for a type conversion error.
fn type_error<T>(&self) -> Result<T, Box<EvalAltResult>> {
EvalAltResult::ErrorMismatchOutputType(
type_name::<T>().into(),
"string".into(),
Position::none(),
)
EvalAltResult::ErrorMismatchOutputType(type_name::<T>().into(), "string".into(), NO_POS)
.into()
}
}

View File

@ -6,7 +6,7 @@ use crate::engine::{Engine, EvalContext, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT
use crate::fn_native::{SendSync, Shared};
use crate::parse_error::{LexError, ParseError};
use crate::result::EvalAltResult;
use crate::token::{is_valid_identifier, Position, Token};
use crate::token::{is_valid_identifier, Position, Token, NO_POS};
use crate::utils::ImmutableString;
use crate::StaticVec;
@ -139,7 +139,7 @@ impl Engine {
segments.len() + 1,
s
))
.into_err(Position::none())
.into_err(NO_POS)
.into());
}
// Identifier in first position
@ -156,7 +156,7 @@ impl Engine {
segments.len() + 1,
s
))
.into_err(Position::none())
.into_err(NO_POS)
.into());
}
};

View File

@ -44,6 +44,9 @@ pub struct Position {
pos: u16,
}
/// No `Position`.
pub const NO_POS: Position = Position { line: 0, pos: 0 };
impl Position {
/// Create a new `Position`.
///
@ -121,7 +124,7 @@ impl Position {
/// Create a `Position` representing no position.
#[inline(always)]
pub fn none() -> Self {
Self { line: 0, pos: 0 }
NO_POS
}
/// Is there no `Position`?

View File

@ -38,7 +38,7 @@ fn test_max_string_size() -> Result<(), Box<EvalAltResult>> {
"#
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 13, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
#[cfg(not(feature = "no_object"))]
@ -52,7 +52,7 @@ fn test_max_string_size() -> Result<(), Box<EvalAltResult>> {
"#
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 100, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
engine.set_max_string_size(0);
@ -98,7 +98,7 @@ fn test_max_array_size() -> Result<(), Box<EvalAltResult>> {
"
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 12, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
#[cfg(not(feature = "no_object"))]
@ -112,7 +112,7 @@ fn test_max_array_size() -> Result<(), Box<EvalAltResult>> {
"
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 100, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
assert!(matches!(
@ -124,7 +124,7 @@ fn test_max_array_size() -> Result<(), Box<EvalAltResult>> {
"
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 12, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
#[cfg(not(feature = "no_object"))]
@ -137,7 +137,7 @@ fn test_max_array_size() -> Result<(), Box<EvalAltResult>> {
"
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 12, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
assert!(matches!(
@ -151,7 +151,7 @@ fn test_max_array_size() -> Result<(), Box<EvalAltResult>> {
"
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 12, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
engine.set_max_array_size(0);
@ -216,7 +216,7 @@ fn test_max_map_size() -> Result<(), Box<EvalAltResult>> {
"
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 12, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
assert!(matches!(
@ -228,7 +228,7 @@ fn test_max_map_size() -> Result<(), Box<EvalAltResult>> {
"
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 12, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
#[cfg(not(feature = "no_index"))]
@ -241,7 +241,7 @@ fn test_max_map_size() -> Result<(), Box<EvalAltResult>> {
"
)
.expect_err("should error"),
EvalAltResult::ErrorDataTooLarge(_, 10, 12, _)
EvalAltResult::ErrorDataTooLarge(_, _)
));
engine.set_max_map_size(0);

View File

@ -1,5 +1,5 @@
#![cfg(not(feature = "unchecked"))]
use rhai::{Engine, EvalAltResult};
use rhai::{Engine, EvalAltResult, INT};
#[test]
fn test_max_operations() -> Result<(), Box<EvalAltResult>> {
@ -10,7 +10,7 @@ fn test_max_operations() -> Result<(), Box<EvalAltResult>> {
if count % 100 == 0 {
println!("{}", count);
}
true
None
});
engine.eval::<()>("let x = 0; while x < 20 { x += 1; }")?;
@ -38,7 +38,7 @@ fn test_max_operations_functions() -> Result<(), Box<EvalAltResult>> {
if count % 100 == 0 {
println!("{}", count);
}
true
None
});
engine.eval::<()>(
@ -94,7 +94,7 @@ fn test_max_operations_eval() -> Result<(), Box<EvalAltResult>> {
if count % 100 == 0 {
println!("{}", count);
}
true
None
});
assert!(matches!(
@ -117,13 +117,19 @@ fn test_max_operations_progress() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
engine.set_max_operations(500);
engine.on_progress(|&count| count < 100);
engine.on_progress(|&count| {
if count < 100 {
None
} else {
Some((42 as INT).into())
}
});
assert!(matches!(
*engine
.eval::<()>("for x in range(0, 500) {}")
.expect_err("should error"),
EvalAltResult::ErrorTerminated(_)
EvalAltResult::ErrorTerminated(x, _) if x.as_int()? == 42
));
Ok(())

View File

@ -1,4 +1,4 @@
use rhai::{Engine, EvalAltResult, ParseError, ParseErrorType, Position, INT};
use rhai::{Engine, EvalAltResult, LexError, ParseError, ParseErrorType, INT, NO_POS};
#[test]
fn test_custom_syntax() -> Result<(), Box<EvalAltResult>> {
@ -68,9 +68,9 @@ fn test_custom_syntax() -> Result<(), Box<EvalAltResult>> {
.register_custom_syntax(&["!"], 0, |_, _| Ok(().into()))
.expect_err("should error")
.0,
ParseErrorType::BadInput(
ParseErrorType::BadInput(LexError::ImproperSymbol(
"Improper symbol for custom syntax at position #1: '!'".to_string()
)
))
);
Ok(())
@ -88,8 +88,10 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
2 => match stream[1].as_str() {
"world" | "kitty" => Ok(None),
s => Err(ParseError(
Box::new(ParseErrorType::BadInput(s.to_string())),
Position::none(),
Box::new(ParseErrorType::BadInput(LexError::ImproperSymbol(
s.to_string(),
))),
NO_POS,
)),
},
_ => unreachable!(),
@ -109,7 +111,7 @@ fn test_custom_syntax_raw() -> Result<(), Box<EvalAltResult>> {
assert_eq!(engine.eval::<INT>("hello kitty")?, 42);
assert_eq!(
*engine.compile("hello hey").expect_err("should error").0,
ParseErrorType::BadInput("hey".to_string())
ParseErrorType::BadInput(LexError::ImproperSymbol("hey".to_string()))
);
Ok(())

View File

@ -1,4 +1,4 @@
use rhai::{Engine, EvalAltResult, ParseErrorType, RegisterFn, INT};
use rhai::{Engine, EvalAltResult, LexError, ParseErrorType, RegisterFn, INT};
#[test]
fn test_tokens_disabled() {
@ -16,10 +16,13 @@ fn test_tokens_disabled() {
engine.disable_symbol("+="); // disable the '+=' operator
assert!(matches!(
*engine.compile("let x = 40 + 2; x += 1;").expect_err("should error").0,
ParseErrorType::BadInput(ref s) if s == "Unexpected '+='"
));
assert_eq!(
*engine
.compile("let x = 40 + 2; x += 1;")
.expect_err("should error")
.0,
ParseErrorType::BadInput(LexError::UnexpectedInput("+=".to_string()))
);
}
#[test]

View File

@ -1,4 +1,4 @@
use rhai::{Engine, EvalAltResult, Position, Scope, INT};
use rhai::{Engine, EvalAltResult, Scope, INT, NO_POS};
#[test]
fn test_var_scope() -> Result<(), Box<EvalAltResult>> {
@ -67,7 +67,7 @@ fn test_var_resolver() -> Result<(), Box<EvalAltResult>> {
"MYSTIC_NUMBER" => Ok(Some((42 as INT).into())),
// Override a variable - make it not found even if it exists!
"DO_NOT_USE" => {
Err(EvalAltResult::ErrorVariableNotFound(name.to_string(), Position::none()).into())
Err(EvalAltResult::ErrorVariableNotFound(name.to_string(), NO_POS).into())
}
// Silently maps 'chameleon' into 'innocent'.
"chameleon" => context
@ -75,7 +75,7 @@ fn test_var_resolver() -> Result<(), Box<EvalAltResult>> {
.get_value("innocent")
.map(Some)
.ok_or_else(|| {
EvalAltResult::ErrorVariableNotFound(name.to_string(), Position::none()).into()
EvalAltResult::ErrorVariableNotFound(name.to_string(), NO_POS).into()
}),
// Return Ok(None) to continue with the normal variable resolution process.
_ => Ok(None),