diff --git a/RELEASES.md b/RELEASES.md index 06d3f9f8..af4262ba 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -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` with the termination value passed on to `EvalAltResult::ErrorTerminated`. +* `ParseErrorType::BadInput` now wraps a `LexError` instead of a text string. New features ------------ diff --git a/doc/src/engine/custom-syntax.md b/doc/src/engine/custom-syntax.md index 61cfae84..ebac08f0 100644 --- a/doc/src/engine/custom-syntax.md +++ b/doc/src/engine/custom-syntax.md @@ -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!(), }, @@ -335,8 +335,8 @@ where: The return value is `Result, 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`].
Normally this is `ParseError(ParseErrorType::BadInput(message), Position::none())` to indicate that there is a syntax error, but it can be any `ParseError`. | +| 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`].
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`. | diff --git a/doc/src/engine/var.md b/doc/src/engine/var.md index dd661f8b..5af45a41 100644 --- a/doc/src/engine/var.md +++ b/doc/src/engine/var.md @@ -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) @@ -82,8 +82,8 @@ where: The return value is `Result, Box>` 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)` | error that is reflected back to the [`Engine`].
Normally this is `EvalAltResult::ErrorVariableNotFound(var_name, Position::none())` to indicate that the variable does not exist, but it can be any `EvalAltResult`. | +| 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)` | error that is reflected back to the [`Engine`].
Normally this is `EvalAltResult::ErrorVariableNotFound(var_name, NO_POS)` to indicate that the variable does not exist, but it can be any `EvalAltResult`. | diff --git a/doc/src/plugins/function.md b/doc/src/plugins/function.md index bd31de0c..e63448d4 100644 --- a/doc/src/plugins/function.md +++ b/doc/src/plugins/function.md @@ -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(); } diff --git a/doc/src/plugins/module.md b/doc/src/plugins/module.md index 6d07abdc..a60d6fed 100644 --- a/doc/src/plugins/module.md +++ b/doc/src/plugins/module.md @@ -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(); } diff --git a/src/engine.rs b/src/engine.rs index 494d2e3a..a9a2a636 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -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,26 +2294,18 @@ 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(), - ) - .into(); + return EvalAltResult::ErrorDataTooLarge("Size of object map".to_string(), NO_POS) + .into(); } result @@ -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(); } } diff --git a/src/engine_api.rs b/src/engine_api.rs index 26fd57ee..619e5f54 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -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::()).into(), typ.into(), - Position::none(), + NO_POS, ) .into() }); @@ -1527,7 +1527,7 @@ impl Engine { EvalAltResult::ErrorMismatchOutputType( self.map_type_name(type_name::()).into(), typ.into(), - Position::none(), + NO_POS, ) .into() }); @@ -1617,7 +1617,7 @@ impl Engine { ) -> Result> { 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(); diff --git a/src/fn_call.rs b/src/fn_call.rs index f5b0a190..313b4b15 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -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::()).into(), typ.into(), - Position::none(), + NO_POS, ) })?) .into(), @@ -234,7 +234,7 @@ impl Engine { EvalAltResult::ErrorMismatchOutputType( self.map_type_name(type_name::()).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::>() .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,29 +394,25 @@ 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) - .or_else(|err| match *err { - // Convert return statement to return value - EvalAltResult::Return(x, _) => Ok(x), - EvalAltResult::ErrorInFunctionCall(name, err, _) => { - EvalAltResult::ErrorInFunctionCall( - format!("{} > {}", fn_def.name, name), - err, - Position::none(), - ) - .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(), - ) - .into(), - }); + 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), + EvalAltResult::ErrorInFunctionCall(name, err, _) => { + EvalAltResult::ErrorInFunctionCall( + format!("{} > {}", fn_def.name, name), + err, + 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, NO_POS) + .into(), + }); // Remove all local variables scope.rewind(prev_scope_len); @@ -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::>() .join(", ") ), - Position::none(), + NO_POS, ) .into(), } diff --git a/src/fn_native.rs b/src/fn_native.rs index 312af42b..f41490d0 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -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 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() } } } diff --git a/src/lib.rs b/src/lib.rs index 621aea86..71fbf3cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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")] diff --git a/src/module/mod.rs b/src/module/mod.rs index a8714a4d..8c9a17a3 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -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> { 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()) } } diff --git a/src/optimize.rs b/src/optimize.rs index def61077..1ef43a5a 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -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); } }); diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index d061ceeb..c8398cea 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -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) -> Box { - EvalAltResult::ErrorArithmetic(msg.into(), Position::none()).into() + EvalAltResult::ErrorArithmetic(msg.into(), NO_POS).into() } macro_rules! gen_arithmetic_functions { diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index fa831e6f..89609714 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -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() diff --git a/src/packages/math_basic.rs b/src/packages/math_basic.rs index ef55765f..1dd00419 100644 --- a/src/packages/math_basic.rs +++ b/src/packages/math_basic.rs @@ -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,11 +85,8 @@ mod int_functions { #[rhai_fn(name = "parse_int", return_raw)] pub fn parse_int_radix(s: &str, radix: INT) -> Result> { if radix < 2 || radix > 36 { - return EvalAltResult::ErrorArithmetic( - format!("Invalid radix: '{}'", radix), - Position::none(), - ) - .into(); + return EvalAltResult::ErrorArithmetic(format!("Invalid radix: '{}'", radix), NO_POS) + .into(); } INT::from_str_radix(s.trim(), radix as u32) @@ -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,11 +203,8 @@ mod float_functions { #[rhai_fn(name = "to_int", return_raw)] pub fn f32_to_int(x: f32) -> Result> { if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f32) { - EvalAltResult::ErrorArithmetic( - format!("Integer overflow: to_int({})", x), - Position::none(), - ) - .into() + EvalAltResult::ErrorArithmetic(format!("Integer overflow: to_int({})", x), NO_POS) + .into() } else { Ok((x.trunc() as INT).into()) } @@ -218,11 +212,8 @@ mod float_functions { #[rhai_fn(name = "to_int", return_raw)] pub fn f64_to_int(x: f64) -> Result> { if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f64) { - EvalAltResult::ErrorArithmetic( - format!("Integer overflow: to_int({})", x), - Position::none(), - ) - .into() + 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() }) diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index 7ce4fb06..6025ad3f 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -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(); } diff --git a/src/parse_error.rs b/src/parse_error.rs index ca0f9d71..23613a24 100644 --- a/src/parse_error.rs +++ b/src/parse_error.rs @@ -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 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 for Box { #[inline(always)] fn from(err: ParseErrorType) -> Self { - Box::new(EvalAltResult::ErrorParsing(err, Position::none())) + Box::new(EvalAltResult::ErrorParsing(err, NO_POS)) } } diff --git a/src/parser.rs b/src/parser.rs index 7acef0d1..61fc858b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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,8 +866,10 @@ 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()) - .into_err(token_pos) + PERR::BadInput(LexError::ImproperSymbol( + "'!' cannot be used to call module functions".to_string(), + )) + .into_err(token_pos) }); } // Function call with ! @@ -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 { - 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)? { diff --git a/src/result.rs b/src/result.rs index 5370850e..79fb519b 100644 --- a/src/result.rs +++ b/src/result.rs @@ -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> From 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> From for Box { 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) diff --git a/src/serde_impl/de.rs b/src/serde_impl/de.rs index 3d14f1ad..a607c589 100644 --- a/src/serde_impl/de.rs +++ b/src/serde_impl/de.rs @@ -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,12 +45,8 @@ impl<'de> DynamicDeserializer<'de> { } /// Shortcut for a type conversion error. fn type_error_str(&self, error: &str) -> Result> { - EvalAltResult::ErrorMismatchOutputType( - error.into(), - self.value.type_name().into(), - Position::none(), - ) - .into() + EvalAltResult::ErrorMismatchOutputType(error.into(), self.value.type_name().into(), NO_POS) + .into() } fn deserialize_int>( &mut self, @@ -127,8 +123,11 @@ pub fn from_dynamic<'de, T: Deserialize<'de>>( impl Error for Box { fn custom(err: T) -> Self { - EvalAltResult::ErrorParsing(ParseErrorType::BadInput(err.to_string()), Position::none()) - .into() + EvalAltResult::ErrorParsing(ParseErrorType::BadInput( + LexError::ImproperSymbol(err.to_string()), + NO_POS, + )) + .into() } } diff --git a/src/serde_impl/ser.rs b/src/serde_impl/ser.rs index c7a77251..4074577c 100644 --- a/src/serde_impl/ser.rs +++ b/src/serde_impl/ser.rs @@ -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(value: T) -> Result> impl Error for Box { fn custom(err: T) -> Self { - EvalAltResult::ErrorRuntime(err.to_string().into(), Position::none()).into() + EvalAltResult::ErrorRuntime(err.to_string().into(), NO_POS).into() } } @@ -295,24 +295,16 @@ impl Serializer for &mut DynamicSerializer { make_variant(_variant, content) } #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchOutputType( - "Dynamic".into(), - "map".into(), - Position::none(), - ) - .into(); + return EvalAltResult::ErrorMismatchOutputType("Dynamic".into(), "map".into(), NO_POS) + .into(); } fn serialize_seq(self, _len: Option) -> Result> { #[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(), - ) - .into(); + return EvalAltResult::ErrorMismatchOutputType("Dynamic".into(), "array".into(), NO_POS) + .into(); } fn serialize_tuple(self, len: usize) -> Result> { @@ -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,12 +345,8 @@ 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(), - ) - .into(); + return EvalAltResult::ErrorMismatchOutputType("Dynamic".into(), "map".into(), NO_POS) + .into(); } fn serialize_struct( @@ -387,12 +370,8 @@ impl Serializer for &mut DynamicSerializer { map: Map::with_capacity(_len), }); #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchOutputType( - "Dynamic".into(), - "map".into(), - Position::none(), - ) - .into(); + 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::().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::().unwrap(); diff --git a/src/serde_impl/str.rs b/src/serde_impl/str.rs index 8283cc79..c499ad49 100644 --- a/src/serde_impl/str.rs +++ b/src/serde_impl/str.rs @@ -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,12 +20,8 @@ impl<'a> ImmutableStringDeserializer<'a> { } /// Shortcut for a type conversion error. fn type_error(&self) -> Result> { - EvalAltResult::ErrorMismatchOutputType( - type_name::().into(), - "string".into(), - Position::none(), - ) - .into() + EvalAltResult::ErrorMismatchOutputType(type_name::().into(), "string".into(), NO_POS) + .into() } } diff --git a/src/syntax.rs b/src/syntax.rs index 4d0a6519..e03c6a21 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -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()); } }; diff --git a/src/token.rs b/src/token.rs index 3e4baba9..944b2f48 100644 --- a/src/token.rs +++ b/src/token.rs @@ -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`? diff --git a/tests/data_size.rs b/tests/data_size.rs index ca91fb5c..3c67b4bc 100644 --- a/tests/data_size.rs +++ b/tests/data_size.rs @@ -38,7 +38,7 @@ fn test_max_string_size() -> Result<(), Box> { "# ) .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> { "# ) .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> { " ) .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> { " ) .expect_err("should error"), - EvalAltResult::ErrorDataTooLarge(_, 10, 100, _) + EvalAltResult::ErrorDataTooLarge(_, _) )); assert!(matches!( @@ -124,7 +124,7 @@ fn test_max_array_size() -> Result<(), Box> { " ) .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> { " ) .expect_err("should error"), - EvalAltResult::ErrorDataTooLarge(_, 10, 12, _) + EvalAltResult::ErrorDataTooLarge(_, _) )); assert!(matches!( @@ -151,7 +151,7 @@ fn test_max_array_size() -> Result<(), Box> { " ) .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> { " ) .expect_err("should error"), - EvalAltResult::ErrorDataTooLarge(_, 10, 12, _) + EvalAltResult::ErrorDataTooLarge(_, _) )); assert!(matches!( @@ -228,7 +228,7 @@ fn test_max_map_size() -> Result<(), Box> { " ) .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> { " ) .expect_err("should error"), - EvalAltResult::ErrorDataTooLarge(_, 10, 12, _) + EvalAltResult::ErrorDataTooLarge(_, _) )); engine.set_max_map_size(0); diff --git a/tests/operations.rs b/tests/operations.rs index dae539f0..a0f52550 100644 --- a/tests/operations.rs +++ b/tests/operations.rs @@ -1,5 +1,5 @@ #![cfg(not(feature = "unchecked"))] -use rhai::{Engine, EvalAltResult}; +use rhai::{Engine, EvalAltResult, INT}; #[test] fn test_max_operations() -> Result<(), Box> { @@ -10,7 +10,7 @@ fn test_max_operations() -> Result<(), Box> { 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> { if count % 100 == 0 { println!("{}", count); } - true + None }); engine.eval::<()>( @@ -94,7 +94,7 @@ fn test_max_operations_eval() -> Result<(), Box> { if count % 100 == 0 { println!("{}", count); } - true + None }); assert!(matches!( @@ -117,13 +117,19 @@ fn test_max_operations_progress() -> Result<(), Box> { 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(()) diff --git a/tests/syntax.rs b/tests/syntax.rs index 9cda2bf6..d6a875cc 100644 --- a/tests/syntax.rs +++ b/tests/syntax.rs @@ -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> { @@ -68,9 +68,9 @@ fn test_custom_syntax() -> Result<(), Box> { .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> { 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> { assert_eq!(engine.eval::("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(()) diff --git a/tests/tokens.rs b/tests/tokens.rs index e393663d..0070c23d 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -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] diff --git a/tests/var_scope.rs b/tests/var_scope.rs index 4faf37b5..e6dc825a 100644 --- a/tests/var_scope.rs +++ b/tests/var_scope.rs @@ -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> { @@ -67,7 +67,7 @@ fn test_var_resolver() -> Result<(), Box> { "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> { .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),