Rename AST option flags.

This commit is contained in:
Stephen Chung 2022-01-28 08:28:17 +08:00
parent 09d03d07ed
commit b9f2fdb635
6 changed files with 41 additions and 37 deletions

View File

@ -378,9 +378,9 @@ pub enum Expr {
Stmt(Box<StmtBlock>), Stmt(Box<StmtBlock>),
/// func `(` expr `,` ... `)` /// func `(` expr `,` ... `)`
FnCall(Box<FnCallExpr>, Position), FnCall(Box<FnCallExpr>, Position),
/// lhs `.` rhs - bool variable is a dummy /// lhs `.` rhs - boolean variable is a dummy
Dot(Box<BinaryExpr>, bool, Position), Dot(Box<BinaryExpr>, bool, Position),
/// expr `[` expr `]` - boolean indicates whether the dotting/indexing chain stops /// lhs `[` rhs `]` - boolean indicates whether the dotting/indexing chain stops
Index(Box<BinaryExpr>, bool, Position), Index(Box<BinaryExpr>, bool, Position),
/// lhs `&&` rhs /// lhs `&&` rhs
And(Box<BinaryExpr>, Position), And(Box<BinaryExpr>, Position),

View File

@ -13,8 +13,12 @@ pub enum FnAccess {
Private, Private,
} }
/// A type that holds a configuration option with bit-flags. /// A type that holds a configuration option with bit-flags. Exported under the `internals` feature
/// Exported under the `internals` feature only. /// 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)] #[derive(PartialEq, Eq, Copy, Clone, Hash, Default)]
pub struct OptionFlags(u8); pub struct OptionFlags(u8);
@ -120,19 +124,20 @@ pub mod AST_OPTION_FLAGS {
/// _(internals)_ The [`AST`][crate::AST] node is constant. /// _(internals)_ The [`AST`][crate::AST] node is constant.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
pub const AST_OPTION_CONSTANT: OptionFlags = OptionFlags(0b0000_0001); 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. /// Exported under the `internals` feature only.
pub const AST_OPTION_PUBLIC: OptionFlags = OptionFlags(0b0000_0010); pub const AST_OPTION_EXPORTED: OptionFlags = OptionFlags(0b0000_0010);
/// _(internals)_ The [`AST`][crate::AST] node is in negated mode. /// _(internals)_ The [`AST`][crate::AST] node is in negated mode
/// (meaning whatever information is the opposite).
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
pub const AST_OPTION_NEGATED: OptionFlags = OptionFlags(0b0000_0100); pub const AST_OPTION_NEGATED: OptionFlags = OptionFlags(0b0000_0100);
/// _(internals)_ The [`AST`][crate::AST] node breaks out of normal control flow. /// _(internals)_ The [`AST`][crate::AST] node breaks out of normal control flow.
/// Exported under the `internals` feature only. /// 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. /// _(internals)_ Mask of all options.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
pub(crate) const AST_OPTION_ALL: OptionFlags = OptionFlags( 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 { impl std::fmt::Debug for OptionFlags {
@ -158,9 +163,9 @@ pub mod AST_OPTION_FLAGS {
f.write_str("(")?; f.write_str("(")?;
write_option(self, f, num_flags, AST_OPTION_CONSTANT, "Constant")?; 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_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(")")?; f.write_str(")")?;
Ok(()) Ok(())

View File

@ -1,6 +1,6 @@
//! Module defining script statements. //! 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::engine::KEYWORD_EVAL;
use crate::tokenizer::Token; use crate::tokenizer::Token;
use crate::{calc_fn_hash, Position, StaticVec, INT}; use crate::{calc_fn_hash, Position, StaticVec, INT};
@ -228,8 +228,8 @@ pub enum Stmt {
/// ///
/// ### Option Flags /// ### Option Flags
/// ///
/// * [`AST_OPTION_NONE`][AST_OPTION_FLAGS::AST_OPTION_NONE] = `while` /// * [`AST_OPTION_NONE`] = `while`
/// * [`AST_OPTION_NEGATED`][AST_OPTION_FLAGS::AST_OPTION_NEGATED] = `until` /// * [`AST_OPTION_NEGATED`] = `until`
Do(Box<StmtBlock>, Expr, OptionFlags, Position), Do(Box<StmtBlock>, Expr, OptionFlags, Position),
/// `for` `(` id `,` counter `)` `in` expr `{` stmt `}` /// `for` `(` id `,` counter `)` `in` expr `{` stmt `}`
For(Expr, Box<(Ident, Option<Ident>, StmtBlock)>, Position), For(Expr, Box<(Ident, Option<Ident>, StmtBlock)>, Position),
@ -237,8 +237,8 @@ pub enum Stmt {
/// ///
/// ### Option Flags /// ### Option Flags
/// ///
/// * [`AST_OPTION_PUBLIC`][AST_OPTION_FLAGS::AST_OPTION_PUBLIC] = `export` /// * [`AST_OPTION_EXPORTED`] = `export`
/// * [`AST_OPTION_CONSTANT`][AST_OPTION_FLAGS::AST_OPTION_CONSTANT] = `const` /// * [`AST_OPTION_CONSTANT`] = `const`
Var(Expr, Box<Ident>, OptionFlags, Position), Var(Expr, Box<Ident>, OptionFlags, Position),
/// expr op`=` expr /// expr op`=` expr
Assignment(Box<(Expr, Option<OpAssignment<'static>>, Expr)>, Position), Assignment(Box<(Expr, Option<OpAssignment<'static>>, Expr)>, Position),
@ -257,15 +257,15 @@ pub enum Stmt {
/// ///
/// ### Option Flags /// ### Option Flags
/// ///
/// * [`AST_OPTION_NONE`][AST_OPTION_FLAGS::AST_OPTION_NONE] = `continue` /// * [`AST_OPTION_NONE`] = `continue`
/// * [`AST_OPTION_BREAK_OUT`][AST_OPTION_FLAGS::AST_OPTION_BREAK_OUT] = `break` /// * [`AST_OPTION_BREAK`] = `break`
BreakLoop(OptionFlags, Position), BreakLoop(OptionFlags, Position),
/// `return`/`throw` /// `return`/`throw`
/// ///
/// ### Option Flags /// ### Option Flags
/// ///
/// * [`AST_OPTION_NONE`][AST_OPTION_FLAGS::AST_OPTION_NONE] = `return` /// * [`AST_OPTION_NONE`] = `return`
/// * [`AST_OPTION_BREAK_OUT`][AST_OPTION_FLAGS::AST_OPTION_BREAK_OUT] = `throw` /// * [`AST_OPTION_BREAK`] = `throw`
Return(OptionFlags, Option<Expr>, Position), Return(OptionFlags, Option<Expr>, Position),
/// `import` expr `as` var /// `import` expr `as` var
/// ///
@ -459,7 +459,7 @@ impl Stmt {
// Loops that exit can be pure because it can never be infinite. // Loops that exit can be pure because it can never be infinite.
Self::While(Expr::BoolConstant(false, _), _, _) => true, Self::While(Expr::BoolConstant(false, _), _, _) => true,
Self::Do(body, Expr::BoolConstant(x, _), options, _) 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) body.iter().all(Stmt::is_pure)
} }

View File

@ -677,7 +677,7 @@ impl Engine {
// Continue/Break statement // Continue/Break statement
Stmt::BreakLoop(options, pos) => { 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 // Try/Catch statement
@ -756,13 +756,12 @@ impl Engine {
} }
// Throw value // Throw value
Stmt::Return(options, Some(expr), pos) if options.contains(AST_OPTION_BREAK_OUT) => { Stmt::Return(options, Some(expr), pos) if options.contains(AST_OPTION_BREAK) => self
self.eval_expr(scope, global, state, lib, this_ptr, expr, level) .eval_expr(scope, global, state, lib, this_ptr, expr, level)
.and_then(|v| Err(ERR::ErrorRuntime(v.flatten(), *pos).into())) .and_then(|v| Err(ERR::ErrorRuntime(v.flatten(), *pos).into())),
}
// Empty throw // 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()) Err(ERR::ErrorRuntime(Dynamic::UNIT, *pos).into())
} }
@ -782,7 +781,7 @@ impl Engine {
} else { } else {
AccessMode::ReadWrite AccessMode::ReadWrite
}; };
let export = options.contains(AST_OPTION_PUBLIC); let export = options.contains(AST_OPTION_EXPORTED);
let value_result = self let value_result = self
.eval_expr(scope, global, state, lib, this_ptr, expr, level) .eval_expr(scope, global, state, lib, this_ptr, expr, level)

View File

@ -308,7 +308,7 @@ fn optimize_stmt_block(
match statements[..] { match statements[..] {
// { return; } -> {} // { return; } -> {}
[Stmt::Return(options, None, _)] [Stmt::Return(options, None, _)]
if reduce_return && !options.contains(AST_OPTION_BREAK_OUT) => if reduce_return && !options.contains(AST_OPTION_BREAK) =>
{ {
state.set_dirty(); state.set_dirty();
statements.clear(); statements.clear();
@ -320,7 +320,7 @@ fn optimize_stmt_block(
// { ...; return; } -> { ... } // { ...; return; } -> { ... }
[.., ref last_stmt, Stmt::Return(options, None, _)] [.., ref last_stmt, Stmt::Return(options, None, _)]
if reduce_return if reduce_return
&& !options.contains(AST_OPTION_BREAK_OUT) && !options.contains(AST_OPTION_BREAK)
&& !last_stmt.returns_value() => && !last_stmt.returns_value() =>
{ {
state.set_dirty(); state.set_dirty();
@ -328,7 +328,7 @@ fn optimize_stmt_block(
} }
// { ...; return val; } -> { ...; val } // { ...; return val; } -> { ...; val }
[.., Stmt::Return(options, ref mut expr, pos)] [.., 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(); state.set_dirty();
*statements.last_mut().unwrap() = expr *statements.last_mut().unwrap() = expr
@ -365,7 +365,7 @@ fn optimize_stmt_block(
} }
// { ...; return; } -> { ... } // { ...; return; } -> { ... }
[.., Stmt::Return(options, None, _)] [.., Stmt::Return(options, None, _)]
if reduce_return && !options.contains(AST_OPTION_BREAK_OUT) => if reduce_return && !options.contains(AST_OPTION_BREAK) =>
{ {
state.set_dirty(); state.set_dirty();
statements.pop().unwrap(); statements.pop().unwrap();
@ -373,7 +373,7 @@ fn optimize_stmt_block(
// { ...; return pure_val; } -> { ... } // { ...; return pure_val; } -> { ... }
[.., Stmt::Return(options, Some(ref expr), _)] [.., Stmt::Return(options, Some(ref expr), _)]
if reduce_return if reduce_return
&& !options.contains(AST_OPTION_BREAK_OUT) && !options.contains(AST_OPTION_BREAK)
&& expr.is_pure() => && expr.is_pure() =>
{ {
state.set_dirty(); state.set_dirty();
@ -663,7 +663,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
if body.len() == 1 { if body.len() == 1 {
match body[0] { match body[0] {
// while expr { break; } -> { expr; } // 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 // Only a single break statement - turn into running the guard expression once
state.set_dirty(); state.set_dirty();
if !condition.is_unit() { if !condition.is_unit() {

View File

@ -2520,7 +2520,7 @@ fn parse_let(
state.stack.push((name, var_type)); state.stack.push((name, var_type));
let export = if is_export { let export = if is_export {
AST_OPTION_PUBLIC AST_OPTION_EXPORTED
} else { } else {
AST_OPTION_NONE AST_OPTION_NONE
}; };
@ -2925,7 +2925,7 @@ fn parse_stmt(
} }
Token::Break if settings.default_options.allow_loop && settings.is_breakable => { Token::Break if settings.default_options.allow_loop && settings.is_breakable => {
let pos = eat_token(input, Token::Break); 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 => { Token::Continue | Token::Break if settings.default_options.allow_loop => {
Err(PERR::LoopBreak.into_err(token_pos)) Err(PERR::LoopBreak.into_err(token_pos))
@ -2937,7 +2937,7 @@ fn parse_stmt(
.map(|(token, pos)| { .map(|(token, pos)| {
let flags = match token { let flags = match token {
Token::Return => AST_OPTION_NONE, Token::Return => AST_OPTION_NONE,
Token::Throw => AST_OPTION_BREAK_OUT, Token::Throw => AST_OPTION_BREAK,
token => unreachable!( token => unreachable!(
"Token::Return or Token::Throw expected but gets {:?}", "Token::Return or Token::Throw expected but gets {:?}",
token token