diff --git a/src/ast/expr.rs b/src/ast/expr.rs index d2256c5b..bda45d83 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -378,9 +378,9 @@ pub enum Expr { Stmt(Box), /// func `(` expr `,` ... `)` FnCall(Box, Position), - /// lhs `.` rhs - bool variable is a dummy + /// lhs `.` rhs - boolean variable is a dummy Dot(Box, bool, Position), - /// expr `[` expr `]` - boolean indicates whether the dotting/indexing chain stops + /// lhs `[` rhs `]` - boolean indicates whether the dotting/indexing chain stops Index(Box, bool, Position), /// lhs `&&` rhs And(Box, Position), diff --git a/src/ast/flags.rs b/src/ast/flags.rs index 0b548135..15b664e2 100644 --- a/src/ast/flags.rs +++ b/src/ast/flags.rs @@ -13,8 +13,12 @@ pub enum FnAccess { Private, } -/// A type that holds a configuration option with bit-flags. -/// Exported under the `internals` feature only. +/// A type that holds a configuration option with bit-flags. Exported under the `internals` feature +/// only. +/// +/// Functionality-wise, this type is a naive and simplistic implementation of +/// [`bit_flags`](https://crates.io/crates/bitflags). It is re-implemented to avoid pulling in yet +/// one more dependency. #[derive(PartialEq, Eq, Copy, Clone, Hash, Default)] pub struct OptionFlags(u8); @@ -120,19 +124,20 @@ pub mod AST_OPTION_FLAGS { /// _(internals)_ The [`AST`][crate::AST] node is constant. /// Exported under the `internals` feature only. pub const AST_OPTION_CONSTANT: OptionFlags = OptionFlags(0b0000_0001); - /// _(internals)_ The [`AST`][crate::AST] node is public. + /// _(internals)_ The [`AST`][crate::AST] node is exported to the outside (i.e. public). /// Exported under the `internals` feature only. - pub const AST_OPTION_PUBLIC: OptionFlags = OptionFlags(0b0000_0010); - /// _(internals)_ The [`AST`][crate::AST] node is in negated mode. + pub const AST_OPTION_EXPORTED: OptionFlags = OptionFlags(0b0000_0010); + /// _(internals)_ The [`AST`][crate::AST] node is in negated mode + /// (meaning whatever information is the opposite). /// Exported under the `internals` feature only. pub const AST_OPTION_NEGATED: OptionFlags = OptionFlags(0b0000_0100); /// _(internals)_ The [`AST`][crate::AST] node breaks out of normal control flow. /// Exported under the `internals` feature only. - pub const AST_OPTION_BREAK_OUT: OptionFlags = OptionFlags(0b0000_1000); + pub const AST_OPTION_BREAK: OptionFlags = OptionFlags(0b0000_1000); /// _(internals)_ Mask of all options. /// Exported under the `internals` feature only. pub(crate) const AST_OPTION_ALL: OptionFlags = OptionFlags( - AST_OPTION_CONSTANT.0 | AST_OPTION_PUBLIC.0 | AST_OPTION_NEGATED.0 | AST_OPTION_BREAK_OUT.0, + AST_OPTION_CONSTANT.0 | AST_OPTION_EXPORTED.0 | AST_OPTION_NEGATED.0 | AST_OPTION_BREAK.0, ); impl std::fmt::Debug for OptionFlags { @@ -158,9 +163,9 @@ pub mod AST_OPTION_FLAGS { f.write_str("(")?; write_option(self, f, num_flags, AST_OPTION_CONSTANT, "Constant")?; - write_option(self, f, num_flags, AST_OPTION_PUBLIC, "Public")?; + write_option(self, f, num_flags, AST_OPTION_EXPORTED, "Exported")?; write_option(self, f, num_flags, AST_OPTION_NEGATED, "Negated")?; - write_option(self, f, num_flags, AST_OPTION_BREAK_OUT, "Break")?; + write_option(self, f, num_flags, AST_OPTION_BREAK, "Break")?; f.write_str(")")?; Ok(()) diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index 136356a1..abd5369f 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -1,6 +1,6 @@ //! Module defining script statements. -use super::{ASTNode, Expr, FnCallExpr, Ident, OptionFlags, AST_OPTION_FLAGS}; +use super::{ASTNode, Expr, FnCallExpr, Ident, OptionFlags, AST_OPTION_FLAGS::*}; use crate::engine::KEYWORD_EVAL; use crate::tokenizer::Token; use crate::{calc_fn_hash, Position, StaticVec, INT}; @@ -228,8 +228,8 @@ pub enum Stmt { /// /// ### Option Flags /// - /// * [`AST_OPTION_NONE`][AST_OPTION_FLAGS::AST_OPTION_NONE] = `while` - /// * [`AST_OPTION_NEGATED`][AST_OPTION_FLAGS::AST_OPTION_NEGATED] = `until` + /// * [`AST_OPTION_NONE`] = `while` + /// * [`AST_OPTION_NEGATED`] = `until` Do(Box, Expr, OptionFlags, Position), /// `for` `(` id `,` counter `)` `in` expr `{` stmt `}` For(Expr, Box<(Ident, Option, StmtBlock)>, Position), @@ -237,8 +237,8 @@ pub enum Stmt { /// /// ### Option Flags /// - /// * [`AST_OPTION_PUBLIC`][AST_OPTION_FLAGS::AST_OPTION_PUBLIC] = `export` - /// * [`AST_OPTION_CONSTANT`][AST_OPTION_FLAGS::AST_OPTION_CONSTANT] = `const` + /// * [`AST_OPTION_EXPORTED`] = `export` + /// * [`AST_OPTION_CONSTANT`] = `const` Var(Expr, Box, OptionFlags, Position), /// expr op`=` expr Assignment(Box<(Expr, Option>, Expr)>, Position), @@ -257,15 +257,15 @@ pub enum Stmt { /// /// ### Option Flags /// - /// * [`AST_OPTION_NONE`][AST_OPTION_FLAGS::AST_OPTION_NONE] = `continue` - /// * [`AST_OPTION_BREAK_OUT`][AST_OPTION_FLAGS::AST_OPTION_BREAK_OUT] = `break` + /// * [`AST_OPTION_NONE`] = `continue` + /// * [`AST_OPTION_BREAK`] = `break` BreakLoop(OptionFlags, Position), /// `return`/`throw` /// /// ### Option Flags /// - /// * [`AST_OPTION_NONE`][AST_OPTION_FLAGS::AST_OPTION_NONE] = `return` - /// * [`AST_OPTION_BREAK_OUT`][AST_OPTION_FLAGS::AST_OPTION_BREAK_OUT] = `throw` + /// * [`AST_OPTION_NONE`] = `return` + /// * [`AST_OPTION_BREAK`] = `throw` Return(OptionFlags, Option, Position), /// `import` expr `as` var /// @@ -459,7 +459,7 @@ impl Stmt { // Loops that exit can be pure because it can never be infinite. Self::While(Expr::BoolConstant(false, _), _, _) => true, Self::Do(body, Expr::BoolConstant(x, _), options, _) - if *x == options.contains(AST_OPTION_FLAGS::AST_OPTION_NEGATED) => + if *x == options.contains(AST_OPTION_NEGATED) => { body.iter().all(Stmt::is_pure) } diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 7f004070..403ddad6 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -677,7 +677,7 @@ impl Engine { // Continue/Break statement Stmt::BreakLoop(options, pos) => { - Err(ERR::LoopBreak(options.contains(AST_OPTION_BREAK_OUT), *pos).into()) + Err(ERR::LoopBreak(options.contains(AST_OPTION_BREAK), *pos).into()) } // Try/Catch statement @@ -756,13 +756,12 @@ impl Engine { } // Throw value - Stmt::Return(options, Some(expr), pos) if options.contains(AST_OPTION_BREAK_OUT) => { - self.eval_expr(scope, global, state, lib, this_ptr, expr, level) - .and_then(|v| Err(ERR::ErrorRuntime(v.flatten(), *pos).into())) - } + Stmt::Return(options, Some(expr), pos) if options.contains(AST_OPTION_BREAK) => self + .eval_expr(scope, global, state, lib, this_ptr, expr, level) + .and_then(|v| Err(ERR::ErrorRuntime(v.flatten(), *pos).into())), // Empty throw - Stmt::Return(options, None, pos) if options.contains(AST_OPTION_BREAK_OUT) => { + Stmt::Return(options, None, pos) if options.contains(AST_OPTION_BREAK) => { Err(ERR::ErrorRuntime(Dynamic::UNIT, *pos).into()) } @@ -782,7 +781,7 @@ impl Engine { } else { AccessMode::ReadWrite }; - let export = options.contains(AST_OPTION_PUBLIC); + let export = options.contains(AST_OPTION_EXPORTED); let value_result = self .eval_expr(scope, global, state, lib, this_ptr, expr, level) diff --git a/src/optimizer.rs b/src/optimizer.rs index 7bfe8bbf..1b438502 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -308,7 +308,7 @@ fn optimize_stmt_block( match statements[..] { // { return; } -> {} [Stmt::Return(options, None, _)] - if reduce_return && !options.contains(AST_OPTION_BREAK_OUT) => + if reduce_return && !options.contains(AST_OPTION_BREAK) => { state.set_dirty(); statements.clear(); @@ -320,7 +320,7 @@ fn optimize_stmt_block( // { ...; return; } -> { ... } [.., ref last_stmt, Stmt::Return(options, None, _)] if reduce_return - && !options.contains(AST_OPTION_BREAK_OUT) + && !options.contains(AST_OPTION_BREAK) && !last_stmt.returns_value() => { state.set_dirty(); @@ -328,7 +328,7 @@ fn optimize_stmt_block( } // { ...; return val; } -> { ...; val } [.., Stmt::Return(options, ref mut expr, pos)] - if reduce_return && !options.contains(AST_OPTION_BREAK_OUT) => + if reduce_return && !options.contains(AST_OPTION_BREAK) => { state.set_dirty(); *statements.last_mut().unwrap() = expr @@ -365,7 +365,7 @@ fn optimize_stmt_block( } // { ...; return; } -> { ... } [.., Stmt::Return(options, None, _)] - if reduce_return && !options.contains(AST_OPTION_BREAK_OUT) => + if reduce_return && !options.contains(AST_OPTION_BREAK) => { state.set_dirty(); statements.pop().unwrap(); @@ -373,7 +373,7 @@ fn optimize_stmt_block( // { ...; return pure_val; } -> { ... } [.., Stmt::Return(options, Some(ref expr), _)] if reduce_return - && !options.contains(AST_OPTION_BREAK_OUT) + && !options.contains(AST_OPTION_BREAK) && expr.is_pure() => { state.set_dirty(); @@ -663,7 +663,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b if body.len() == 1 { match body[0] { // while expr { break; } -> { expr; } - Stmt::BreakLoop(options, pos) if options.contains(AST_OPTION_BREAK_OUT) => { + Stmt::BreakLoop(options, pos) if options.contains(AST_OPTION_BREAK) => { // Only a single break statement - turn into running the guard expression once state.set_dirty(); if !condition.is_unit() { diff --git a/src/parser.rs b/src/parser.rs index c7895361..0c814199 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2520,7 +2520,7 @@ fn parse_let( state.stack.push((name, var_type)); let export = if is_export { - AST_OPTION_PUBLIC + AST_OPTION_EXPORTED } else { AST_OPTION_NONE }; @@ -2925,7 +2925,7 @@ fn parse_stmt( } Token::Break if settings.default_options.allow_loop && settings.is_breakable => { let pos = eat_token(input, Token::Break); - Ok(Stmt::BreakLoop(AST_OPTION_BREAK_OUT, pos)) + Ok(Stmt::BreakLoop(AST_OPTION_BREAK, pos)) } Token::Continue | Token::Break if settings.default_options.allow_loop => { Err(PERR::LoopBreak.into_err(token_pos)) @@ -2937,7 +2937,7 @@ fn parse_stmt( .map(|(token, pos)| { let flags = match token { Token::Return => AST_OPTION_NONE, - Token::Throw => AST_OPTION_BREAK_OUT, + Token::Throw => AST_OPTION_BREAK, token => unreachable!( "Token::Return or Token::Throw expected but gets {:?}", token