From c84f80d433ff256e70b878101a1b1fc716033402 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 12 Sep 2021 14:34:00 +0800 Subject: [PATCH] Use StaticVec for parsing. --- src/engine_api.rs | 6 ++-- src/optimize.rs | 80 ++++++++++++++++++++++------------------------- src/parse.rs | 15 ++++++--- 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/engine_api.rs b/src/engine_api.rs index 1e786638..2a83afd6 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -2040,7 +2040,7 @@ impl Engine { let lib = Default::default(); 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. /// Exported under the `metadata` feature only. @@ -2053,9 +2053,7 @@ impl Engine { #[inline] #[must_use] pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec { - let mut signatures = Vec::new(); - - signatures.extend(self.global_namespace().gen_fn_signatures()); + let mut signatures = self.global_namespace().gen_fn_signatures(); self.global_sub_modules.iter().for_each(|(name, m)| { signatures.extend(m.gen_fn_signatures().map(|f| format!("{}::{}", name, f))) diff --git a/src/optimize.rs b/src/optimize.rs index 6a8f2ff9..b8ef6106 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -51,7 +51,7 @@ struct OptimizerState<'a> { /// Has the [`AST`] been changed during this pass? changed: bool, /// Collection of constants to use for eager function evaluations. - variables: Vec<(String, AccessMode, Option)>, + variables: StaticVec<(String, AccessMode, Option)>, /// Activate constants propagation? propagate_constants: bool, /// An [`Engine`] instance for eager function evaluation. @@ -65,14 +65,14 @@ struct OptimizerState<'a> { impl<'a> OptimizerState<'a> { /// Create a new State. #[inline(always)] - pub const fn new( + pub fn new( engine: &'a Engine, lib: &'a [&'a Module], optimization_level: OptimizationLevel, ) -> Self { Self { changed: false, - variables: Vec::new(), + variables: StaticVec::new(), propagate_constants: true, engine, lib, @@ -158,12 +158,12 @@ impl<'a> OptimizerState<'a> { /// Optimize a block of [statements][Stmt]. fn optimize_stmt_block( - mut statements: Vec, + mut statements: StaticVec, state: &mut OptimizerState, preserve_result: bool, is_internal: bool, reduce_return: bool, -) -> Vec { +) -> StaticVec { if statements.is_empty() { 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 Stmt::If(Expr::BoolConstant(false, _), x, _) => { 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) { statements if statements.is_empty() => Stmt::Noop(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 Stmt::If(Expr::BoolConstant(true, _), x, _) => { 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) { statements if statements.is_empty() => Stmt::Noop(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 } Stmt::If(condition, x, _) => { optimize_expr(condition, state, false); - let if_block = mem::take(x.0.deref_mut()).into_vec(); - *x.0 = optimize_stmt_block(if_block, state, preserve_result, true, false).into(); - let else_block = mem::take(x.1.deref_mut()).into_vec(); - *x.1 = optimize_stmt_block(else_block, state, preserve_result, true, false).into(); + let if_block = mem::take(x.0.deref_mut()); + *x.0 = optimize_stmt_block(if_block, state, preserve_result, true, false); + let else_block = mem::take(x.1.deref_mut()); + *x.1 = optimize_stmt_block(else_block, state, preserve_result, true, false); } // 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 } 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_pos = if x.1.position().is_none() { *pos @@ -517,13 +517,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // Promote the matched case let new_pos = block.1.position(); let statements = mem::take(&mut *block.1); - let statements = - optimize_stmt_block(statements.into_vec(), state, true, true, false); + let statements = optimize_stmt_block(statements, state, true, true, false); *stmt = Stmt::Block(statements.into_boxed_slice(), new_pos); } } else { // 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_pos = if x.1.position().is_none() { *pos @@ -551,13 +550,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b block.0 = Some(condition); *block.1 = optimize_stmt_block( - mem::take(block.1.deref_mut()).into_vec(), + mem::take(block.1.deref_mut()), state, preserve_result, true, false, - ) - .into(); + ); } } }); @@ -571,8 +569,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b x.0.remove(&key); } - let def_block = mem::take(x.1.deref_mut()).into_vec(); - *x.1 = optimize_stmt_block(def_block, state, preserve_result, true, false).into(); + let def_block = mem::take(x.1.deref_mut()); + *x.1 = optimize_stmt_block(def_block, state, preserve_result, true, false); } // 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 { *condition = Expr::Unit(*pos); } - let block = mem::take(body.as_mut().deref_mut()).into_vec(); - *body.as_mut().deref_mut() = - optimize_stmt_block(block, state, false, true, false).into(); + let block = mem::take(body.as_mut().deref_mut()); + *body.as_mut().deref_mut() = optimize_stmt_block(block, state, false, true, false); if body.len() == 1 { match body[0] { @@ -616,7 +613,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b { state.set_dirty(); 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( optimize_stmt_block(block, state, false, true, false).into_boxed_slice(), block_pos, @@ -625,15 +622,14 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // do { block } while|until expr Stmt::Do(body, condition, _, _) => { optimize_expr(condition, state, false); - let block = mem::take(body.as_mut().deref_mut()).into_vec(); - *body.as_mut().deref_mut() = - optimize_stmt_block(block, state, false, true, false).into(); + let block = mem::take(body.as_mut().deref_mut()); + *body.as_mut().deref_mut() = optimize_stmt_block(block, state, false, true, false); } // for id in expr { block } Stmt::For(iterable, x, _) => { optimize_expr(iterable, state, false); - let body = mem::take(x.2.deref_mut()).into_vec(); - *x.2 = optimize_stmt_block(body, state, false, true, false).into(); + let body = mem::take(x.2.deref_mut()); + *x.2 = optimize_stmt_block(body, state, false, true, false); } // let id = expr; 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), // { block } 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); 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 state.set_dirty(); 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( optimize_stmt_block(try_block, state, false, true, false).into_boxed_slice(), 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 } Stmt::TryCatch(x, _) => { - let try_block = mem::take(x.0.deref_mut()).into_vec(); - *x.0 = optimize_stmt_block(try_block, state, false, true, false).into(); - let catch_block = mem::take(x.2.deref_mut()).into_vec(); - *x.2 = optimize_stmt_block(catch_block, state, false, true, false).into(); + let try_block = mem::take(x.0.deref_mut()); + *x.0 = optimize_stmt_block(try_block, state, false, true, false); + let catch_block = mem::take(x.2.deref_mut()); + *x.2 = optimize_stmt_block(catch_block, state, false, true, false); } // func(...) 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 Expr::Stmt(x) => { *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 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. fn optimize_top_level( - statements: Vec, + statements: StaticVec, engine: &Engine, scope: &Scope, lib: &[&Module], optimization_level: OptimizationLevel, -) -> Vec { +) -> StaticVec { let mut statements = statements; // If optimization level is None then skip optimizing @@ -1125,8 +1121,8 @@ fn optimize_top_level( pub fn optimize_into_ast( engine: &Engine, scope: &Scope, - statements: Vec, - functions: Vec>, + statements: StaticVec, + functions: StaticVec>, optimization_level: OptimizationLevel, ) -> AST { let level = if cfg!(feature = "no_optimize") { @@ -1176,9 +1172,9 @@ pub fn optimize_into_ast( // Optimize the function body 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 }) diff --git a/src/parse.rs b/src/parse.rs index 3dc45951..9507aabb 100644 --- a/src/parse.rs +++ b/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( // 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, input: &mut TokenStream, state: &mut ParseState, - ) -> Result<(Vec, Vec>), ParseError> { - let mut statements = Vec::with_capacity(16); + ) -> Result<(StaticVec, StaticVec>), ParseError> { + let mut statements = StaticVec::new(); let mut functions = BTreeMap::new(); while !input.peek().expect(NEVER_ENDS).0.is_eof() {