Code cleanup.

This commit is contained in:
Stephen Chung 2020-12-28 09:49:54 +08:00
parent 6b8d78d64c
commit 5c813ca7c0
7 changed files with 94 additions and 96 deletions

View File

@ -4,13 +4,16 @@ Rhai Release Notes
Version 0.19.9 Version 0.19.9
============== ==============
This version removes the confusing differences between _packages_ and _modules_ This version fixes a bug introduced in `0.19.8` which breaks property access
within closures.
It also removes the confusing differences between _packages_ and _modules_
by unifying the terminology and API under the global umbrella of _modules_. by unifying the terminology and API under the global umbrella of _modules_.
Bug fixes Bug fixes
--------- ---------
* Property access in * Bug when accessing properties in closures is fixed.
Breaking changes Breaking changes
---------------- ----------------

View File

@ -53,9 +53,10 @@ In this case, the first parameter should be `&mut T` of the custom type and the
Script-defined [function] signatures contain parameter names. Since all parameters, as well as Script-defined [function] signatures contain parameter names. Since all parameters, as well as
the return value, are [`Dynamic`] the types are simply not shown. the return value, are [`Dynamic`] the types are simply not shown.
A script-defined function always takes dynamic arguments, and the return type is also dynamic: A script-defined function always takes dynamic arguments, and the return type is also dynamic,
so no type information is needed:
> `foo(x, y, z) -> Dynamic` > `foo(x, y, z)`
probably defined as: probably defined as:

View File

