commit
df07eaacdb
@ -20,7 +20,7 @@ smallvec = { version = "1.6", default-features = false, features = ["union"] }
|
||||
ahash = { version = "0.7", default-features = false }
|
||||
num-traits = { version = "0.2", default-features = false }
|
||||
smartstring = { version = "0.2.7", default-features = false }
|
||||
rhai_codegen = { version = "1.1", path = "codegen", default-features = false }
|
||||
rhai_codegen = { version = "1.2", path = "codegen", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["ahash/std", "num-traits/std"]
|
||||
|
30
src/ast.rs
30
src/ast.rs
@ -1667,11 +1667,11 @@ impl Stmt {
|
||||
pub struct CustomExpr {
|
||||
/// List of keywords.
|
||||
pub inputs: StaticVec<Expr>,
|
||||
/// List of tokens actually parsed.
|
||||
pub tokens: StaticVec<Identifier>,
|
||||
/// Is the current [`Scope`][crate::Scope] possibly modified by this custom statement
|
||||
/// (e.g. introducing a new variable)?
|
||||
pub scope_may_be_changed: bool,
|
||||
/// List of tokens actually parsed.
|
||||
pub tokens: StaticVec<Identifier>,
|
||||
/// Is this custom syntax self-terminated?
|
||||
pub self_terminated: bool,
|
||||
}
|
||||
@ -1693,7 +1693,7 @@ impl CustomExpr {
|
||||
/// # Volatile Data Structure
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub struct BinaryExpr {
|
||||
/// LHS expression.
|
||||
pub lhs: Expr,
|
||||
@ -1711,7 +1711,7 @@ pub struct BinaryExpr {
|
||||
pub struct OpAssignment<'a> {
|
||||
/// Hash of the op-assignment call.
|
||||
pub hash_op_assign: u64,
|
||||
/// Hash of the underlying operator call.
|
||||
/// Hash of the underlying operator call (for fallback).
|
||||
pub hash_op: u64,
|
||||
/// Op-assignment operator.
|
||||
pub op: &'a str,
|
||||
@ -1739,31 +1739,31 @@ impl OpAssignment<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// _(internals)_ An set of function call hashes.
|
||||
/// Exported under the `internals` feature only.
|
||||
/// _(internals)_ A set of function call hashes. Exported under the `internals` feature only.
|
||||
///
|
||||
/// Two separate hashes are pre-calculated because of the following pattern:
|
||||
/// Two separate hashes are pre-calculated because of the following patterns:
|
||||
///
|
||||
/// ```ignore
|
||||
/// func(a, b, c); // Native: func(a, b, c) - 3 parameters
|
||||
/// // Script: func(a, b, c) - 3 parameters
|
||||
/// func(a, b, c); // Native: func(a, b, c) - 3 parameters
|
||||
/// // Script: func(a, b, c) - 3 parameters
|
||||
///
|
||||
/// a.func(b, c); // Native: func(&mut a, b, c) - 3 parameters
|
||||
/// // Script: func(b, c) - 2 parameters
|
||||
/// a.func(b, c); // Native: func(&mut a, b, c) - 3 parameters
|
||||
/// // Script: func(b, c) - 2 parameters
|
||||
/// ```
|
||||
///
|
||||
/// For normal function calls, the native hash equals the script hash.
|
||||
///
|
||||
/// For method-style calls, the script hash contains one fewer parameter.
|
||||
///
|
||||
/// Function call hashes are used in the following manner:
|
||||
///
|
||||
/// * First, the script hash is tried, which contains only the called function's name plus the
|
||||
/// of parameters.
|
||||
/// number of parameters.
|
||||
///
|
||||
/// * Next, the actual types of arguments are hashed and _combined_ with the native hash, which is
|
||||
/// then used to search for a native function.
|
||||
/// In other words, a native function call hash always contains the called function's name plus
|
||||
/// the types of the arguments. This is to due to possible function overloading for different parameter types.
|
||||
/// then used to search for a native function. In other words, a complete native function call
|
||||
/// hash always contains the called function's name plus the types of the arguments. This is due
|
||||
/// to possible function overloading for different parameter types.
|
||||
///
|
||||
/// # Volatile Data Structure
|
||||
///
|
||||
|
218
src/parser.rs
218
src/parser.rs
@ -422,12 +422,11 @@ fn parse_paren_expr(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Expr, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// ( ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::LeftParen);
|
||||
|
||||
if match_token(input, Token::RightParen).0 {
|
||||
@ -597,11 +596,11 @@ fn parse_index_chain(
|
||||
lhs: Expr,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Expr, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut settings = settings;
|
||||
|
||||
let idx_expr = parse_expr(input, state, lib, settings.level_up())?;
|
||||
|
||||
// Check type of indexing - must be integer or string
|
||||
@ -760,12 +759,11 @@ fn parse_array_literal(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Expr, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// [ ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::LeftBracket);
|
||||
|
||||
let mut arr = StaticVec::new();
|
||||
@ -834,12 +832,11 @@ fn parse_map_literal(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Expr, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// #{ ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::MapStart);
|
||||
|
||||
let mut map = StaticVec::<(Ident, Expr)>::new();
|
||||
@ -952,12 +949,11 @@ fn parse_switch(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// switch ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::Switch);
|
||||
|
||||
let item = parse_expr(input, state, lib, settings.level_up())?;
|
||||
@ -1099,12 +1095,12 @@ fn parse_primary(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Expr, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let (token, token_pos) = input.peek().expect(NEVER_ENDS);
|
||||
|
||||
let mut settings = settings;
|
||||
settings.pos = *token_pos;
|
||||
|
||||
let mut root_expr = match token {
|
||||
@ -1358,48 +1354,48 @@ fn parse_primary(
|
||||
root_expr = match (root_expr, tail_token) {
|
||||
// Qualified function call with !
|
||||
(Expr::Variable(_, _, x), Token::Bang) if x.1.is_some() => {
|
||||
return Err(if !match_token(input, Token::LeftParen).0 {
|
||||
LexError::UnexpectedInput(Token::Bang.syntax().to_string()).into_err(tail_pos)
|
||||
return if !match_token(input, Token::LeftParen).0 {
|
||||
Err(LexError::UnexpectedInput(Token::Bang.syntax().to_string())
|
||||
.into_err(tail_pos))
|
||||
} else {
|
||||
LexError::ImproperSymbol(
|
||||
Err(LexError::ImproperSymbol(
|
||||
"!".to_string(),
|
||||
"'!' cannot be used to call module functions".to_string(),
|
||||
)
|
||||
.into_err(tail_pos)
|
||||
});
|
||||
.into_err(tail_pos))
|
||||
};
|
||||
}
|
||||
// Function call with !
|
||||
(Expr::Variable(_, var_pos, x), Token::Bang) => {
|
||||
let (matched, pos) = match_token(input, Token::LeftParen);
|
||||
if !matched {
|
||||
return Err(PERR::MissingToken(
|
||||
Token::LeftParen.syntax().into(),
|
||||
"to start arguments list of function call".into(),
|
||||
)
|
||||
.into_err(pos));
|
||||
(Expr::Variable(_, pos, x), Token::Bang) => {
|
||||
match match_token(input, Token::LeftParen) {
|
||||
(false, pos) => {
|
||||
return Err(PERR::MissingToken(
|
||||
Token::LeftParen.syntax().into(),
|
||||
"to start arguments list of function call".into(),
|
||||
)
|
||||
.into_err(pos))
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let (_, namespace, name) = *x;
|
||||
settings.pos = var_pos;
|
||||
settings.pos = pos;
|
||||
let ns = namespace.map(|(ns, _)| ns);
|
||||
parse_fn_call(input, state, lib, name, true, ns, settings.level_up())?
|
||||
}
|
||||
// Function call
|
||||
(Expr::Variable(_, var_pos, x), Token::LeftParen) => {
|
||||
(Expr::Variable(_, pos, x), Token::LeftParen) => {
|
||||
let (_, namespace, name) = *x;
|
||||
settings.pos = var_pos;
|
||||
let ns = namespace.map(|(ns, _)| ns);
|
||||
settings.pos = pos;
|
||||
parse_fn_call(input, state, lib, name, false, ns, settings.level_up())?
|
||||
}
|
||||
// module access
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
(Expr::Variable(_, var_pos, x), Token::DoubleColon) => {
|
||||
(Expr::Variable(_, pos, x), Token::DoubleColon) => {
|
||||
let (id2, pos2) = parse_var_name(input)?;
|
||||
let (_, mut namespace, var_name) = *x;
|
||||
let var_name_def = Ident {
|
||||
name: var_name,
|
||||
pos: var_pos,
|
||||
};
|
||||
let (_, mut namespace, name) = *x;
|
||||
let var_name_def = Ident { name, pos };
|
||||
|
||||
if let Some((ref mut namespace, _)) = namespace {
|
||||
namespace.push(var_name_def);
|
||||
@ -1437,7 +1433,6 @@ fn parse_primary(
|
||||
}
|
||||
|
||||
let rhs = parse_primary(input, state, lib, settings.level_up())?;
|
||||
|
||||
make_dot_expr(state, expr, false, rhs, tail_pos)?
|
||||
}
|
||||
// Unknown postfix operator
|
||||
@ -1482,14 +1477,14 @@ fn parse_unary(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Expr, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
let (token, token_pos) = input.peek().expect(NEVER_ENDS);
|
||||
settings.pos = *token_pos;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let (token, token_pos) = input.peek().expect(NEVER_ENDS);
|
||||
|
||||
let mut settings = settings;
|
||||
settings.pos = *token_pos;
|
||||
|
||||
match token {
|
||||
// -expr
|
||||
Token::Minus | Token::UnaryMinus => {
|
||||
@ -1676,7 +1671,7 @@ fn make_assignment_stmt(
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse an operator-assignment expression.
|
||||
/// Parse an operator-assignment expression (if any).
|
||||
fn parse_op_assignment_stmt(
|
||||
input: &mut TokenStream,
|
||||
state: &mut ParseState,
|
||||
@ -1684,23 +1679,24 @@ fn parse_op_assignment_stmt(
|
||||
lhs: Expr,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let (token, token_pos) = input.peek().expect(NEVER_ENDS);
|
||||
settings.pos = *token_pos;
|
||||
|
||||
let (op, pos) = match token {
|
||||
Token::Equals => (None, input.next().expect(NEVER_ENDS).1),
|
||||
_ if token.is_op_assignment() => input
|
||||
let (op, pos) = match input.peek().expect(NEVER_ENDS) {
|
||||
// var = ...
|
||||
(Token::Equals, _) => (None, eat_token(input, Token::Equals)),
|
||||
// var op= ...
|
||||
(token, _) if token.is_op_assignment() => input
|
||||
.next()
|
||||
.map(|(op, pos)| (Some(op), pos))
|
||||
.expect(NEVER_ENDS),
|
||||
// Not op-assignment
|
||||
_ => return Ok(Stmt::Expr(lhs)),
|
||||
};
|
||||
|
||||
let mut settings = settings;
|
||||
settings.pos = pos;
|
||||
|
||||
let rhs = parse_expr(input, state, lib, settings.level_up())?;
|
||||
make_assignment_stmt(op, state, lhs, rhs, pos)
|
||||
}
|
||||
@ -1714,25 +1710,27 @@ fn make_dot_expr(
|
||||
rhs: Expr,
|
||||
op_pos: Position,
|
||||
) -> Result<Expr, ParseError> {
|
||||
Ok(match (lhs, rhs) {
|
||||
match (lhs, rhs) {
|
||||
// lhs[idx_expr].rhs
|
||||
(Expr::Index(mut x, term, pos), rhs) => {
|
||||
x.rhs = make_dot_expr(state, x.rhs, term || terminate_chaining, rhs, op_pos)?;
|
||||
Expr::Index(x, false, pos)
|
||||
Ok(Expr::Index(x, false, pos))
|
||||
}
|
||||
// lhs.id
|
||||
(lhs, var_expr @ Expr::Variable(_, _, _)) if var_expr.is_variable_access(true) => {
|
||||
let rhs = var_expr.into_property(state);
|
||||
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
|
||||
Ok(Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos))
|
||||
}
|
||||
// lhs.module::id - syntax error
|
||||
(_, Expr::Variable(_, _, x)) => {
|
||||
return Err(PERR::PropertyExpected.into_err(x.1.expect("`Some`").0[0].pos))
|
||||
Err(PERR::PropertyExpected.into_err(x.1.expect("`Some`").0[0].pos))
|
||||
}
|
||||
// lhs.prop
|
||||
(lhs, prop @ Expr::Property(_)) => {
|
||||
Expr::Dot(BinaryExpr { lhs, rhs: prop }.into(), false, op_pos)
|
||||
}
|
||||
(lhs, prop @ Expr::Property(_)) => Ok(Expr::Dot(
|
||||
BinaryExpr { lhs, rhs: prop }.into(),
|
||||
false,
|
||||
op_pos,
|
||||
)),
|
||||
// lhs.dot_lhs.dot_rhs or lhs.dot_lhs[idx_rhs]
|
||||
(lhs, rhs @ Expr::Dot(_, _, _)) | (lhs, rhs @ Expr::Index(_, _, _)) => {
|
||||
let (x, term, pos, is_dot) = match rhs {
|
||||
@ -1754,7 +1752,7 @@ fn make_dot_expr(
|
||||
} else {
|
||||
Expr::Index(new_lhs, term, pos)
|
||||
};
|
||||
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
|
||||
Ok(Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos))
|
||||
}
|
||||
Expr::FnCall(mut func, func_pos) => {
|
||||
// Recalculate hash
|
||||
@ -1775,7 +1773,7 @@ fn make_dot_expr(
|
||||
} else {
|
||||
Expr::Index(new_lhs, term, pos)
|
||||
};
|
||||
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
|
||||
Ok(Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos))
|
||||
}
|
||||
_ => unreachable!("invalid dot expression: {:?}", x.lhs),
|
||||
}
|
||||
@ -1790,7 +1788,7 @@ fn make_dot_expr(
|
||||
&& [crate::engine::KEYWORD_FN_PTR, crate::engine::KEYWORD_EVAL]
|
||||
.contains(&x.name.as_ref()) =>
|
||||
{
|
||||
return Err(LexError::ImproperSymbol(
|
||||
Err(LexError::ImproperSymbol(
|
||||
x.name.to_string(),
|
||||
format!(
|
||||
"'{}' should not be called in method style. Try {}(...);",
|
||||
@ -1800,12 +1798,10 @@ fn make_dot_expr(
|
||||
.into_err(pos))
|
||||
}
|
||||
// lhs.func!(...)
|
||||
(_, Expr::FnCall(x, pos)) if x.capture_parent_scope => {
|
||||
return Err(PERR::MalformedCapture(
|
||||
"method-call style does not support running within the caller's scope".into(),
|
||||
)
|
||||
.into_err(pos))
|
||||
}
|
||||
(_, Expr::FnCall(x, pos)) if x.capture_parent_scope => Err(PERR::MalformedCapture(
|
||||
"method-call style does not support running within the caller's scope".into(),
|
||||
)
|
||||
.into_err(pos)),
|
||||
// lhs.func(...)
|
||||
(lhs, Expr::FnCall(mut func, func_pos)) => {
|
||||
// Recalculate hash
|
||||
@ -1816,14 +1812,14 @@ fn make_dot_expr(
|
||||
);
|
||||
|
||||
let rhs = Expr::FnCall(func, func_pos);
|
||||
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
|
||||
Ok(Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos))
|
||||
}
|
||||
// lhs.rhs
|
||||
(_, rhs) => return Err(PERR::PropertyExpected.into_err(rhs.position())),
|
||||
})
|
||||
(_, rhs) => Err(PERR::PropertyExpected.into_err(rhs.position())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a binary expression.
|
||||
/// Parse a binary expression (if any).
|
||||
fn parse_binary_op(
|
||||
input: &mut TokenStream,
|
||||
state: &mut ParseState,
|
||||
@ -1832,11 +1828,10 @@ fn parse_binary_op(
|
||||
lhs: Expr,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Expr, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut settings = settings;
|
||||
settings.pos = lhs.position();
|
||||
|
||||
let mut root = lhs;
|
||||
@ -2177,11 +2172,10 @@ fn parse_expr(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Expr, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut settings = settings;
|
||||
settings.pos = input.peek().expect(NEVER_ENDS).1;
|
||||
|
||||
// Check if it is a custom syntax.
|
||||
@ -2222,12 +2216,11 @@ fn parse_if(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// if ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::If);
|
||||
|
||||
// if guard { if_body }
|
||||
@ -2263,11 +2256,11 @@ fn parse_while_loop(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut settings = settings;
|
||||
|
||||
// while|loops ...
|
||||
let (guard, token_pos) = match input.next().expect(NEVER_ENDS) {
|
||||
(Token::While, pos) => {
|
||||
@ -2294,12 +2287,11 @@ fn parse_do(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// do ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::Do);
|
||||
|
||||
// do { body } [while|until] guard
|
||||
@ -2338,12 +2330,11 @@ fn parse_for(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// for ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::For);
|
||||
|
||||
// for name ...
|
||||
@ -2398,16 +2389,20 @@ fn parse_for(
|
||||
let prev_stack_len = state.stack.len();
|
||||
|
||||
let counter_var = if let Some(name) = counter_name {
|
||||
let counter_var = state.get_identifier(name);
|
||||
state
|
||||
.stack
|
||||
.push((counter_var.clone(), AccessMode::ReadWrite));
|
||||
Some(counter_var)
|
||||
let name = state.get_identifier(name);
|
||||
let pos = counter_pos.expect("`Some`");
|
||||
state.stack.push((name.clone(), AccessMode::ReadWrite));
|
||||
Some(Ident { name, pos })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let loop_var = state.get_identifier(name);
|
||||
state.stack.push((loop_var.clone(), AccessMode::ReadWrite));
|
||||
let loop_var = Ident {
|
||||
name: loop_var,
|
||||
pos: name_pos,
|
||||
};
|
||||
|
||||
settings.is_breakable = true;
|
||||
let body = parse_block(input, state, lib, settings.level_up())?;
|
||||
@ -2416,17 +2411,7 @@ fn parse_for(
|
||||
|
||||
Ok(Stmt::For(
|
||||
expr,
|
||||
Box::new((
|
||||
Ident {
|
||||
name: loop_var,
|
||||
pos: name_pos,
|
||||
},
|
||||
counter_var.map(|name| Ident {
|
||||
name,
|
||||
pos: counter_pos.expect("`Some`"),
|
||||
}),
|
||||
body.into(),
|
||||
)),
|
||||
Box::new((loop_var, counter_var, body.into())),
|
||||
settings.pos,
|
||||
))
|
||||
}
|
||||
@ -2440,12 +2425,11 @@ fn parse_let(
|
||||
is_export: bool,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// let/const... (specified in `var_type`)
|
||||
let mut settings = settings;
|
||||
settings.pos = input.next().expect(NEVER_ENDS).1;
|
||||
|
||||
// let name ...
|
||||
@ -2494,12 +2478,11 @@ fn parse_import(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// import ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::Import);
|
||||
|
||||
// import expr ...
|
||||
@ -2511,19 +2494,13 @@ fn parse_import(
|
||||
}
|
||||
|
||||
// import expr as name ...
|
||||
let (name, name_pos) = parse_var_name(input)?;
|
||||
let (name, pos) = parse_var_name(input)?;
|
||||
let name = state.get_identifier(name);
|
||||
state.modules.push(name.clone());
|
||||
|
||||
Ok(Stmt::Import(
|
||||
expr,
|
||||
Some(
|
||||
Ident {
|
||||
name,
|
||||
pos: name_pos,
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
Some(Ident { name, pos }.into()),
|
||||
settings.pos,
|
||||
))
|
||||
}
|
||||
@ -2536,11 +2513,10 @@ fn parse_export(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::Export);
|
||||
|
||||
match input.peek().expect(NEVER_ENDS) {
|
||||
@ -2610,9 +2586,11 @@ fn parse_block(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// Must start with {
|
||||
let mut settings = settings;
|
||||
settings.pos = match input.next().expect(NEVER_ENDS) {
|
||||
(Token::LeftBrace, pos) => pos,
|
||||
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
|
||||
@ -2625,9 +2603,6 @@ fn parse_block(
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut statements = Vec::with_capacity(8);
|
||||
|
||||
let prev_entry_stack_len = state.entry_stack_len;
|
||||
@ -2713,11 +2688,10 @@ fn parse_expr_stmt(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut settings = settings;
|
||||
settings.pos = input.peek().expect(NEVER_ENDS).1;
|
||||
|
||||
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
||||
@ -2934,12 +2908,11 @@ fn parse_try_catch(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<Stmt, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
// try ...
|
||||
let mut settings = settings;
|
||||
settings.pos = eat_token(input, Token::Try);
|
||||
|
||||
// try { body }
|
||||
@ -3001,11 +2974,11 @@ fn parse_fn(
|
||||
#[cfg(feature = "metadata")]
|
||||
comments: Vec<Box<str>>,
|
||||
) -> Result<ScriptFnDef, ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut settings = settings;
|
||||
|
||||
let (token, pos) = input.next().expect(NEVER_ENDS);
|
||||
|
||||
let name = match token.into_function_name_for_override() {
|
||||
@ -3142,11 +3115,10 @@ fn parse_anon_fn(
|
||||
lib: &mut FunctionsLib,
|
||||
settings: ParseSettings,
|
||||
) -> Result<(Expr, ScriptFnDef), ParseError> {
|
||||
let mut settings = settings;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
settings.ensure_level_within_max_limit(state.max_expr_depth)?;
|
||||
|
||||
let mut settings = settings;
|
||||
let mut params_list = StaticVec::new();
|
||||
|
||||
if input.next().expect(NEVER_ENDS).0 != Token::Or && !match_token(input, Token::Pipe).0 {
|
||||
|
Loading…
Reference in New Issue
Block a user