Use StaticVec for parsing.
This commit is contained in:
parent
b961a10d27
commit
c84f80d433
@ -2040,7 +2040,7 @@ impl Engine {
|
|||||||
let lib = Default::default();
|
let lib = Default::default();
|
||||||
|
|
||||||
let stmt = std::mem::take(ast.statements_mut());
|
let stmt = std::mem::take(ast.statements_mut());
|
||||||
crate::optimize::optimize_into_ast(self, scope, stmt.into_vec(), lib, optimization_level)
|
crate::optimize::optimize_into_ast(self, scope, stmt, lib, optimization_level)
|
||||||
}
|
}
|
||||||
/// _(metadata)_ Generate a list of all registered functions.
|
/// _(metadata)_ Generate a list of all registered functions.
|
||||||
/// Exported under the `metadata` feature only.
|
/// Exported under the `metadata` feature only.
|
||||||
@ -2053,9 +2053,7 @@ impl Engine {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> {
|
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> {
|
||||||
let mut signatures = Vec::new();
|
let mut signatures = self.global_namespace().gen_fn_signatures();
|
||||||
|
|
||||||
signatures.extend(self.global_namespace().gen_fn_signatures());
|
|
||||||
|
|
||||||
self.global_sub_modules.iter().for_each(|(name, m)| {
|
self.global_sub_modules.iter().for_each(|(name, m)| {
|
||||||
signatures.extend(m.gen_fn_signatures().map(|f| format!("{}::{}", name, f)))
|
signatures.extend(m.gen_fn_signatures().map(|f| format!("{}::{}", name, f)))
|
||||||
|
@ -51,7 +51,7 @@ struct OptimizerState<'a> {
|
|||||||
/// Has the [`AST`] been changed during this pass?
|
/// Has the [`AST`] been changed during this pass?
|
||||||
changed: bool,
|
changed: bool,
|
||||||
/// Collection of constants to use for eager function evaluations.
|
/// Collection of constants to use for eager function evaluations.
|
||||||
variables: Vec<(String, AccessMode, Option<Dynamic>)>,
|
variables: StaticVec<(String, AccessMode, Option<Dynamic>)>,
|
||||||
/// Activate constants propagation?
|
/// Activate constants propagation?
|
||||||
propagate_constants: bool,
|
propagate_constants: bool,
|
||||||
/// An [`Engine`] instance for eager function evaluation.
|
/// An [`Engine`] instance for eager function evaluation.
|
||||||
@ -65,14 +65,14 @@ struct OptimizerState<'a> {
|
|||||||
impl<'a> OptimizerState<'a> {
|
impl<'a> OptimizerState<'a> {
|
||||||
/// Create a new State.
|
/// Create a new State.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn new(
|
pub fn new(
|
||||||
engine: &'a Engine,
|
engine: &'a Engine,
|
||||||
lib: &'a [&'a Module],
|
lib: &'a [&'a Module],
|
||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
changed: false,
|
changed: false,
|
||||||
variables: Vec::new(),
|
variables: StaticVec::new(),
|
||||||
propagate_constants: true,
|
propagate_constants: true,
|
||||||
engine,
|
engine,
|
||||||
lib,
|
lib,
|
||||||
@ -158,12 +158,12 @@ impl<'a> OptimizerState<'a> {
|
|||||||
|
|
||||||
/// Optimize a block of [statements][Stmt].
|
/// Optimize a block of [statements][Stmt].
|
||||||
fn optimize_stmt_block(
|
fn optimize_stmt_block(
|
||||||
mut statements: Vec<Stmt>,
|
mut statements: StaticVec<Stmt>,
|
||||||
state: &mut OptimizerState,
|
state: &mut OptimizerState,
|
||||||
preserve_result: bool,
|
preserve_result: bool,
|
||||||
is_internal: bool,
|
is_internal: bool,
|
||||||
reduce_return: bool,
|
reduce_return: bool,
|
||||||
) -> Vec<Stmt> {
|
) -> StaticVec<Stmt> {
|
||||||
if statements.is_empty() {
|
if statements.is_empty() {
|
||||||
return statements;
|
return statements;
|
||||||
}
|
}
|
||||||
@ -456,7 +456,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// if false { if_block } else { else_block } -> else_block
|
// if false { if_block } else { else_block } -> else_block
|
||||||
Stmt::If(Expr::BoolConstant(false, _), x, _) => {
|
Stmt::If(Expr::BoolConstant(false, _), x, _) => {
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
let else_block = mem::take(&mut *x.1).into_vec();
|
let else_block = mem::take(&mut *x.1);
|
||||||
*stmt = match optimize_stmt_block(else_block, state, preserve_result, true, false) {
|
*stmt = match optimize_stmt_block(else_block, state, preserve_result, true, false) {
|
||||||
statements if statements.is_empty() => Stmt::Noop(x.1.position()),
|
statements if statements.is_empty() => Stmt::Noop(x.1.position()),
|
||||||
statements => Stmt::Block(statements.into_boxed_slice(), x.1.position()),
|
statements => Stmt::Block(statements.into_boxed_slice(), x.1.position()),
|
||||||
@ -465,7 +465,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// if true { if_block } else { else_block } -> if_block
|
// if true { if_block } else { else_block } -> if_block
|
||||||
Stmt::If(Expr::BoolConstant(true, _), x, _) => {
|
Stmt::If(Expr::BoolConstant(true, _), x, _) => {
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
let if_block = mem::take(&mut *x.0).into_vec();
|
let if_block = mem::take(&mut *x.0);
|
||||||
*stmt = match optimize_stmt_block(if_block, state, preserve_result, true, false) {
|
*stmt = match optimize_stmt_block(if_block, state, preserve_result, true, false) {
|
||||||
statements if statements.is_empty() => Stmt::Noop(x.0.position()),
|
statements if statements.is_empty() => Stmt::Noop(x.0.position()),
|
||||||
statements => Stmt::Block(statements.into_boxed_slice(), x.0.position()),
|
statements => Stmt::Block(statements.into_boxed_slice(), x.0.position()),
|
||||||
@ -474,10 +474,10 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// if expr { if_block } else { else_block }
|
// if expr { if_block } else { else_block }
|
||||||
Stmt::If(condition, x, _) => {
|
Stmt::If(condition, x, _) => {
|
||||||
optimize_expr(condition, state, false);
|
optimize_expr(condition, state, false);
|
||||||
let if_block = mem::take(x.0.deref_mut()).into_vec();
|
let if_block = mem::take(x.0.deref_mut());
|
||||||
*x.0 = optimize_stmt_block(if_block, state, preserve_result, true, false).into();
|
*x.0 = optimize_stmt_block(if_block, state, preserve_result, true, false);
|
||||||
let else_block = mem::take(x.1.deref_mut()).into_vec();
|
let else_block = mem::take(x.1.deref_mut());
|
||||||
*x.1 = optimize_stmt_block(else_block, state, preserve_result, true, false).into();
|
*x.1 = optimize_stmt_block(else_block, state, preserve_result, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch const { ... }
|
// switch const { ... }
|
||||||
@ -497,7 +497,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// switch const { case if condition => stmt, _ => def } => if condition { stmt } else { def }
|
// switch const { case if condition => stmt, _ => def } => if condition { stmt } else { def }
|
||||||
optimize_expr(&mut condition, state, false);
|
optimize_expr(&mut condition, state, false);
|
||||||
|
|
||||||
let def_block = mem::take(&mut *x.1).into_vec();
|
let def_block = mem::take(&mut *x.1);
|
||||||
let def_stmt = optimize_stmt_block(def_block, state, true, true, false);
|
let def_stmt = optimize_stmt_block(def_block, state, true, true, false);
|
||||||
let def_pos = if x.1.position().is_none() {
|
let def_pos = if x.1.position().is_none() {
|
||||||
*pos
|
*pos
|
||||||
@ -517,13 +517,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// Promote the matched case
|
// Promote the matched case
|
||||||
let new_pos = block.1.position();
|
let new_pos = block.1.position();
|
||||||
let statements = mem::take(&mut *block.1);
|
let statements = mem::take(&mut *block.1);
|
||||||
let statements =
|
let statements = optimize_stmt_block(statements, state, true, true, false);
|
||||||
optimize_stmt_block(statements.into_vec(), state, true, true, false);
|
|
||||||
*stmt = Stmt::Block(statements.into_boxed_slice(), new_pos);
|
*stmt = Stmt::Block(statements.into_boxed_slice(), new_pos);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Promote the default case
|
// Promote the default case
|
||||||
let def_block = mem::take(&mut *x.1).into_vec();
|
let def_block = mem::take(&mut *x.1);
|
||||||
let def_stmt = optimize_stmt_block(def_block, state, true, true, false);
|
let def_stmt = optimize_stmt_block(def_block, state, true, true, false);
|
||||||
let def_pos = if x.1.position().is_none() {
|
let def_pos = if x.1.position().is_none() {
|
||||||
*pos
|
*pos
|
||||||
@ -551,13 +550,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
block.0 = Some(condition);
|
block.0 = Some(condition);
|
||||||
|
|
||||||
*block.1 = optimize_stmt_block(
|
*block.1 = optimize_stmt_block(
|
||||||
mem::take(block.1.deref_mut()).into_vec(),
|
mem::take(block.1.deref_mut()),
|
||||||
state,
|
state,
|
||||||
preserve_result,
|
preserve_result,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
)
|
);
|
||||||
.into();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -571,8 +569,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
x.0.remove(&key);
|
x.0.remove(&key);
|
||||||
}
|
}
|
||||||
|
|
||||||
let def_block = mem::take(x.1.deref_mut()).into_vec();
|
let def_block = mem::take(x.1.deref_mut());
|
||||||
*x.1 = optimize_stmt_block(def_block, state, preserve_result, true, false).into();
|
*x.1 = optimize_stmt_block(def_block, state, preserve_result, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// while false { block } -> Noop
|
// while false { block } -> Noop
|
||||||
@ -586,9 +584,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
if let Expr::BoolConstant(true, pos) = condition {
|
if let Expr::BoolConstant(true, pos) = condition {
|
||||||
*condition = Expr::Unit(*pos);
|
*condition = Expr::Unit(*pos);
|
||||||
}
|
}
|
||||||
let block = mem::take(body.as_mut().deref_mut()).into_vec();
|
let block = mem::take(body.as_mut().deref_mut());
|
||||||
*body.as_mut().deref_mut() =
|
*body.as_mut().deref_mut() = optimize_stmt_block(block, state, false, true, false);
|
||||||
optimize_stmt_block(block, state, false, true, false).into();
|
|
||||||
|
|
||||||
if body.len() == 1 {
|
if body.len() == 1 {
|
||||||
match body[0] {
|
match body[0] {
|
||||||
@ -616,7 +613,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
{
|
{
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
let block_pos = body.position();
|
let block_pos = body.position();
|
||||||
let block = mem::take(body.as_mut().deref_mut()).into_vec();
|
let block = mem::take(body.as_mut().deref_mut());
|
||||||
*stmt = Stmt::Block(
|
*stmt = Stmt::Block(
|
||||||
optimize_stmt_block(block, state, false, true, false).into_boxed_slice(),
|
optimize_stmt_block(block, state, false, true, false).into_boxed_slice(),
|
||||||
block_pos,
|
block_pos,
|
||||||
@ -625,15 +622,14 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// do { block } while|until expr
|
// do { block } while|until expr
|
||||||
Stmt::Do(body, condition, _, _) => {
|
Stmt::Do(body, condition, _, _) => {
|
||||||
optimize_expr(condition, state, false);
|
optimize_expr(condition, state, false);
|
||||||
let block = mem::take(body.as_mut().deref_mut()).into_vec();
|
let block = mem::take(body.as_mut().deref_mut());
|
||||||
*body.as_mut().deref_mut() =
|
*body.as_mut().deref_mut() = optimize_stmt_block(block, state, false, true, false);
|
||||||
optimize_stmt_block(block, state, false, true, false).into();
|
|
||||||
}
|
}
|
||||||
// for id in expr { block }
|
// for id in expr { block }
|
||||||
Stmt::For(iterable, x, _) => {
|
Stmt::For(iterable, x, _) => {
|
||||||
optimize_expr(iterable, state, false);
|
optimize_expr(iterable, state, false);
|
||||||
let body = mem::take(x.2.deref_mut()).into_vec();
|
let body = mem::take(x.2.deref_mut());
|
||||||
*x.2 = optimize_stmt_block(body, state, false, true, false).into();
|
*x.2 = optimize_stmt_block(body, state, false, true, false);
|
||||||
}
|
}
|
||||||
// let id = expr;
|
// let id = expr;
|
||||||
Stmt::Var(expr, _, options, _) if !options.contains(AST_OPTION_CONSTANT) => {
|
Stmt::Var(expr, _, options, _) if !options.contains(AST_OPTION_CONSTANT) => {
|
||||||
@ -644,7 +640,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
Stmt::Import(expr, _, _) => optimize_expr(expr, state, false),
|
Stmt::Import(expr, _, _) => optimize_expr(expr, state, false),
|
||||||
// { block }
|
// { block }
|
||||||
Stmt::Block(statements, pos) => {
|
Stmt::Block(statements, pos) => {
|
||||||
let statements = mem::take(statements).into_vec();
|
let statements = mem::take(statements).into_vec().into();
|
||||||
let mut block = optimize_stmt_block(statements, state, preserve_result, true, false);
|
let mut block = optimize_stmt_block(statements, state, preserve_result, true, false);
|
||||||
|
|
||||||
match block.as_mut_slice() {
|
match block.as_mut_slice() {
|
||||||
@ -665,7 +661,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// If try block is pure, there will never be any exceptions
|
// If try block is pure, there will never be any exceptions
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
let try_pos = x.0.position();
|
let try_pos = x.0.position();
|
||||||
let try_block = mem::take(&mut *x.0).into_vec();
|
let try_block = mem::take(&mut *x.0);
|
||||||
*stmt = Stmt::Block(
|
*stmt = Stmt::Block(
|
||||||
optimize_stmt_block(try_block, state, false, true, false).into_boxed_slice(),
|
optimize_stmt_block(try_block, state, false, true, false).into_boxed_slice(),
|
||||||
try_pos,
|
try_pos,
|
||||||
@ -673,10 +669,10 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
}
|
}
|
||||||
// try { try_block } catch ( var ) { catch_block }
|
// try { try_block } catch ( var ) { catch_block }
|
||||||
Stmt::TryCatch(x, _) => {
|
Stmt::TryCatch(x, _) => {
|
||||||
let try_block = mem::take(x.0.deref_mut()).into_vec();
|
let try_block = mem::take(x.0.deref_mut());
|
||||||
*x.0 = optimize_stmt_block(try_block, state, false, true, false).into();
|
*x.0 = optimize_stmt_block(try_block, state, false, true, false);
|
||||||
let catch_block = mem::take(x.2.deref_mut()).into_vec();
|
let catch_block = mem::take(x.2.deref_mut());
|
||||||
*x.2 = optimize_stmt_block(catch_block, state, false, true, false).into();
|
*x.2 = optimize_stmt_block(catch_block, state, false, true, false);
|
||||||
}
|
}
|
||||||
// func(...)
|
// func(...)
|
||||||
Stmt::Expr(expr @ Expr::FnCall(_, _)) => {
|
Stmt::Expr(expr @ Expr::FnCall(_, _)) => {
|
||||||
@ -726,7 +722,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
|
|||||||
// { stmt; ... } - do not count promotion as dirty because it gets turned back into an array
|
// { stmt; ... } - do not count promotion as dirty because it gets turned back into an array
|
||||||
Expr::Stmt(x) => {
|
Expr::Stmt(x) => {
|
||||||
*x.as_mut().deref_mut() =
|
*x.as_mut().deref_mut() =
|
||||||
optimize_stmt_block(mem::take(x.as_mut().deref_mut()).into_vec(), state, true, true, false).into();
|
optimize_stmt_block(mem::take(x.as_mut().deref_mut()), state, true, true, false);
|
||||||
|
|
||||||
// { Stmt(Expr) } - promote
|
// { Stmt(Expr) } - promote
|
||||||
match x.as_mut().as_mut() {
|
match x.as_mut().as_mut() {
|
||||||
@ -1091,12 +1087,12 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
|
|||||||
|
|
||||||
/// Optimize a block of [statements][Stmt] at top level.
|
/// Optimize a block of [statements][Stmt] at top level.
|
||||||
fn optimize_top_level(
|
fn optimize_top_level(
|
||||||
statements: Vec<Stmt>,
|
statements: StaticVec<Stmt>,
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
lib: &[&Module],
|
lib: &[&Module],
|
||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
) -> Vec<Stmt> {
|
) -> StaticVec<Stmt> {
|
||||||
let mut statements = statements;
|
let mut statements = statements;
|
||||||
|
|
||||||
// If optimization level is None then skip optimizing
|
// If optimization level is None then skip optimizing
|
||||||
@ -1125,8 +1121,8 @@ fn optimize_top_level(
|
|||||||
pub fn optimize_into_ast(
|
pub fn optimize_into_ast(
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
statements: Vec<Stmt>,
|
statements: StaticVec<Stmt>,
|
||||||
functions: Vec<crate::Shared<crate::ast::ScriptFnDef>>,
|
functions: StaticVec<crate::Shared<crate::ast::ScriptFnDef>>,
|
||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
) -> AST {
|
) -> AST {
|
||||||
let level = if cfg!(feature = "no_optimize") {
|
let level = if cfg!(feature = "no_optimize") {
|
||||||
@ -1176,9 +1172,9 @@ pub fn optimize_into_ast(
|
|||||||
// Optimize the function body
|
// Optimize the function body
|
||||||
let state = &mut OptimizerState::new(engine, lib2, level);
|
let state = &mut OptimizerState::new(engine, lib2, level);
|
||||||
|
|
||||||
let body = mem::take(fn_def.body.deref_mut()).into_vec();
|
let body = mem::take(fn_def.body.deref_mut());
|
||||||
|
|
||||||
*fn_def.body = optimize_stmt_block(body, state, true, true, true).into();
|
*fn_def.body = optimize_stmt_block(body, state, true, true, true);
|
||||||
|
|
||||||
fn_def
|
fn_def
|
||||||
})
|
})
|
||||||
|
15
src/parse.rs
15
src/parse.rs
@ -3244,11 +3244,18 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = vec![Stmt::Expr(expr)];
|
let mut statements = StaticVec::new();
|
||||||
|
statements.push(Stmt::Expr(expr));
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
// Optimize AST
|
// Optimize AST
|
||||||
optimize_into_ast(self, scope, expr, Default::default(), optimization_level),
|
optimize_into_ast(
|
||||||
|
self,
|
||||||
|
scope,
|
||||||
|
statements,
|
||||||
|
Default::default(),
|
||||||
|
optimization_level,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3257,8 +3264,8 @@ impl Engine {
|
|||||||
&self,
|
&self,
|
||||||
input: &mut TokenStream,
|
input: &mut TokenStream,
|
||||||
state: &mut ParseState,
|
state: &mut ParseState,
|
||||||
) -> Result<(Vec<Stmt>, Vec<Shared<ScriptFnDef>>), ParseError> {
|
) -> Result<(StaticVec<Stmt>, StaticVec<Shared<ScriptFnDef>>), ParseError> {
|
||||||
let mut statements = Vec::with_capacity(16);
|
let mut statements = StaticVec::new();
|
||||||
let mut functions = BTreeMap::new();
|
let mut functions = BTreeMap::new();
|
||||||
|
|
||||||
while !input.peek().expect(NEVER_ENDS).0.is_eof() {
|
while !input.peek().expect(NEVER_ENDS).0.is_eof() {
|
||||||
|
Loading…
Reference in New Issue
Block a user