@ -91,7 +91,7 @@ impl fmt::Display for ScriptFnDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
"{}{}({}) -> Dynamic", "{}{}({})",
if self.access.is_private() { if self.access.is_private() {
"private " "private "
} else { } else {
@ -133,7 +133,7 @@ impl fmt::Display for ScriptFnMetadata<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
"{}{}({}) -> Dynamic", "{}{}({})",
if self.access.is_private() { if self.access.is_private() {
"private " "private "
} else { } else {
@ -646,7 +646,7 @@ impl AsRef<Module> for AST {
/// ## WARNING /// ## WARNING
/// ///
/// This type is volatile and may change. /// This type is volatile and may change.
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Clone, Eq, PartialEq, Hash)]
pub struct Ident { pub struct Ident {
/// Identifier name. /// Identifier name.
pub name: ImmutableString, pub name: ImmutableString,
@ -654,6 +654,12 @@ pub struct Ident {
pub pos: Position, pub pos: Position,
} }
impl fmt::Debug for Ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Ident({:?} @ {:?})", self.name, self.pos)
}
}
/// _(INTERNALS)_ A type encapsulating the mode of a `return`/`throw` statement. /// _(INTERNALS)_ A type encapsulating the mode of a `return`/`throw` statement.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
/// ///

View File

@ -101,8 +101,6 @@ impl FuncInfo {
if return_type != "()" { if return_type != "()" {
sig.push_str(") -> "); sig.push_str(") -> ");
sig.push_str(&return_type); sig.push_str(&return_type);
} else if self.func.is_script() {
sig.push_str(") -> Dynamic");
} else { } else {
sig.push_str(")"); sig.push_str(")");
} }
@ -115,7 +113,7 @@ impl FuncInfo {
} }
if self.func.is_script() { if self.func.is_script() {
sig.push_str(") -> Dynamic"); sig.push_str(")");
} else { } else {
sig.push_str(") -> ?"); sig.push_str(") -> ?");
} }
@ -471,6 +469,7 @@ impl Module {
/// ///
/// By taking a mutable reference, it is assumed that some sub-modules will be modified. /// By taking a mutable reference, it is assumed that some sub-modules will be modified.
/// Thus the module is automatically set to be non-indexed. /// Thus the module is automatically set to be non-indexed.
#[cfg(not(feature = "no_module"))]
#[inline(always)] #[inline(always)]
pub(crate) fn sub_modules_mut(&mut self) -> &mut HashMap<ImmutableString, Shared<Module>> { pub(crate) fn sub_modules_mut(&mut self) -> &mut HashMap<ImmutableString, Shared<Module>> {
// We must assume that the user has changed the sub-modules // We must assume that the user has changed the sub-modules

View File

@ -39,7 +39,7 @@ use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
pub struct FileModuleResolver { pub struct FileModuleResolver {
path: PathBuf, base_path: PathBuf,
extension: String, extension: String,
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
@ -99,7 +99,7 @@ impl FileModuleResolver {
extension: impl Into<String>, extension: impl Into<String>,
) -> Self { ) -> Self {
Self { Self {
path: path.into(), base_path: path.into(),
extension: extension.into(), extension: extension.into(),
cache: Default::default(), cache: Default::default(),
} }
@ -127,13 +127,13 @@ impl FileModuleResolver {
/// Get the base path for script files. /// Get the base path for script files.
#[inline(always)] #[inline(always)]
pub fn path(&self) -> &Path { pub fn base_path(&self) -> &Path {
self.path.as_ref() self.base_path.as_ref()
} }
/// Set the base path for script files. /// Set the base path for script files.
#[inline(always)] #[inline(always)]
pub fn set_path(&mut self, path: impl Into<PathBuf>) -> &mut Self { pub fn set_base_path(&mut self, path: impl Into<PathBuf>) -> &mut Self {
self.path = path.into(); self.base_path = path.into();
self self
} }
@ -186,7 +186,7 @@ impl ModuleResolver for FileModuleResolver {
pos: Position, pos: Position,
) -> Result<Shared<Module>, Box<EvalAltResult>> { ) -> Result<Shared<Module>, Box<EvalAltResult>> {
// Construct the script file path // Construct the script file path
let mut file_path = self.path.clone(); let mut file_path = self.base_path.clone();
file_path.push(path); file_path.push(path);
file_path.set_extension(&self.extension); // Force extension file_path.set_extension(&self.extension); // Force extension

View File

@ -280,12 +280,12 @@ fn parse_paren_expr(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
// ( ...
settings.pos = eat_token(input, Token::LeftParen);
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// ( ...
settings.pos = eat_token(input, Token::LeftParen);
if match_token(input, Token::RightParen).0 { if match_token(input, Token::RightParen).0 {
return Ok(Expr::Unit(settings.pos)); return Ok(Expr::Unit(settings.pos));
} }
@ -316,11 +316,11 @@ fn parse_fn_call(
mut namespace: Option<NamespaceRef>, mut namespace: Option<NamespaceRef>,
settings: ParseSettings, settings: ParseSettings,
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
let (token, token_pos) = input.peek().unwrap();
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
let (token, token_pos) = input.peek().unwrap();
let mut args = StaticVec::new(); let mut args = StaticVec::new();
match token { match token {
@ -642,12 +642,12 @@ fn parse_array_literal(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
// [ ...
settings.pos = eat_token(input, Token::LeftBracket);
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// [ ...
settings.pos = eat_token(input, Token::LeftBracket);
let mut arr = StaticVec::new(); let mut arr = StaticVec::new();
loop { loop {
@ -712,12 +712,12 @@ fn parse_map_literal(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
// #{ ...
settings.pos = eat_token(input, Token::MapStart);
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// #{ ...
settings.pos = eat_token(input, Token::MapStart);
let mut map: StaticVec<(Ident, Expr)> = Default::default(); let mut map: StaticVec<(Ident, Expr)> = Default::default();
loop { loop {
@ -823,13 +823,12 @@ fn parse_switch(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
// switch ...
let token_pos = eat_token(input, Token::Switch);
settings.pos = token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// switch ...
settings.pos = eat_token(input, Token::Switch);
let item = parse_expr(input, state, lib, settings.level_up())?; let item = parse_expr(input, state, lib, settings.level_up())?;
match input.next().unwrap() { match input.next().unwrap() {
@ -950,12 +949,12 @@ fn parse_primary(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
let (token, token_pos) = input.peek().unwrap();
settings.pos = *token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
let (token, token_pos) = input.peek().unwrap();
settings.pos = *token_pos;
let mut root_expr = match token { let mut root_expr = match token {
Token::EOF => return Err(PERR::UnexpectedEOF.into_err(settings.pos)), Token::EOF => return Err(PERR::UnexpectedEOF.into_err(settings.pos)),
@ -1241,7 +1240,7 @@ fn parse_primary(
state.allow_capture = false; state.allow_capture = false;
} }
let rhs = parse_unary(input, state, lib, settings.level_up())?; let rhs = parse_primary(input, state, lib, settings.level_up())?;
make_dot_expr(state, expr, rhs, tail_pos)? make_dot_expr(state, expr, rhs, tail_pos)?
} }
// Unknown postfix operator // Unknown postfix operator
@ -1262,17 +1261,16 @@ fn parse_primary(
}, },
_ => None, _ => None,
} }
.map(|x| { .map(|x| match x.as_mut() {
if let (_, Some((ref mut hash, ref mut namespace)), Ident { name, .. }) = x.as_mut() { (_, Some((ref mut hash, ref mut namespace)), Ident { name, .. }) => {
// Qualifiers + variable name // Qualifiers + variable name
*hash = *hash =
calc_script_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0).unwrap(); calc_script_fn_hash(namespace.iter().map(|v| v.name.as_str()), name, 0).unwrap();
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
namespace.set_index(state.find_module(&namespace[0].name)); namespace.set_index(state.find_module(&namespace[0].name));
} else {
unreachable!();
} }
_ => unreachable!(),
}); });
// Make sure identifiers are valid // Make sure identifiers are valid
@ -1458,12 +1456,12 @@ fn parse_op_assignment_stmt(
lhs: Expr, lhs: Expr,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
let (token, token_pos) = input.peek().unwrap();
settings.pos = *token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
let (token, token_pos) = input.peek().unwrap();
settings.pos = *token_pos;
let op = match token { let op = match token {
Token::Equals => "".into(), Token::Equals => "".into(),
@ -1714,11 +1712,11 @@ fn parse_binary_op(
lhs: Expr, lhs: Expr,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
settings.pos = lhs.position();
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
settings.pos = lhs.position();
let mut root = lhs; let mut root = lhs;
loop { loop {
@ -1868,12 +1866,6 @@ fn parse_binary_op(
make_in_expr(current_lhs, rhs, pos)? make_in_expr(current_lhs, rhs, pos)?
} }
// #[cfg(not(feature = "no_object"))]
// Token::Period => {
// let rhs = args.pop().unwrap();
// let current_lhs = args.pop().unwrap();
// make_dot_expr(state, current_lhs, rhs, pos)?
// }
Token::Custom(s) Token::Custom(s)
if state if state
.engine .engine
@ -2017,11 +2009,11 @@ fn parse_expr(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
settings.pos = input.peek().unwrap().1;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
settings.pos = input.peek().unwrap().1;
// Check if it is a custom syntax. // Check if it is a custom syntax.
if !state.engine.custom_syntax.is_empty() { if !state.engine.custom_syntax.is_empty() {
let (token, pos) = input.peek().unwrap(); let (token, pos) = input.peek().unwrap();
@ -2095,13 +2087,12 @@ fn parse_if(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
// if ...
let token_pos = eat_token(input, Token::If);
settings.pos = token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// if ...
settings.pos = eat_token(input, Token::If);
// if guard { if_body } // if guard { if_body }
ensure_not_statement_expr(input, "a boolean")?; ensure_not_statement_expr(input, "a boolean")?;
let guard = parse_expr(input, state, lib, settings.level_up())?; let guard = parse_expr(input, state, lib, settings.level_up())?;
@ -2121,7 +2112,11 @@ fn parse_if(
None None
}; };
Ok(Stmt::If(guard, Box::new((if_body, else_body)), token_pos)) Ok(Stmt::If(
guard,
Box::new((if_body, else_body)),
settings.pos,
))
} }
/// Parse a while loop. /// Parse a while loop.
@ -2149,7 +2144,7 @@ fn parse_while_loop(
settings.is_breakable = true; settings.is_breakable = true;
let body = Box::new(parse_block(input, state, lib, settings.level_up())?); let body = Box::new(parse_block(input, state, lib, settings.level_up())?);
Ok(Stmt::While(guard, body, token_pos)) Ok(Stmt::While(guard, body, settings.pos))
} }
/// Parse a do loop. /// Parse a do loop.
@ -2159,13 +2154,12 @@ fn parse_do(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
// do ...
let token_pos = eat_token(input, Token::Do);
settings.pos = token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// do ...
settings.pos = eat_token(input, Token::Do);
// do { body } [while|until] guard // do { body } [while|until] guard
settings.is_breakable = true; settings.is_breakable = true;
let body = Box::new(parse_block(input, state, lib, settings.level_up())?); let body = Box::new(parse_block(input, state, lib, settings.level_up())?);
@ -2186,7 +2180,7 @@ fn parse_do(
let guard = parse_expr(input, state, lib, settings.level_up())?; let guard = parse_expr(input, state, lib, settings.level_up())?;
ensure_not_assignment(input)?; ensure_not_assignment(input)?;
Ok(Stmt::Do(body, guard, is_while, token_pos)) Ok(Stmt::Do(body, guard, is_while, settings.pos))
} }
/// Parse a for loop. /// Parse a for loop.
@ -2196,13 +2190,12 @@ fn parse_for(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
// for ...
let token_pos = eat_token(input, Token::For);
settings.pos = token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// for ...
settings.pos = eat_token(input, Token::For);
// for name ... // for name ...
let name = match input.next().unwrap() { let name = match input.next().unwrap() {
// Variable name // Variable name
@ -2242,7 +2235,7 @@ fn parse_for(
state.stack.truncate(prev_stack_len); state.stack.truncate(prev_stack_len);
Ok(Stmt::For(expr, Box::new((name, body)), token_pos)) Ok(Stmt::For(expr, Box::new((name, body)), settings.pos))
} }
/// Parse a variable definition statement. /// Parse a variable definition statement.
@ -2254,13 +2247,12 @@ fn parse_let(
export: bool, export: bool,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
// let/const... (specified in `var_type`)
let token_pos = input.next().unwrap().1;
settings.pos = token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// let/const... (specified in `var_type`)
settings.pos = input.next().unwrap().1;
// let name ... // let name ...
let (name, pos) = match input.next().unwrap() { let (name, pos) = match input.next().unwrap() {
(Token::Identifier(s), pos) => (s, pos), (Token::Identifier(s), pos) => (s, pos),
@ -2272,7 +2264,7 @@ fn parse_let(
}; };
// let name = ... // let name = ...
let init_expr = if match_token(input, Token::Equals).0 { let expr = if match_token(input, Token::Equals).0 {
// let name = expr // let name = expr
Some(parse_expr(input, state, lib, settings.level_up())?) Some(parse_expr(input, state, lib, settings.level_up())?)
} else { } else {
@ -2285,14 +2277,14 @@ fn parse_let(
let name = state.get_interned_string(name); let name = state.get_interned_string(name);
state.stack.push((name.clone(), AccessMode::ReadWrite)); state.stack.push((name.clone(), AccessMode::ReadWrite));
let var_def = Ident { name, pos }; let var_def = Ident { name, pos };
Ok(Stmt::Let(Box::new(var_def), init_expr, export, token_pos)) Ok(Stmt::Let(Box::new(var_def), expr, export, settings.pos))
} }
// const name = { expr:constant } // const name = { expr:constant }
AccessMode::ReadOnly => { AccessMode::ReadOnly => {
let name = state.get_interned_string(name); let name = state.get_interned_string(name);
state.stack.push((name.clone(), AccessMode::ReadOnly)); state.stack.push((name.clone(), AccessMode::ReadOnly));
let var_def = Ident { name, pos }; let var_def = Ident { name, pos };
Ok(Stmt::Const(Box::new(var_def), init_expr, export, token_pos)) Ok(Stmt::Const(Box::new(var_def), expr, export, settings.pos))
} }
} }
} }
@ -2305,23 +2297,22 @@ fn parse_import(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
// import ...
let token_pos = eat_token(input, Token::Import);
settings.pos = token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// import ...
settings.pos = eat_token(input, Token::Import);
// import expr ... // import expr ...
let expr = parse_expr(input, state, lib, settings.level_up())?; let expr = parse_expr(input, state, lib, settings.level_up())?;
// import expr as ... // import expr as ...
if !match_token(input, Token::As).0 { if !match_token(input, Token::As).0 {
return Ok(Stmt::Import(expr, None, token_pos)); return Ok(Stmt::Import(expr, None, settings.pos));
} }
// import expr as name ... // import expr as name ...
let (name, _) = match input.next().unwrap() { let (name, name_pos) = match input.next().unwrap() {
(Token::Identifier(s), pos) => (s, pos), (Token::Identifier(s), pos) => (s, pos),
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => { (Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
return Err(PERR::Reserved(s).into_err(pos)); return Err(PERR::Reserved(s).into_err(pos));
@ -2337,9 +2328,9 @@ fn parse_import(
expr, expr,
Some(Box::new(Ident { Some(Box::new(Ident {
name, name,
pos: settings.pos, pos: name_pos,
})), })),
token_pos, settings.pos,
)) ))
} }
@ -2351,12 +2342,11 @@ fn parse_export(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
let token_pos = eat_token(input, Token::Export);
settings.pos = token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
settings.pos = eat_token(input, Token::Export);
match input.peek().unwrap() { match input.peek().unwrap() {
(Token::Let, pos) => { (Token::Let, pos) => {
let pos = *pos; let pos = *pos;
@ -2424,7 +2414,7 @@ fn parse_export(
} }
} }
Ok(Stmt::Export(exports, token_pos)) Ok(Stmt::Export(exports, settings.pos))
} }
/// Parse a statement block. /// Parse a statement block.
@ -2513,11 +2503,11 @@ fn parse_expr_stmt(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
settings.pos = input.peek().unwrap().1;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
settings.pos = input.peek().unwrap().1;
let expr = parse_expr(input, state, lib, settings.level_up())?; let expr = parse_expr(input, state, lib, settings.level_up())?;
let stmt = parse_op_assignment_stmt(input, state, lib, expr, settings.level_up())?; let stmt = parse_op_assignment_stmt(input, state, lib, expr, settings.level_up())?;
Ok(stmt) Ok(stmt)
@ -2715,13 +2705,12 @@ fn parse_try_catch(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
mut settings: ParseSettings, mut settings: ParseSettings,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, ParseError> {
// try ...
let token_pos = eat_token(input, Token::Try);
settings.pos = token_pos;
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
// try ...
settings.pos = eat_token(input, Token::Try);
// try { body } // try { body }
let body = parse_block(input, state, lib, settings.level_up())?; let body = parse_block(input, state, lib, settings.level_up())?;
@ -2765,7 +2754,7 @@ fn parse_try_catch(
Ok(Stmt::TryCatch( Ok(Stmt::TryCatch(
Box::new((body, var_def, catch_body)), Box::new((body, var_def, catch_body)),
token_pos, settings.pos,
catch_pos, catch_pos,
)) ))
} }

View File

@ -55,7 +55,7 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?; let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?;
assert!(format!("{:?}", ast).starts_with(r#"AST { source: None, statements: [Block([Const(Ident { name: "DECISION", pos: 1:9 }, Some(Unit(0:0)), false, 1:3), Expr(IntegerConstant(123, 1:53))], 1:1)]"#)); assert!(format!("{:?}", ast).starts_with(r#"AST { source: None, statements: [Block([Const(Ident("DECISION" @ 1:9), Some(Unit(0:0)), false, 1:3), Expr(IntegerConstant(123, 1:53))], 1:1)]"#));
let ast = engine.compile("if 1 == 2 { 42 }")?; let ast = engine.compile("if 1 == 2 { 42 }")?;