From a049f7b5ba9a06d338a90653ce3ad9ef41edada9 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 30 Mar 2021 23:55:29 +0800 Subject: [PATCH] Optimize data structures. --- src/ast.rs | 18 +++++++++++------- src/engine.rs | 14 ++++++++------ src/optimize.rs | 4 ++-- src/parser.rs | 43 +++++++++++++++++++++++++------------------ 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index ca012df1..408db58e 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -864,19 +864,23 @@ pub enum Stmt { /// `if` expr `{` stmt `}` `else` `{` stmt `}` If(Expr, Box<(StmtBlock, StmtBlock)>, Position), /// `switch` expr `{` literal or _ `=>` stmt `,` ... `}` - Switch(Expr, Box<(BTreeMap, StmtBlock)>, Position), + Switch( + Expr, + Box<(BTreeMap>, StmtBlock)>, + Position, + ), /// `while` expr `{` stmt `}` While(Expr, Box, Position), /// `do` `{` stmt `}` `while`|`until` expr Do(Box, Expr, bool, Position), /// `for` id `in` expr `{` stmt `}` - For(Expr, Box<(Identifier, StmtBlock)>, Position), + For(Expr, Box<(Ident, StmtBlock)>, Position), /// \[`export`\] `let` id `=` expr Let(Expr, Box, bool, Position), /// \[`export`\] `const` id `=` expr Const(Expr, Box, bool, Position), /// expr op`=` expr - Assignment(Box<(Expr, Expr, Option)>, Position), + Assignment(Box<(Expr, Option, Expr)>, Position), /// `{` stmt`;` ... `}` Block(Vec, Position), /// `try` `{` stmt; ... `}` `catch` `(` var `)` `{` stmt; ... `}` @@ -901,7 +905,7 @@ pub enum Stmt { Export(Vec<(Ident, Option)>, Position), /// Convert a variable to shared. #[cfg(not(feature = "no_closure"))] - Share(Box), + Share(Identifier), } impl Default for Stmt { @@ -967,7 +971,7 @@ impl Stmt { Self::Export(_, pos) => *pos, #[cfg(not(feature = "no_closure"))] - Self::Share(x) => x.pos, + Self::Share(_) => Position::NONE, } } /// Override the [position][Position] of this statement. @@ -998,7 +1002,7 @@ impl Stmt { Self::Export(_, pos) => *pos = new_pos, #[cfg(not(feature = "no_closure"))] - Self::Share(x) => x.pos = new_pos, + Self::Share(_) => (), } self @@ -1203,7 +1207,7 @@ impl Stmt { if !x.0.walk(path, on_node) { return false; } - if !x.1.walk(path, on_node) { + if !x.2.walk(path, on_node) { return false; } } diff --git a/src/engine.rs b/src/engine.rs index 16f32037..05c64223 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1957,7 +1957,7 @@ impl Engine { // var op= rhs Stmt::Assignment(x, op_pos) if x.0.get_variable_access(false).is_some() => { - let (lhs_expr, rhs_expr, op_info) = x.as_ref(); + let (lhs_expr, op_info, rhs_expr) = x.as_ref(); let rhs_val = self .eval_expr(scope, mods, state, lib, this_ptr, rhs_expr, level)? .flatten(); @@ -1998,7 +1998,7 @@ impl Engine { // lhs op= rhs Stmt::Assignment(x, op_pos) => { - let (lhs_expr, rhs_expr, op_info) = x.as_ref(); + let (lhs_expr, op_info, rhs_expr) = x.as_ref(); let rhs_val = self .eval_expr(scope, mods, state, lib, this_ptr, rhs_expr, level)? .flatten(); @@ -2083,7 +2083,9 @@ impl Engine { value.hash(hasher); let hash = hasher.finish(); - table.get(&hash).map(|StmtBlock { statements, .. }| { + table.get(&hash).map(|t| { + let statements = &t.statements; + if !statements.is_empty() { self.eval_stmt_block( scope, mods, state, lib, this_ptr, statements, true, level, @@ -2178,7 +2180,7 @@ impl Engine { // For loop Stmt::For(expr, x, _) => { - let (name, StmtBlock { statements, pos }) = x.as_ref(); + let (Ident { name, .. }, StmtBlock { statements, pos }) = x.as_ref(); let iter_obj = self .eval_expr(scope, mods, state, lib, this_ptr, expr, level)? .flatten(); @@ -2479,8 +2481,8 @@ impl Engine { // Share statement #[cfg(not(feature = "no_closure"))] - Stmt::Share(x) => { - if let Some((index, _)) = scope.get_index(&x.name) { + Stmt::Share(name) => { + if let Some((index, _)) = scope.get_index(name) { let val = scope.get_mut_by_index(index); if !val.is_shared() { diff --git a/src/optimize.rs b/src/optimize.rs index e4b62c26..ae0f5dce 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -385,10 +385,10 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) { match stmt { // expr op= expr Stmt::Assignment(x, _) => match x.0 { - Expr::Variable(_) => optimize_expr(&mut x.1, state), + Expr::Variable(_) => optimize_expr(&mut x.2, state), _ => { optimize_expr(&mut x.0, state); - optimize_expr(&mut x.1, state); + optimize_expr(&mut x.2, state); } }, diff --git a/src/parser.rs b/src/parser.rs index 4460539d..0925cc38 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -813,7 +813,7 @@ fn parse_switch( } } - let mut table = BTreeMap::::new(); + let mut table = BTreeMap::>::new(); let mut def_stmt = None; loop { @@ -873,7 +873,7 @@ fn parse_switch( let need_comma = !stmt.is_self_terminated(); def_stmt = if let Some(hash) = hash { - table.insert(hash, stmt.into()); + table.insert(hash, Box::new(stmt.into())); None } else { Some(stmt.into()) @@ -1390,14 +1390,14 @@ fn make_assignment_stmt<'a>( } // var (non-indexed) = rhs Expr::Variable(x) if x.0.is_none() => { - Ok(Stmt::Assignment(Box::new((lhs, rhs, op_info)), op_pos)) + Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos)) } // var (indexed) = rhs Expr::Variable(x) => { let (index, _, Ident { name, pos, .. }) = x.as_ref(); match state.stack[(state.stack.len() - index.unwrap().get())].1 { AccessMode::ReadWrite => { - Ok(Stmt::Assignment(Box::new((lhs, rhs, op_info)), op_pos)) + Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos)) } // Constant values cannot be assigned to AccessMode::ReadOnly => { @@ -1411,14 +1411,14 @@ fn make_assignment_stmt<'a>( Position::NONE => match &x.lhs { // var[???] (non-indexed) = rhs, var.??? (non-indexed) = rhs Expr::Variable(x) if x.0.is_none() => { - Ok(Stmt::Assignment(Box::new((lhs, rhs, op_info)), op_pos)) + Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos)) } // var[???] (indexed) = rhs, var.??? (indexed) = rhs Expr::Variable(x) => { let (index, _, Ident { name, pos, .. }) = x.as_ref(); match state.stack[(state.stack.len() - index.unwrap().get())].1 { AccessMode::ReadWrite => { - Ok(Stmt::Assignment(Box::new((lhs, rhs, op_info)), op_pos)) + Ok(Stmt::Assignment(Box::new((lhs, op_info, rhs)), op_pos)) } // Constant values cannot be assigned to AccessMode::ReadOnly => { @@ -2091,9 +2091,9 @@ fn parse_for( settings.pos = eat_token(input, Token::For); // for name ... - let name = match input.next().unwrap() { + let (name, name_pos) = match input.next().unwrap() { // Variable name - (Token::Identifier(s), _) => s, + (Token::Identifier(s), pos) => (s, pos), // Reserved keyword (Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => { return Err(PERR::Reserved(s).into_err(pos)); @@ -2131,7 +2131,13 @@ fn parse_for( Ok(Stmt::For( expr, - Box::new((loop_var, body.into())), + Box::new(( + Ident { + name: loop_var, + pos: name_pos, + }, + body.into(), + )), settings.pos, )) } @@ -2766,7 +2772,7 @@ fn parse_fn( fn make_curry_from_externals( state: &mut ParseState, fn_expr: Expr, - externals: StaticVec, + externals: StaticVec, pos: Position, ) -> Expr { // If there are no captured variables, no need to curry @@ -2780,7 +2786,11 @@ fn make_curry_from_externals( args.push(fn_expr); externals.iter().for_each(|x| { - args.push(Expr::Variable(Box::new((None, None, x.clone())))); + let var_def = Ident { + name: x.clone(), + pos: Position::NONE, + }; + args.push(Expr::Variable(Box::new((None, None, var_def)))); }); let expr = Expr::FnCall( @@ -2800,7 +2810,7 @@ fn make_curry_from_externals( // Convert the entire expression into a statement block, then insert the relevant // [`Share`][Stmt::Share] statements. let mut statements: StaticVec<_> = Default::default(); - statements.extend(externals.into_iter().map(|v| Stmt::Share(Box::new(v)))); + statements.extend(externals.into_iter().map(Stmt::Share)); statements.push(Stmt::Expr(expr)); Expr::Stmt(Box::new(StmtBlock { statements, pos })) } @@ -2863,16 +2873,13 @@ fn parse_anon_fn( // External variables may need to be processed in a consistent order, // so extract them into a list. - let externals: StaticVec = { + let externals: StaticVec = { #[cfg(not(feature = "no_closure"))] { state .external_vars .iter() - .map(|(name, &pos)| Ident { - name: name.clone(), - pos, - }) + .map(|(name, _)| name.clone()) .collect() } #[cfg(feature = "no_closure")] @@ -2882,7 +2889,7 @@ fn parse_anon_fn( let params: StaticVec<_> = if cfg!(not(feature = "no_closure")) { externals .iter() - .map(|k| k.name.clone()) + .cloned() .chain(params.into_iter().map(|(v, _)| v)) .collect() } else {