diff --git a/src/ast.rs b/src/ast.rs index 6b0e4c76..daffd793 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -953,25 +953,27 @@ impl From for Stmt { /// A type that holds a configuration option with bit-flags. /// Exported under the `internals` feature only. #[derive(PartialEq, Eq, Copy, Clone, Hash, Default)] -pub struct BitOptions(u8); +pub struct OptionFlags(u8); -impl BitOptions { +impl OptionFlags { /// Does this [`BitOptions`] contain a particular option flag? #[inline(always)] + #[must_use] pub const fn contains(self, flag: Self) -> bool { self.0 & flag.0 != 0 } } -impl Not for BitOptions { +impl Not for OptionFlags { type Output = Self; + #[inline(always)] fn not(self) -> Self::Output { Self(!self.0) } } -impl Add for BitOptions { +impl Add for OptionFlags { type Output = Self; #[inline(always)] @@ -980,14 +982,14 @@ impl Add for BitOptions { } } -impl AddAssign for BitOptions { +impl AddAssign for OptionFlags { #[inline(always)] fn add_assign(&mut self, rhs: Self) { self.0 |= rhs.0 } } -impl Sub for BitOptions { +impl Sub for OptionFlags { type Output = Self; #[inline(always)] @@ -996,7 +998,7 @@ impl Sub for BitOptions { } } -impl SubAssign for BitOptions { +impl SubAssign for OptionFlags { #[inline(always)] fn sub_assign(&mut self, rhs: Self) { self.0 &= !rhs.0 @@ -1005,48 +1007,47 @@ impl SubAssign for BitOptions { /// Option bit-flags for [`AST`] nodes. #[allow(non_snake_case)] -pub mod AST_FLAGS { - use super::BitOptions; +pub mod AST_OPTION_FLAGS { + use super::OptionFlags; /// _(internals)_ No options for the [`AST`][crate::AST] node. /// Exported under the `internals` feature only. - pub const AST_FLAG_NONE: BitOptions = BitOptions(0b0000_0000); + pub const AST_OPTION_NONE: OptionFlags = OptionFlags(0b0000_0000); /// _(internals)_ The [`AST`][crate::AST] node is constant. /// Exported under the `internals` feature only. - pub const AST_FLAG_CONSTANT: BitOptions = BitOptions(0b0000_0001); + pub const AST_OPTION_CONSTANT: OptionFlags = OptionFlags(0b0000_0001); /// _(internals)_ The [`AST`][crate::AST] node is exported. /// Exported under the `internals` feature only. - pub const AST_FLAG_EXPORTED: BitOptions = BitOptions(0b0000_0010); + pub const AST_OPTION_EXPORTED: OptionFlags = OptionFlags(0b0000_0010); /// _(internals)_ The [`AST`][crate::AST] node is in negated mode. /// Exported under the `internals` feature only. - pub const AST_FLAG_NEGATED: BitOptions = BitOptions(0b0000_0100); + pub const AST_OPTION_NEGATED: OptionFlags = OptionFlags(0b0000_0100); - impl std::fmt::Debug for BitOptions { + impl std::fmt::Debug for OptionFlags { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut has_flags = false; + fn write_option( + options: &OptionFlags, + f: &mut std::fmt::Formatter<'_>, + num_flags: &mut usize, + flag: OptionFlags, + name: &str, + ) -> std::fmt::Result { + if options.contains(flag) { + if *num_flags > 0 { + f.write_str("+")?; + } + f.write_str(name)?; + *num_flags += 1; + } + Ok(()) + } + + let num_flags = &mut 0; f.write_str("(")?; - if self.contains(AST_FLAG_CONSTANT) { - if has_flags { - f.write_str("+")?; - } - f.write_str("Constant")?; - has_flags = true; - } - if self.contains(AST_FLAG_EXPORTED) { - if has_flags { - f.write_str("+")?; - } - f.write_str("Exported")?; - has_flags = true; - } - if self.contains(AST_FLAG_NEGATED) { - if has_flags { - f.write_str("+")?; - } - f.write_str("Negated")?; - //has_flags = true; - } + write_option(self, f, num_flags, AST_OPTION_CONSTANT, "Constant")?; + write_option(self, f, num_flags, AST_OPTION_EXPORTED, "Exported")?; + write_option(self, f, num_flags, AST_OPTION_NEGATED, "Negated")?; f.write_str(")")?; Ok(()) @@ -1076,20 +1077,20 @@ pub enum Stmt { While(Expr, Box, Position), /// `do` `{` stmt `}` `while`|`until` expr /// - /// ### Option flags + /// ### Option Flags /// /// * [`AST_FLAG_NONE`][AST_FLAGS::AST_FLAG_NONE] = `while` /// * [`AST_FLAG_NEGATED`][AST_FLAGS::AST_FLAG_NEGATED] = `until` - Do(Box, Expr, BitOptions, Position), + Do(Box, Expr, OptionFlags, Position), /// `for` `(` id `,` counter `)` `in` expr `{` stmt `}` For(Expr, Box<(Ident, Option, StmtBlock)>, Position), /// \[`export`\] `let`/`const` id `=` expr /// - /// ### Option flags + /// ### Option Flags /// /// * [`AST_FLAG_EXPORTED`][AST_FLAGS::AST_FLAG_EXPORTED] = `export` /// * [`AST_FLAG_CONSTANT`][AST_FLAGS::AST_FLAG_CONSTANT] = `const` - Var(Expr, Box, BitOptions, Position), + Var(Expr, Box, OptionFlags, Position), /// expr op`=` expr Assignment(Box<(Expr, Option>, Expr)>, Position), /// func `(` expr `,` ... `)` diff --git a/src/engine.rs b/src/engine.rs index 256c0aa7..cdba7f9f 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,6 +1,6 @@ //! Main module defining the script evaluation [`Engine`]. -use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, ReturnType, Stmt, AST_FLAGS::*}; +use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, ReturnType, Stmt, AST_OPTION_FLAGS::*}; use crate::custom_syntax::CustomSyntax; use crate::dynamic::{map_std_type_name, AccessMode, Union, Variant}; use crate::fn_hash::get_hasher; @@ -2569,8 +2569,8 @@ impl Engine { }, // Do loop - Stmt::Do(body, expr, flags, _) => loop { - let is_while = !flags.contains(AST_FLAG_NEGATED); + Stmt::Do(body, expr, options, _) => loop { + let is_while = !options.contains(AST_OPTION_NEGATED); if !body.is_empty() { match self.eval_stmt_block(scope, mods, state, lib, this_ptr, body, true, level) @@ -2853,14 +2853,14 @@ impl Engine { } // Let/const statement - Stmt::Var(expr, x, flags, _) => { + Stmt::Var(expr, x, options, _) => { let name = &x.name; - let entry_type = if flags.contains(AST_FLAG_CONSTANT) { + let entry_type = if options.contains(AST_OPTION_CONSTANT) { AccessMode::ReadOnly } else { AccessMode::ReadWrite }; - let export = flags.contains(AST_FLAG_EXPORTED); + let export = options.contains(AST_OPTION_EXPORTED); let value = self .eval_expr(scope, mods, state, lib, this_ptr, expr, level)? diff --git a/src/lib.rs b/src/lib.rs index 1d103f43..614a8fb8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -227,8 +227,8 @@ pub use token::{InputStream, Token, TokenizeState, TokenizerControl, TokenizerCo #[cfg(feature = "internals")] #[deprecated = "this type is volatile and may change"] pub use ast::{ - ASTNode, BinaryExpr, BitOptions, CustomExpr, Expr, FloatWrapper, FnCallExpr, FnCallHashes, - Ident, OpAssignment, ReturnType, ScriptFnDef, Stmt, StmtBlock, AST_FLAGS::*, + ASTNode, BinaryExpr, CustomExpr, Expr, FloatWrapper, FnCallExpr, FnCallHashes, Ident, + OpAssignment, OptionFlags, ReturnType, ScriptFnDef, Stmt, StmtBlock, AST_OPTION_FLAGS::*, }; #[cfg(feature = "internals")] diff --git a/src/optimize.rs b/src/optimize.rs index 13883603..3376240e 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -1,6 +1,6 @@ //! Module implementing the [`AST`] optimizer. -use crate::ast::{Expr, OpAssignment, Stmt, AST_FLAGS::*}; +use crate::ast::{Expr, OpAssignment, Stmt, AST_OPTION_FLAGS::*}; use crate::dynamic::AccessMode; use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT, KEYWORD_TYPE_OF}; use crate::fn_builtin::get_builtin_binary_op_fn; @@ -201,8 +201,8 @@ fn optimize_stmt_block( // Optimize each statement in the block statements.iter_mut().for_each(|stmt| { match stmt { - Stmt::Var(value_expr, x, flags, _) => { - if flags.contains(AST_FLAG_CONSTANT) { + Stmt::Var(value_expr, x, options, _) => { + if options.contains(AST_OPTION_CONSTANT) { // Add constant literals into the state optimize_expr(value_expr, state, false); @@ -583,8 +583,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b } } // do { block } while false | do { block } until true -> { block } - Stmt::Do(body, Expr::BoolConstant(x, _), flags, _) - if *x == flags.contains(AST_FLAG_NEGATED) => + Stmt::Do(body, Expr::BoolConstant(x, _), options, _) + if *x == options.contains(AST_OPTION_NEGATED) => { state.set_dirty(); let block_pos = body.position(); @@ -607,7 +607,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b *x.2.statements_mut() = optimize_stmt_block(body, state, false, true, false).into(); } // let id = expr; - Stmt::Var(expr, _, flags, _) if !flags.contains(AST_FLAG_CONSTANT) => { + Stmt::Var(expr, _, options, _) if !options.contains(AST_OPTION_CONSTANT) => { optimize_expr(expr, state, false) } // import expr as var; diff --git a/src/parse.rs b/src/parse.rs index cdfff3ad..777020d8 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -2,7 +2,7 @@ use crate::ast::{ BinaryExpr, CustomExpr, Expr, FnCallExpr, FnCallHashes, Ident, OpAssignment, ReturnType, - ScriptFnDef, Stmt, StmtBlock, AST_FLAGS::*, + ScriptFnDef, Stmt, StmtBlock, AST_OPTION_FLAGS::*, }; use crate::custom_syntax::{ CustomSyntax, CUSTOM_SYNTAX_MARKER_BLOCK, CUSTOM_SYNTAX_MARKER_BOOL, CUSTOM_SYNTAX_MARKER_EXPR, @@ -2225,8 +2225,8 @@ fn parse_do( let body = parse_block(input, state, lib, settings.level_up())?; let negated = match input.next().expect(NEVER_ENDS) { - (Token::While, _) => AST_FLAG_NONE, - (Token::Until, _) => AST_FLAG_NEGATED, + (Token::While, _) => AST_OPTION_NONE, + (Token::Until, _) => AST_OPTION_NEGATED, (_, pos) => { return Err( PERR::MissingToken(Token::While.into(), "for the do statement".into()) @@ -2382,9 +2382,9 @@ fn parse_let( state.stack.push((name, var_type)); let export = if export { - AST_FLAG_EXPORTED + AST_OPTION_EXPORTED } else { - AST_FLAG_NONE + AST_OPTION_NONE }; match var_type { @@ -2394,7 +2394,7 @@ fn parse_let( AccessMode::ReadOnly => Ok(Stmt::Var( expr, var_def.into(), - AST_FLAG_CONSTANT + export, + AST_OPTION_CONSTANT + export, settings.pos, )), }