1) Change namespaces to iter_namespaces

2) throw can throw any value
This commit is contained in:
Stephen Chung
2020-10-20 18:09:26 +08:00
parent 09f8b13f2d
commit 5ee9dfc5cd
15 changed files with 97 additions and 69 deletions

View File

@@ -442,13 +442,13 @@ pub struct Limits {
/// Context of a script evaluation process.
#[derive(Debug)]
pub struct EvalContext<'e, 'x, 'px: 'x, 'a, 's, 'm, 'pm: 'm, 't, 'pt: 't> {
engine: &'e Engine,
pub(crate) engine: &'e Engine,
pub scope: &'x mut Scope<'px>,
pub(crate) mods: &'a mut Imports,
pub(crate) state: &'s mut State,
lib: &'m [&'pm Module],
pub(crate) lib: &'m [&'pm Module],
pub(crate) this_ptr: &'t mut Option<&'pt mut Dynamic>,
level: usize,
pub(crate) level: usize,
}
impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> {
@@ -465,10 +465,10 @@ impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm,
pub fn imports(&self) -> &'a Imports {
self.mods
}
/// The chain of namespaces containing definition of all script-defined functions.
/// Get an iterator over the namespaces containing definition of all script-defined functions.
#[inline(always)]
pub fn namespaces(&self) -> &'m [&'pm Module] {
self.lib
pub fn iter_namespaces(&self) -> impl Iterator<Item = &'pm Module> + 'm {
self.lib.iter().cloned()
}
/// The current bound `this` pointer, if any.
#[inline(always)]
@@ -1951,16 +1951,12 @@ impl Engine {
Stmt::ReturnWithVal(x) if x.1.is_some() && (x.0).0 == ReturnType::Exception => {
let expr = x.1.as_ref().unwrap();
let val = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
EvalAltResult::ErrorRuntime(
val.take_string().unwrap_or_else(|_| "".into()),
(x.0).1,
)
.into()
EvalAltResult::ErrorRuntime(val, (x.0).1).into()
}
// Empty throw
Stmt::ReturnWithVal(x) if (x.0).0 == ReturnType::Exception => {
EvalAltResult::ErrorRuntime("".into(), (x.0).1).into()
EvalAltResult::ErrorRuntime(().into(), (x.0).1).into()
}
Stmt::ReturnWithVal(_) => unreachable!(),

View File

@@ -533,7 +533,8 @@ impl Engine {
format!(
"'{}' should not be called in method style. Try {}(...);",
fn_name, fn_name
),
)
.into(),
Position::none(),
)
.into()

View File

@@ -72,10 +72,10 @@ impl<'e, 'm, 'pm> NativeCallContext<'e, 'm, 'pm> {
pub fn engine(&self) -> &'e Engine {
self.engine
}
/// The chain of namespaces containing definition of all script-defined functions.
/// Get an iterator over the namespaces containing definition of all script-defined functions.
#[inline(always)]
pub fn namespaces(&self) -> &'m [&'pm Module] {
self.lib
pub fn iter_namespaces(&self) -> impl Iterator<Item = &'pm Module> + 'm {
self.lib.iter().cloned()
}
}
@@ -186,7 +186,7 @@ impl FnPtr {
.engine()
.exec_fn_call(
&mut Default::default(),
context.namespaces(),
context.lib,
fn_name,
hash_script,
args.as_mut(),

View File

@@ -3297,25 +3297,24 @@ fn parse_stmt(
match input.peek().unwrap() {
// `return`/`throw` at <EOF>
(Token::EOF, pos) => Ok(Some(Stmt::ReturnWithVal(Box::new((
(return_type, *pos),
(return_type, token_pos),
None,
token_pos,
*pos,
))))),
// `return;` or `throw;`
(Token::SemiColon, _) => Ok(Some(Stmt::ReturnWithVal(Box::new((
(return_type, settings.pos),
(return_type, token_pos),
None,
token_pos,
settings.pos,
))))),
// `return` or `throw` with expression
(_, _) => {
let expr = parse_expr(input, state, lib, settings.level_up())?;
let pos = expr.position();
Ok(Some(Stmt::ReturnWithVal(Box::new((
(return_type, pos),
(return_type, token_pos),
Some(expr),
token_pos,
pos,
)))))
}
}

View File

@@ -4,6 +4,7 @@ use crate::any::Dynamic;
use crate::error::ParseErrorType;
use crate::parser::INT;
use crate::token::Position;
use crate::utils::ImmutableString;
#[cfg(not(feature = "no_function"))]
use crate::engine::is_anonymous_fn;
@@ -82,8 +83,8 @@ pub enum EvalAltResult {
ErrorDataTooLarge(String, usize, usize, Position),
/// The script is prematurely terminated.
ErrorTerminated(Position),
/// Run-time error encountered. Wrapped value is the error message.
ErrorRuntime(String, Position),
/// Run-time error encountered. Wrapped value is the error.
ErrorRuntime(Dynamic, Position),
/// Breaking out of loops - not an error if within a loop.
/// The wrapped value, if true, means breaking clean out of the loop (i.e. a `break` statement).
@@ -186,7 +187,12 @@ impl fmt::Display for EvalAltResult {
| Self::ErrorStackOverflow(_)
| Self::ErrorTerminated(_) => f.write_str(desc)?,
Self::ErrorRuntime(s, _) => f.write_str(if s.is_empty() { desc } else { s })?,
Self::ErrorRuntime(d, _) if d.is::<ImmutableString>() => {
let s = d.as_str().unwrap();
write!(f, "{}: {}", desc, if s.is_empty() { desc } else { s })?
}
Self::ErrorRuntime(d, _) if d.is::<()>() => f.write_str(desc)?,
Self::ErrorRuntime(d, _) => write!(f, "{}: {}", desc, d)?,
Self::ErrorAssignmentToConstant(s, _) => write!(f, "{}: '{}'", desc, s)?,
Self::ErrorMismatchOutputType(r, s, _) => {
@@ -248,7 +254,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(), Position::none())
Self::ErrorRuntime(err.as_ref().to_string().into(), Position::none())
}
}
@@ -256,13 +262,49 @@ impl<T: AsRef<str>> From<T> for Box<EvalAltResult> {
#[inline(always)]
fn from(err: T) -> Self {
Box::new(EvalAltResult::ErrorRuntime(
err.as_ref().to_string(),
err.as_ref().to_string().into(),
Position::none(),
))
}
}
impl EvalAltResult {
/// Can this error be caught?
pub fn catchable(&self) -> bool {
match self {
Self::ErrorSystem(_, _) => false,
Self::ErrorParsing(_, _) => false,
Self::ErrorFunctionNotFound(_, _)
| Self::ErrorInFunctionCall(_, _, _)
| Self::ErrorInModule(_, _, _)
| Self::ErrorUnboundThis(_)
| Self::ErrorMismatchDataType(_, _, _)
| Self::ErrorArrayBounds(_, _, _)
| Self::ErrorStringBounds(_, _, _)
| Self::ErrorIndexingType(_, _)
| Self::ErrorFor(_)
| Self::ErrorVariableNotFound(_, _)
| Self::ErrorModuleNotFound(_, _)
| Self::ErrorDataRace(_, _)
| Self::ErrorAssignmentToUnknownLHS(_)
| Self::ErrorAssignmentToConstant(_, _)
| Self::ErrorMismatchOutputType(_, _, _)
| Self::ErrorInExpr(_)
| Self::ErrorDotExpr(_, _)
| Self::ErrorArithmetic(_, _)
| Self::ErrorRuntime(_, _) => true,
Self::ErrorTooManyOperations(_)
| Self::ErrorTooManyModules(_)
| Self::ErrorStackOverflow(_)
| Self::ErrorDataTooLarge(_, _, _, _)
| Self::ErrorTerminated(_)
| Self::LoopBreak(_, _)
| Self::Return(_, _) => false,
}
}
/// Get the `Position` of this error.
pub fn position(&self) -> Position {
match self {

View File

@@ -64,14 +64,14 @@ impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_, '_> {
&mut self,
expr: &Expression,
) -> Result<Dynamic, Box<EvalAltResult>> {
self.engine().eval_expr(
self.engine.eval_expr(
self.scope,
self.mods,
self.state,
self.namespaces(),
self.lib,
self.this_ptr,
expr.expr(),
self.call_level(),
self.level,
)
}
}