General cleanup.
This commit is contained in:
parent
708c285a0a
commit
880bce1114
@ -18,6 +18,7 @@ include = [
|
|||||||
num-traits = "*"
|
num-traits = "*"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
#default = ["no_index", "no_float", "only_i32", "no_stdlib", "unchecked"]
|
||||||
default = []
|
default = []
|
||||||
debug_msgs = []
|
debug_msgs = []
|
||||||
unchecked = []
|
unchecked = []
|
||||||
|
@ -2,45 +2,23 @@
|
|||||||
//! _standard library_ of utility functions.
|
//! _standard library_ of utility functions.
|
||||||
|
|
||||||
use crate::any::Any;
|
use crate::any::Any;
|
||||||
use crate::engine::Engine;
|
|
||||||
use crate::fn_register::RegisterFn;
|
|
||||||
use crate::parser::INT;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
use crate::{parser::Position, result::EvalAltResult, RegisterResultFn};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::engine::Array;
|
use crate::engine::Array;
|
||||||
|
use crate::engine::Engine;
|
||||||
#[cfg(not(feature = "no_float"))]
|
use crate::fn_register::{RegisterFn, RegisterResultFn};
|
||||||
|
use crate::parser::{Position, INT};
|
||||||
|
use crate::result::EvalAltResult;
|
||||||
use crate::FLOAT;
|
use crate::FLOAT;
|
||||||
|
|
||||||
|
use num_traits::{
|
||||||
|
identities::Zero, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl,
|
||||||
|
CheckedShr, CheckedSub,
|
||||||
|
};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
ops::{BitAnd, BitOr, BitXor, Range},
|
ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Range, Rem, Shl, Shr, Sub},
|
||||||
};
|
{i32, i64, u32},
|
||||||
|
|
||||||
#[cfg(feature = "unchecked")]
|
|
||||||
use std::ops::{Shl, Shr};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
|
||||||
use std::{i32, i64};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
use std::u32;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "unchecked", not(feature = "no_float")))]
|
|
||||||
use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
|
||||||
use {
|
|
||||||
num_traits::{
|
|
||||||
CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr,
|
|
||||||
CheckedSub,
|
|
||||||
},
|
|
||||||
std::convert::TryFrom,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! reg_op {
|
macro_rules! reg_op {
|
||||||
@ -162,12 +140,9 @@ impl Engine<'_> {
|
|||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
fn div<T>(x: T, y: T) -> Result<T, EvalAltResult>
|
fn div<T>(x: T, y: T) -> Result<T, EvalAltResult>
|
||||||
where
|
where
|
||||||
T: Display + CheckedDiv + PartialEq + TryFrom<i8>,
|
T: Display + CheckedDiv + PartialEq + Zero,
|
||||||
{
|
{
|
||||||
if y == <T as TryFrom<i8>>::try_from(0)
|
if y == T::zero() {
|
||||||
.map_err(|_| ())
|
|
||||||
.expect("zero should always succeed")
|
|
||||||
{
|
|
||||||
return Err(EvalAltResult::ErrorArithmetic(
|
return Err(EvalAltResult::ErrorArithmetic(
|
||||||
format!("Division by zero: {} / {}", x, y),
|
format!("Division by zero: {} / {}", x, y),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
@ -191,8 +166,10 @@ impl Engine<'_> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
fn abs<T: Display + CheckedNeg + PartialOrd + From<i8>>(x: T) -> Result<T, EvalAltResult> {
|
fn abs<T: Display + CheckedNeg + PartialOrd + Zero>(x: T) -> Result<T, EvalAltResult> {
|
||||||
if x >= 0.into() {
|
// FIX - We don't use Signed::abs() here because, contrary to documentation, it panics
|
||||||
|
// when the number is ::MIN instead of returning ::MIN itself.
|
||||||
|
if x >= <T as Zero>::zero() {
|
||||||
Ok(x)
|
Ok(x)
|
||||||
} else {
|
} else {
|
||||||
x.checked_neg().ok_or_else(|| {
|
x.checked_neg().ok_or_else(|| {
|
||||||
@ -224,14 +201,15 @@ impl Engine<'_> {
|
|||||||
-x
|
-x
|
||||||
}
|
}
|
||||||
#[cfg(any(feature = "unchecked", not(feature = "no_float")))]
|
#[cfg(any(feature = "unchecked", not(feature = "no_float")))]
|
||||||
fn abs_u<T: Neg + PartialOrd + From<i8>>(x: T) -> T
|
fn abs_u<T>(x: T) -> <T as Neg>::Output
|
||||||
where
|
where
|
||||||
<T as Neg>::Output: Into<T>,
|
T: Neg + PartialOrd + Default + Into<<T as Neg>::Output>,
|
||||||
{
|
{
|
||||||
if x < 0.into() {
|
// Numbers should default to zero
|
||||||
(-x).into()
|
if x < Default::default() {
|
||||||
|
-x
|
||||||
} else {
|
} else {
|
||||||
x
|
x.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn lt<T: PartialOrd>(x: T, y: T) -> bool {
|
fn lt<T: PartialOrd>(x: T, y: T) -> bool {
|
||||||
|
@ -4,8 +4,6 @@ use crate::any::{Any, AnyExt, Dynamic, Variant};
|
|||||||
use crate::parser::{Expr, FnDef, Position, Stmt};
|
use crate::parser::{Expr, FnDef, Position, Stmt};
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
use crate::INT;
|
use crate::INT;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
@ -788,6 +786,9 @@ impl Engine<'_> {
|
|||||||
.eval_index_expr(scope, lhs, idx_expr, *idx_pos)
|
.eval_index_expr(scope, lhs, idx_expr, *idx_pos)
|
||||||
.map(|(_, _, _, x)| x),
|
.map(|(_, _, _, x)| x),
|
||||||
|
|
||||||
|
#[cfg(feature = "no_index")]
|
||||||
|
Expr::Index(_, _, _) => panic!("encountered an index expression during no_index!"),
|
||||||
|
|
||||||
// Statement block
|
// Statement block
|
||||||
Expr::Stmt(stmt, _) => self.eval_stmt(scope, stmt),
|
Expr::Stmt(stmt, _) => self.eval_stmt(scope, stmt),
|
||||||
|
|
||||||
@ -855,6 +856,8 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
Ok(Box::new(arr))
|
Ok(Box::new(arr))
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "no_index")]
|
||||||
|
Expr::Array(_, _) => panic!("encountered an array during no_index!"),
|
||||||
|
|
||||||
Expr::FunctionCall(fn_name, args, def_val, pos) => {
|
Expr::FunctionCall(fn_name, args, def_val, pos) => {
|
||||||
let mut args = args
|
let mut args = args
|
||||||
|
@ -120,20 +120,20 @@ macro_rules! def_register {
|
|||||||
const NUM_ARGS: usize = count_args!($($par)*);
|
const NUM_ARGS: usize = count_args!($($par)*);
|
||||||
|
|
||||||
if args.len() != NUM_ARGS {
|
if args.len() != NUM_ARGS {
|
||||||
Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos))
|
return Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos));
|
||||||
} else {
|
|
||||||
#[allow(unused_variables, unused_mut)]
|
|
||||||
let mut drain = args.drain(..);
|
|
||||||
$(
|
|
||||||
// Downcast every element, return in case of a type mismatch
|
|
||||||
let $par = drain.next().unwrap().downcast_mut::<$par>().unwrap();
|
|
||||||
)*
|
|
||||||
|
|
||||||
// Call the user-supplied function using ($clone) to
|
|
||||||
// potentially clone the value, otherwise pass the reference.
|
|
||||||
let r = f($(($clone)($par)),*);
|
|
||||||
Ok(Box::new(r) as Dynamic)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut drain = args.drain(..);
|
||||||
|
$(
|
||||||
|
// Downcast every element, return in case of a type mismatch
|
||||||
|
let $par = drain.next().unwrap().downcast_mut::<$par>().unwrap();
|
||||||
|
)*
|
||||||
|
|
||||||
|
// Call the user-supplied function using ($clone) to
|
||||||
|
// potentially clone the value, otherwise pass the reference.
|
||||||
|
let r = f($(($clone)($par)),*);
|
||||||
|
Ok(Box::new(r) as Dynamic)
|
||||||
};
|
};
|
||||||
self.register_fn_raw(name, Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
self.register_fn_raw(name, Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
||||||
}
|
}
|
||||||
@ -152,19 +152,19 @@ macro_rules! def_register {
|
|||||||
const NUM_ARGS: usize = count_args!($($par)*);
|
const NUM_ARGS: usize = count_args!($($par)*);
|
||||||
|
|
||||||
if args.len() != NUM_ARGS {
|
if args.len() != NUM_ARGS {
|
||||||
Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos))
|
return Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos));
|
||||||
} else {
|
|
||||||
#[allow(unused_variables, unused_mut)]
|
|
||||||
let mut drain = args.drain(..);
|
|
||||||
$(
|
|
||||||
// Downcast every element, return in case of a type mismatch
|
|
||||||
let $par = drain.next().unwrap().downcast_mut::<$par>().unwrap();
|
|
||||||
)*
|
|
||||||
|
|
||||||
// Call the user-supplied function using ($clone) to
|
|
||||||
// potentially clone the value, otherwise pass the reference.
|
|
||||||
Ok(f($(($clone)($par)),*))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut drain = args.drain(..);
|
||||||
|
$(
|
||||||
|
// Downcast every element, return in case of a type mismatch
|
||||||
|
let $par = drain.next().unwrap().downcast_mut::<$par>().unwrap();
|
||||||
|
)*
|
||||||
|
|
||||||
|
// Call the user-supplied function using ($clone) to
|
||||||
|
// potentially clone the value, otherwise pass the reference.
|
||||||
|
Ok(f($(($clone)($par)),*))
|
||||||
};
|
};
|
||||||
self.register_fn_raw(name, Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
self.register_fn_raw(name, Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
||||||
}
|
}
|
||||||
@ -184,23 +184,23 @@ macro_rules! def_register {
|
|||||||
const NUM_ARGS: usize = count_args!($($par)*);
|
const NUM_ARGS: usize = count_args!($($par)*);
|
||||||
|
|
||||||
if args.len() != NUM_ARGS {
|
if args.len() != NUM_ARGS {
|
||||||
Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos))
|
return Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos));
|
||||||
} else {
|
}
|
||||||
#[allow(unused_variables, unused_mut)]
|
|
||||||
let mut drain = args.drain(..);
|
|
||||||
$(
|
|
||||||
// Downcast every element, return in case of a type mismatch
|
|
||||||
let $par = drain.next().unwrap().downcast_mut::<$par>().unwrap();
|
|
||||||
)*
|
|
||||||
|
|
||||||
// Call the user-supplied function using ($clone) to
|
#[allow(unused_variables, unused_mut)]
|
||||||
// potentially clone the value, otherwise pass the reference.
|
let mut drain = args.drain(..);
|
||||||
match f($(($clone)($par)),*) {
|
$(
|
||||||
Ok(r) => Ok(Box::new(r) as Dynamic),
|
// Downcast every element, return in case of a type mismatch
|
||||||
Err(mut err) => {
|
let $par = drain.next().unwrap().downcast_mut::<$par>().unwrap();
|
||||||
err.set_position(pos);
|
)*
|
||||||
Err(err)
|
|
||||||
}
|
// Call the user-supplied function using ($clone) to
|
||||||
|
// potentially clone the value, otherwise pass the reference.
|
||||||
|
match f($(($clone)($par)),*) {
|
||||||
|
Ok(r) => Ok(Box::new(r) as Dynamic),
|
||||||
|
Err(mut err) => {
|
||||||
|
err.set_position(pos);
|
||||||
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -141,6 +141,7 @@ fn optimize_expr(expr: Expr, changed: &mut bool) -> Expr {
|
|||||||
Box::new(optimize_expr(*rhs, changed)),
|
Box::new(optimize_expr(*rhs, changed)),
|
||||||
pos,
|
pos,
|
||||||
),
|
),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Index(lhs, rhs, pos) => match (*lhs, *rhs) {
|
Expr::Index(lhs, rhs, pos) => match (*lhs, *rhs) {
|
||||||
(Expr::Array(mut items, _), Expr::IntegerConstant(i, _))
|
(Expr::Array(mut items, _), Expr::IntegerConstant(i, _))
|
||||||
@ -158,6 +159,9 @@ fn optimize_expr(expr: Expr, changed: &mut bool) -> Expr {
|
|||||||
pos,
|
pos,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
#[cfg(feature = "no_index")]
|
||||||
|
Expr::Index(_, _, _) => panic!("encountered an index expression during no_index!"),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Array(items, pos) => {
|
Expr::Array(items, pos) => {
|
||||||
let original_len = items.len();
|
let original_len = items.len();
|
||||||
@ -172,6 +176,9 @@ fn optimize_expr(expr: Expr, changed: &mut bool) -> Expr {
|
|||||||
Expr::Array(items, pos)
|
Expr::Array(items, pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "no_index")]
|
||||||
|
Expr::Array(_, _) => panic!("encountered an array during no_index!"),
|
||||||
|
|
||||||
Expr::And(lhs, rhs) => match (*lhs, *rhs) {
|
Expr::And(lhs, rhs) => match (*lhs, *rhs) {
|
||||||
(Expr::True(_), rhs) => {
|
(Expr::True(_), rhs) => {
|
||||||
*changed = true;
|
*changed = true;
|
||||||
@ -208,7 +215,6 @@ fn optimize_expr(expr: Expr, changed: &mut bool) -> Expr {
|
|||||||
Box::new(optimize_expr(rhs, changed)),
|
Box::new(optimize_expr(rhs, changed)),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
Expr::FunctionCall(id, args, def_value, pos) => {
|
Expr::FunctionCall(id, args, def_value, pos) => {
|
||||||
let original_len = args.len();
|
let original_len = args.len();
|
||||||
|
|
||||||
|
@ -3,13 +3,18 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::error::{LexError, ParseError, ParseErrorType};
|
use crate::error::{LexError, ParseError, ParseErrorType};
|
||||||
use crate::optimize::optimize;
|
use crate::optimize::optimize;
|
||||||
|
|
||||||
use std::{borrow::Cow, char, fmt, iter::Peekable, str::Chars, str::FromStr, usize};
|
use std::{borrow::Cow, char, fmt, iter::Peekable, str::Chars, str::FromStr, usize};
|
||||||
|
|
||||||
/// The system integer type
|
/// The system integer type.
|
||||||
|
///
|
||||||
|
/// If the `only_i32` feature is enabled, this will be `i32` instead.
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
pub type INT = i64;
|
pub type INT = i64;
|
||||||
|
|
||||||
/// The system integer type
|
/// The system integer type
|
||||||
|
///
|
||||||
|
/// If the `only_i32` feature is not enabled, this will be `i64` instead.
|
||||||
#[cfg(feature = "only_i32")]
|
#[cfg(feature = "only_i32")]
|
||||||
pub type INT = i32;
|
pub type INT = i32;
|
||||||
|
|
||||||
@ -179,9 +184,7 @@ pub enum Expr {
|
|||||||
FunctionCall(String, Vec<Expr>, Option<Dynamic>, Position),
|
FunctionCall(String, Vec<Expr>, Option<Dynamic>, Position),
|
||||||
Assignment(Box<Expr>, Box<Expr>, Position),
|
Assignment(Box<Expr>, Box<Expr>, Position),
|
||||||
Dot(Box<Expr>, Box<Expr>, Position),
|
Dot(Box<Expr>, Box<Expr>, Position),
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Index(Box<Expr>, Box<Expr>, Position),
|
Index(Box<Expr>, Box<Expr>, Position),
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Array(Vec<Expr>, Position),
|
Array(Vec<Expr>, Position),
|
||||||
And(Box<Expr>, Box<Expr>),
|
And(Box<Expr>, Box<Expr>),
|
||||||
Or(Box<Expr>, Box<Expr>),
|
Or(Box<Expr>, Box<Expr>),
|
||||||
@ -197,24 +200,21 @@ impl Expr {
|
|||||||
| Expr::Identifier(_, pos)
|
| Expr::Identifier(_, pos)
|
||||||
| Expr::CharConstant(_, pos)
|
| Expr::CharConstant(_, pos)
|
||||||
| Expr::StringConstant(_, pos)
|
| Expr::StringConstant(_, pos)
|
||||||
| Expr::FunctionCall(_, _, _, pos)
|
|
||||||
| Expr::Stmt(_, pos)
|
| Expr::Stmt(_, pos)
|
||||||
|
| Expr::FunctionCall(_, _, _, pos)
|
||||||
|
| Expr::Array(_, pos)
|
||||||
| Expr::True(pos)
|
| Expr::True(pos)
|
||||||
| Expr::False(pos)
|
| Expr::False(pos)
|
||||||
| Expr::Unit(pos) => *pos,
|
| Expr::Unit(pos) => *pos,
|
||||||
|
|
||||||
Expr::Assignment(e, _, _) | Expr::Dot(e, _, _) | Expr::And(e, _) | Expr::Or(e, _) => {
|
Expr::Assignment(e, _, _)
|
||||||
e.position()
|
| Expr::Dot(e, _, _)
|
||||||
}
|
| Expr::Index(e, _, _)
|
||||||
|
| Expr::And(e, _)
|
||||||
|
| Expr::Or(e, _) => e.position(),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Expr::FloatConstant(_, pos) => *pos,
|
Expr::FloatConstant(_, pos) => *pos,
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Expr::Index(e, _, _) => e.position(),
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
|
||||||
Expr::Array(_, pos) => *pos,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
use crate::parser::{Position, INT};
|
use crate::parser::{Position, INT};
|
||||||
|
|
||||||
use std::{error::Error, fmt};
|
use std::{error::Error, fmt};
|
||||||
|
|
||||||
/// Evaluation result.
|
/// Evaluation result.
|
||||||
@ -75,12 +76,12 @@ impl Error for EvalAltResult {
|
|||||||
Self::ErrorArrayBounds(_, index, _) if *index < 0 => {
|
Self::ErrorArrayBounds(_, index, _) if *index < 0 => {
|
||||||
"Array access expects non-negative index"
|
"Array access expects non-negative index"
|
||||||
}
|
}
|
||||||
Self::ErrorArrayBounds(max, _, _) if *max == 0 => "Access of empty array",
|
Self::ErrorArrayBounds(0, _, _) => "Access of empty array",
|
||||||
Self::ErrorArrayBounds(_, _, _) => "Array index out of bounds",
|
Self::ErrorArrayBounds(_, _, _) => "Array index out of bounds",
|
||||||
Self::ErrorStringBounds(_, index, _) if *index < 0 => {
|
Self::ErrorStringBounds(_, index, _) if *index < 0 => {
|
||||||
"Indexing a string expects a non-negative index"
|
"Indexing a string expects a non-negative index"
|
||||||
}
|
}
|
||||||
Self::ErrorStringBounds(max, _, _) if *max == 0 => "Indexing of empty string",
|
Self::ErrorStringBounds(0, _, _) => "Indexing of empty string",
|
||||||
Self::ErrorStringBounds(_, _, _) => "String index out of bounds",
|
Self::ErrorStringBounds(_, _, _) => "String index out of bounds",
|
||||||
Self::ErrorIfGuard(_) => "If guard expects boolean expression",
|
Self::ErrorIfGuard(_) => "If guard expects boolean expression",
|
||||||
Self::ErrorFor(_) => "For loop expects array or range",
|
Self::ErrorFor(_) => "For loop expects array or range",
|
||||||
@ -128,6 +129,16 @@ impl fmt::Display for EvalAltResult {
|
|||||||
write!(f, "{} '{}': {}", desc, filename, err)
|
write!(f, "{} '{}': {}", desc, filename, err)
|
||||||
}
|
}
|
||||||
Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p),
|
Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p),
|
||||||
|
Self::ErrorFunctionArgsMismatch(fun, 0, n, pos) => write!(
|
||||||
|
f,
|
||||||
|
"Function '{}' expects no argument but {} found ({})",
|
||||||
|
fun, n, pos
|
||||||
|
),
|
||||||
|
Self::ErrorFunctionArgsMismatch(fun, 1, n, pos) => write!(
|
||||||
|
f,
|
||||||
|
"Function '{}' expects one argument but {} found ({})",
|
||||||
|
fun, n, pos
|
||||||
|
),
|
||||||
Self::ErrorFunctionArgsMismatch(fun, need, n, pos) => write!(
|
Self::ErrorFunctionArgsMismatch(fun, need, n, pos) => write!(
|
||||||
f,
|
f,
|
||||||
"Function '{}' expects {} argument(s) but {} found ({})",
|
"Function '{}' expects {} argument(s) but {} found ({})",
|
||||||
@ -142,26 +153,30 @@ impl fmt::Display for EvalAltResult {
|
|||||||
Self::ErrorArrayBounds(_, index, pos) if *index < 0 => {
|
Self::ErrorArrayBounds(_, index, pos) if *index < 0 => {
|
||||||
write!(f, "{}: {} < 0 ({})", desc, index, pos)
|
write!(f, "{}: {} < 0 ({})", desc, index, pos)
|
||||||
}
|
}
|
||||||
Self::ErrorArrayBounds(max, _, pos) if *max == 0 => write!(f, "{} ({})", desc, pos),
|
Self::ErrorArrayBounds(0, _, pos) => write!(f, "{} ({})", desc, pos),
|
||||||
|
Self::ErrorArrayBounds(1, index, pos) => write!(
|
||||||
|
f,
|
||||||
|
"Array index {} is out of bounds: only one element in the array ({})",
|
||||||
|
index, pos
|
||||||
|
),
|
||||||
Self::ErrorArrayBounds(max, index, pos) => write!(
|
Self::ErrorArrayBounds(max, index, pos) => write!(
|
||||||
f,
|
f,
|
||||||
"Array index {} is out of bounds: only {} element{} in the array ({})",
|
"Array index {} is out of bounds: only {} elements in the array ({})",
|
||||||
index,
|
index, max, pos
|
||||||
max,
|
|
||||||
if *max > 1 { "s" } else { "" },
|
|
||||||
pos
|
|
||||||
),
|
),
|
||||||
Self::ErrorStringBounds(_, index, pos) if *index < 0 => {
|
Self::ErrorStringBounds(_, index, pos) if *index < 0 => {
|
||||||
write!(f, "{}: {} < 0 ({})", desc, index, pos)
|
write!(f, "{}: {} < 0 ({})", desc, index, pos)
|
||||||
}
|
}
|
||||||
Self::ErrorStringBounds(max, _, pos) if *max == 0 => write!(f, "{} ({})", desc, pos),
|
Self::ErrorStringBounds(0, _, pos) => write!(f, "{} ({})", desc, pos),
|
||||||
|
Self::ErrorStringBounds(1, index, pos) => write!(
|
||||||
|
f,
|
||||||
|
"String index {} is out of bounds: only one character in the string ({})",
|
||||||
|
index, pos
|
||||||
|
),
|
||||||
Self::ErrorStringBounds(max, index, pos) => write!(
|
Self::ErrorStringBounds(max, index, pos) => write!(
|
||||||
f,
|
f,
|
||||||
"String index {} is out of bounds: only {} character{} in the string ({})",
|
"String index {} is out of bounds: only {} characters in the string ({})",
|
||||||
index,
|
index, max, pos
|
||||||
max,
|
|
||||||
if *max > 1 { "s" } else { "" },
|
|
||||||
pos
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Module that defines the `Scope` type representing a function call-stack scope.
|
//! Module that defines the `Scope` type representing a function call-stack scope.
|
||||||
|
|
||||||
use crate::any::{Any, Dynamic};
|
use crate::any::{Any, Dynamic};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
/// A type containing information about current scope.
|
/// A type containing information about current scope.
|
||||||
|
@ -24,6 +24,10 @@ fn test_math() -> Result<(), EvalAltResult> {
|
|||||||
{
|
{
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
{
|
{
|
||||||
|
match engine.eval::<INT>("(-9223372036854775808).abs()") {
|
||||||
|
Err(EvalAltResult::ErrorArithmetic(_, _)) => (),
|
||||||
|
r => panic!("should return overflow error: {:?}", r),
|
||||||
|
}
|
||||||
match engine.eval::<INT>("9223372036854775807 + 1") {
|
match engine.eval::<INT>("9223372036854775807 + 1") {
|
||||||
Err(EvalAltResult::ErrorArithmetic(_, _)) => (),
|
Err(EvalAltResult::ErrorArithmetic(_, _)) => (),
|
||||||
r => panic!("should return overflow error: {:?}", r),
|
r => panic!("should return overflow error: {:?}", r),
|
||||||
|
Loading…
Reference in New Issue
Block a user