Merge Stmt::Let and Stmt::Const into Stmt::Var.

This commit is contained in:
Stephen Chung 2021-08-01 11:59:53 +08:00
parent 39f4baf769
commit 0944261b88
6 changed files with 48 additions and 38 deletions

View File

@ -950,6 +950,18 @@ impl From<StmtBlock> for Stmt {
} }
} }
/// _(internals)_ Type of variable declaration.
/// Exported under the `internals` feature only.
///
/// # Volatile Data Structure
///
/// This type is volatile and may change.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub enum VarDeclaration {
Let,
Const,
}
/// _(internals)_ A statement. /// _(internals)_ A statement.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
/// ///
@ -974,10 +986,8 @@ pub enum Stmt {
Do(Box<StmtBlock>, Expr, bool, Position), Do(Box<StmtBlock>, Expr, bool, 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),
/// \[`export`\] `let` id `=` expr /// \[`export`\] `let`/`const` id `=` expr
Let(Expr, Box<Ident>, bool, Position), Var(Expr, Box<Ident>, VarDeclaration, bool, Position),
/// \[`export`\] `const` id `=` expr
Const(Expr, Box<Ident>, bool, Position),
/// expr op`=` expr /// expr op`=` expr
Assignment(Box<(Expr, Option<OpAssignment<'static>>, Expr)>, Position), Assignment(Box<(Expr, Option<OpAssignment<'static>>, Expr)>, Position),
/// func `(` expr `,` ... `)` /// func `(` expr `,` ... `)`
@ -1058,8 +1068,7 @@ impl Stmt {
| Self::Do(_, _, _, pos) | Self::Do(_, _, _, pos)
| Self::For(_, _, pos) | Self::For(_, _, pos)
| Self::Return(_, _, pos) | Self::Return(_, _, pos)
| Self::Let(_, _, _, pos) | Self::Var(_, _, _, _, pos)
| Self::Const(_, _, _, pos)
| Self::TryCatch(_, pos) => *pos, | Self::TryCatch(_, pos) => *pos,
Self::Expr(x) => x.position(), Self::Expr(x) => x.position(),
@ -1088,8 +1097,7 @@ impl Stmt {
| Self::Do(_, _, _, pos) | Self::Do(_, _, _, pos)
| Self::For(_, _, pos) | Self::For(_, _, pos)
| Self::Return(_, _, pos) | Self::Return(_, _, pos)
| Self::Let(_, _, _, pos) | Self::Var(_, _, _, _, pos)
| Self::Const(_, _, _, pos)
| Self::TryCatch(_, pos) => *pos = new_pos, | Self::TryCatch(_, pos) => *pos = new_pos,
Self::Expr(x) => { Self::Expr(x) => {
@ -1123,8 +1131,7 @@ impl Stmt {
| Self::For(_, _, _) | Self::For(_, _, _)
| Self::TryCatch(_, _) => false, | Self::TryCatch(_, _) => false,
Self::Let(_, _, _, _) Self::Var(_, _, _, _, _)
| Self::Const(_, _, _, _)
| Self::Assignment(_, _) | Self::Assignment(_, _)
| Self::Continue(_) | Self::Continue(_)
| Self::Break(_) | Self::Break(_)
@ -1151,8 +1158,7 @@ impl Stmt {
// A No-op requires a semicolon in order to know it is an empty statement! // A No-op requires a semicolon in order to know it is an empty statement!
Self::Noop(_) => false, Self::Noop(_) => false,
Self::Let(_, _, _, _) Self::Var(_, _, _, _, _)
| Self::Const(_, _, _, _)
| Self::Assignment(_, _) | Self::Assignment(_, _)
| Self::FnCall(_, _) | Self::FnCall(_, _)
| Self::Expr(_) | Self::Expr(_)
@ -1193,10 +1199,7 @@ impl Stmt {
condition.is_pure() && block.0.iter().all(Stmt::is_pure) condition.is_pure() && block.0.iter().all(Stmt::is_pure)
} }
Self::For(iterable, x, _) => iterable.is_pure() && (x.2).0.iter().all(Stmt::is_pure), Self::For(iterable, x, _) => iterable.is_pure() && (x.2).0.iter().all(Stmt::is_pure),
Self::Let(_, _, _, _) Self::Var(_, _, _, _, _) | Self::Assignment(_, _) | Self::FnCall(_, _) => false,
| Self::Const(_, _, _, _)
| Self::Assignment(_, _)
| Self::FnCall(_, _) => false,
Self::Block(block, _) => block.iter().all(|stmt| stmt.is_pure()), Self::Block(block, _) => block.iter().all(|stmt| stmt.is_pure()),
Self::Continue(_) | Self::Break(_) | Self::Return(_, _, _) => false, Self::Continue(_) | Self::Break(_) | Self::Return(_, _, _) => false,
Self::TryCatch(x, _) => { Self::TryCatch(x, _) => {
@ -1222,7 +1225,7 @@ impl Stmt {
#[must_use] #[must_use]
pub fn is_internally_pure(&self) -> bool { pub fn is_internally_pure(&self) -> bool {
match self { match self {
Self::Let(expr, _, _, _) | Self::Const(expr, _, _, _) => expr.is_pure(), Self::Var(expr, _, _, _, _) => expr.is_pure(),
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Self::Import(expr, _, _) => expr.is_pure(), Self::Import(expr, _, _) => expr.is_pure(),
@ -1260,7 +1263,7 @@ impl Stmt {
} }
match self { match self {
Self::Let(e, _, _, _) | Self::Const(e, _, _, _) => { Self::Var(e, _, _, _, _) => {
if !e.walk(path, on_node) { if !e.walk(path, on_node) {
return false; return false;
} }

View File

@ -1,6 +1,6 @@
//! Main module defining the script evaluation [`Engine`]. //! Main module defining the script evaluation [`Engine`].
use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, ReturnType, Stmt}; use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, ReturnType, Stmt, VarDeclaration};
use crate::custom_syntax::CustomSyntax; use crate::custom_syntax::CustomSyntax;
use crate::dynamic::{map_std_type_name, AccessMode, Union, Variant}; use crate::dynamic::{map_std_type_name, AccessMode, Union, Variant};
use crate::fn_hash::get_hasher; use crate::fn_hash::get_hasher;
@ -2851,12 +2851,11 @@ impl Engine {
} }
// Let/const statement // Let/const statement
Stmt::Let(expr, x, export, _) | Stmt::Const(expr, x, export, _) => { Stmt::Var(expr, x, var_type, export, _) => {
let name = &x.name; let name = &x.name;
let entry_type = match stmt { let entry_type = match var_type {
Stmt::Let(_, _, _, _) => AccessMode::ReadWrite, VarDeclaration::Let => AccessMode::ReadWrite,
Stmt::Const(_, _, _, _) => AccessMode::ReadOnly, VarDeclaration::Const => AccessMode::ReadOnly,
_ => unreachable!("should be Stmt::Let or Stmt::Const, but gets {:?}", stmt),
}; };
let value = self let value = self

View File

@ -228,7 +228,7 @@ pub use token::{InputStream, Token, TokenizeState, TokenizerControl, TokenizerCo
#[deprecated = "this type is volatile and may change"] #[deprecated = "this type is volatile and may change"]
pub use ast::{ pub use ast::{
ASTNode, BinaryExpr, CustomExpr, Expr, FloatWrapper, FnCallExpr, FnCallHashes, Ident, ASTNode, BinaryExpr, CustomExpr, Expr, FloatWrapper, FnCallExpr, FnCallHashes, Ident,
OpAssignment, ReturnType, ScriptFnDef, Stmt, StmtBlock, OpAssignment, ReturnType, ScriptFnDef, Stmt, StmtBlock, VarDeclaration,
}; };
#[cfg(feature = "internals")] #[cfg(feature = "internals")]

View File

@ -1,6 +1,6 @@
//! Module implementing the [`AST`] optimizer. //! Module implementing the [`AST`] optimizer.
use crate::ast::{Expr, OpAssignment, Stmt}; use crate::ast::{Expr, OpAssignment, Stmt, VarDeclaration};
use crate::dynamic::AccessMode; use crate::dynamic::AccessMode;
use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT, KEYWORD_TYPE_OF}; use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT, KEYWORD_TYPE_OF};
use crate::fn_builtin::get_builtin_binary_op_fn; use crate::fn_builtin::get_builtin_binary_op_fn;
@ -202,7 +202,7 @@ fn optimize_stmt_block(
statements.iter_mut().for_each(|stmt| { statements.iter_mut().for_each(|stmt| {
match stmt { match stmt {
// Add constant literals into the state // Add constant literals into the state
Stmt::Const(value_expr, x, _, _) => { Stmt::Var(value_expr, x, VarDeclaration::Const, _, _) => {
optimize_expr(value_expr, state, false); optimize_expr(value_expr, state, false);
if value_expr.is_constant() { if value_expr.is_constant() {
@ -214,7 +214,7 @@ fn optimize_stmt_block(
} }
} }
// Add variables into the state // Add variables into the state
Stmt::Let(value_expr, x, _, _) => { Stmt::Var(value_expr, x, VarDeclaration::Let, _, _) => {
optimize_expr(value_expr, state, false); optimize_expr(value_expr, state, false);
state.push_var(&x.name, AccessMode::ReadWrite, None); state.push_var(&x.name, AccessMode::ReadWrite, None);
} }
@ -232,11 +232,7 @@ fn optimize_stmt_block(
.find_map(|(i, stmt)| match stmt { .find_map(|(i, stmt)| match stmt {
stmt if !is_pure(stmt) => Some(i), stmt if !is_pure(stmt) => Some(i),
Stmt::Let(e, _, _, _) | Stmt::Const(e, _, _, _) | Stmt::Expr(e) Stmt::Var(e, _, _, _, _) | Stmt::Expr(e) if !e.is_constant() => Some(i),
if !e.is_constant() =>
{
Some(i)
}
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Import(e, _, _) if !e.is_constant() => Some(i), Stmt::Import(e, _, _) if !e.is_constant() => Some(i),
@ -609,7 +605,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(); *x.2.statements_mut() = optimize_stmt_block(body, state, false, true, false).into();
} }
// let id = expr; // let id = expr;
Stmt::Let(expr, _, _, _) => optimize_expr(expr, state, false), Stmt::Var(expr, _, VarDeclaration::Let, _, _) => optimize_expr(expr, state, false),
// import expr as var; // import expr as var;
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Stmt::Import(expr, _, _) => optimize_expr(expr, state, false), Stmt::Import(expr, _, _) => optimize_expr(expr, state, false),

View File

@ -2,7 +2,7 @@
use crate::ast::{ use crate::ast::{
BinaryExpr, CustomExpr, Expr, FnCallExpr, FnCallHashes, Ident, OpAssignment, ReturnType, BinaryExpr, CustomExpr, Expr, FnCallExpr, FnCallHashes, Ident, OpAssignment, ReturnType,
ScriptFnDef, Stmt, StmtBlock, ScriptFnDef, Stmt, StmtBlock, VarDeclaration,
}; };
use crate::custom_syntax::{ use crate::custom_syntax::{
CustomSyntax, CUSTOM_SYNTAX_MARKER_BLOCK, CUSTOM_SYNTAX_MARKER_BOOL, CUSTOM_SYNTAX_MARKER_EXPR, CustomSyntax, CUSTOM_SYNTAX_MARKER_BLOCK, CUSTOM_SYNTAX_MARKER_BOOL, CUSTOM_SYNTAX_MARKER_EXPR,
@ -2383,9 +2383,21 @@ fn parse_let(
match var_type { match var_type {
// let name = expr // let name = expr
AccessMode::ReadWrite => Ok(Stmt::Let(expr, var_def.into(), export, settings.pos)), AccessMode::ReadWrite => Ok(Stmt::Var(
expr,
var_def.into(),
VarDeclaration::Let,
export,
settings.pos,
)),
// const name = { expr:constant } // const name = { expr:constant }
AccessMode::ReadOnly => Ok(Stmt::Const(expr, var_def.into(), export, settings.pos)), AccessMode::ReadOnly => Ok(Stmt::Var(
expr,
var_def.into(),
VarDeclaration::Const,
export,
settings.pos,
)),
} }
} }

View File

@ -86,7 +86,7 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
assert_eq!( assert_eq!(
format!("{:?}", ast), format!("{:?}", ast),
r#"AST { source: None, body: Block[Const(false @ 1:18, "DECISION" @ 1:7, false, 1:1), Expr(123 @ 1:51)], functions: Module, resolver: None }"# r#"AST { source: None, body: Block[Var(false @ 1:18, "DECISION" @ 1:7, Const, false, 1:1), Expr(123 @ 1:51)], functions: Module, resolver: None }"#
); );
let ast = engine.compile("if 1 == 2 { 42 }")?; let ast = engine.compile("if 1 == 2 { 42 }")?;