From f62f7908ab3bd9d4e892b08eeb4793221441e62f Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 27 Oct 2020 19:23:43 +0800 Subject: [PATCH] Pack Stmt tighter. --- src/engine.rs | 35 +++++++++++++++++--------------- src/optimize.rs | 49 +++++++++++++++++++++++---------------------- src/parser.rs | 53 ++++++++++++++++++++++--------------------------- 3 files changed, 68 insertions(+), 69 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index fdc1a71a..401edc2e 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1830,19 +1830,21 @@ impl Engine { } // If-else statement - Stmt::IfThenElse(expr, if_block, else_block, _) => self - .eval_expr(scope, mods, state, lib, this_ptr, expr, level)? - .as_bool() - .map_err(|err| self.make_type_mismatch_err::(err, expr.position())) - .and_then(|guard_val| { - if guard_val { - self.eval_stmt(scope, mods, state, lib, this_ptr, if_block, level) - } else if let Some(stmt) = else_block { - self.eval_stmt(scope, mods, state, lib, this_ptr, stmt, level) - } else { - Ok(Default::default()) - } - }), + Stmt::IfThenElse(expr, x, _) => { + let (if_block, else_block) = x.as_ref(); + self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)? + .as_bool() + .map_err(|err| self.make_type_mismatch_err::(err, expr.position())) + .and_then(|guard_val| { + if guard_val { + self.eval_stmt(scope, mods, state, lib, this_ptr, if_block, level) + } else if let Some(stmt) = else_block { + self.eval_stmt(scope, mods, state, lib, this_ptr, stmt, level) + } else { + Ok(Default::default()) + } + }) + } // While loop Stmt::While(expr, body, _) => loop { @@ -1880,7 +1882,8 @@ impl Engine { }, // For loop - Stmt::For(name, expr, stmt, _) => { + Stmt::For(expr, x, _) => { + let (name, stmt) = x.as_ref(); let iter_obj = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?; let iter_type = iter_obj.type_id(); @@ -2043,9 +2046,9 @@ impl Engine { if let Some(resolver) = &self.module_resolver { let mut module = resolver.resolve(self, &path, expr.position())?; - if let Some((name, _)) = alias { + if let Some(name_def) = alias { module.index_all_sub_modules(); - mods.push((name.clone(), module)); + mods.push((name_def.0.clone(), module)); } state.modules += 1; diff --git a/src/optimize.rs b/src/optimize.rs index 9584277f..9672fc7f 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -164,16 +164,14 @@ fn call_fn_with_constant_arguments( fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt { match stmt { // if false { if_block } -> Noop - Stmt::IfThenElse(Expr::False(pos), _, None, _) => { + Stmt::IfThenElse(Expr::False(pos), x, _) if x.1.is_none() => { state.set_dirty(); Stmt::Noop(pos) } // if true { if_block } -> if_block - Stmt::IfThenElse(Expr::True(_), if_block, None, _) => optimize_stmt(*if_block, state, true), + Stmt::IfThenElse(Expr::True(_), x, _) if x.1.is_none() => optimize_stmt(x.0, state, true), // if expr { Noop } - Stmt::IfThenElse(condition, if_block, None, _) - if matches!(if_block.as_ref(), Stmt::Noop(_)) => - { + Stmt::IfThenElse(condition, x, _) if x.1.is_none() && matches!(x.0, Stmt::Noop(_)) => { state.set_dirty(); let pos = condition.position(); @@ -183,7 +181,7 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt { // -> { expr, Noop } let mut statements = Vec::new(); statements.push(Stmt::Expr(expr)); - statements.push(*if_block); + statements.push(x.0); Stmt::Block(statements, pos) } else { @@ -192,26 +190,27 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt { } } // if expr { if_block } - Stmt::IfThenElse(condition, if_block, None, pos) => Stmt::IfThenElse( + Stmt::IfThenElse(condition, x, pos) if x.1.is_none() => Stmt::IfThenElse( optimize_expr(condition, state), - Box::new(optimize_stmt(*if_block, state, true)), - None, + Box::new((optimize_stmt(x.0, state, true), None)), pos, ), // if false { if_block } else { else_block } -> else_block - Stmt::IfThenElse(Expr::False(_), _, Some(else_block), _) => { - optimize_stmt(*else_block, state, true) + Stmt::IfThenElse(Expr::False(_), x, _) if x.1.is_some() => { + optimize_stmt(x.1.unwrap(), state, true) } // if true { if_block } else { else_block } -> if_block - Stmt::IfThenElse(Expr::True(_), if_block, _, _) => optimize_stmt(*if_block, state, true), + Stmt::IfThenElse(Expr::True(_), x, _) => optimize_stmt(x.0, state, true), // if expr { if_block } else { else_block } - Stmt::IfThenElse(condition, if_block, Some(else_block), pos) => Stmt::IfThenElse( + Stmt::IfThenElse(condition, x, pos) => Stmt::IfThenElse( optimize_expr(condition, state), - Box::new(optimize_stmt(*if_block, state, true)), - match optimize_stmt(*else_block, state, true) { - Stmt::Noop(_) => None, // Noop -> no else block - stmt => Some(Box::new(stmt)), - }, + Box::new(( + optimize_stmt(x.0, state, true), + match optimize_stmt(x.1.unwrap(), state, true) { + Stmt::Noop(_) => None, // Noop -> no else block + stmt => Some(stmt), + }, + )), pos, ), @@ -254,12 +253,14 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt { stmt => Stmt::Loop(Box::new(stmt), pos), }, // for id in expr { block } - Stmt::For(var_name, iterable, block, pos) => Stmt::For( - var_name, - optimize_expr(iterable, state), - Box::new(optimize_stmt(*block, state, false)), - pos, - ), + Stmt::For(iterable, x, pos) => { + let (var_name, block) = *x; + Stmt::For( + optimize_expr(iterable, state), + Box::new((var_name, optimize_stmt(block, state, false))), + pos, + ) + } // let id = expr; Stmt::Let(name, Some(expr), pos) => Stmt::Let(name, Some(optimize_expr(expr, state)), pos), // let id; diff --git a/src/parser.rs b/src/parser.rs index 251cb799..7ac6ad02 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -742,13 +742,13 @@ pub enum Stmt { /// No-op. Noop(Position), /// if expr { stmt } else { stmt } - IfThenElse(Expr, Box, Option>, Position), + IfThenElse(Expr, Box<(Stmt, Option)>, Position), /// while expr { stmt } While(Expr, Box, Position), /// loop { stmt } Loop(Box, Position), /// for id in expr { stmt } - For(Box, Expr, Box, Position), + For(Expr, Box<(String, Stmt)>, Position), /// let id = expr Let(Box<(String, Position)>, Option, Position), /// const id = expr @@ -773,7 +773,7 @@ pub enum Stmt { ReturnWithVal((ReturnType, Position), Option, Position), /// import expr as var #[cfg(not(feature = "no_module"))] - Import(Expr, Option<(ImmutableString, Position)>, Position), + Import(Expr, Option>, Position), /// export var as var, ... #[cfg(not(feature = "no_module"))] Export( @@ -808,10 +808,10 @@ impl Stmt { | Self::Continue(pos) | Self::Break(pos) | Self::Block(_, pos) - | Self::IfThenElse(_, _, _, pos) + | Self::IfThenElse(_, _, pos) | Self::While(_, _, pos) | Self::Loop(_, pos) - | Self::For(_, _, _, pos) + | Self::For(_, _, pos) | Self::ReturnWithVal((_, pos), _, _) => *pos, Self::Let(x, _, _) | Self::Const(x, _, _) => x.1, @@ -836,10 +836,10 @@ impl Stmt { | Self::Continue(pos) | Self::Break(pos) | Self::Block(_, pos) - | Self::IfThenElse(_, _, _, pos) + | Self::IfThenElse(_, _, pos) | Self::While(_, _, pos) | Self::Loop(_, pos) - | Self::For(_, _, _, pos) + | Self::For(_, _, pos) | Self::ReturnWithVal((_, pos), _, _) => *pos = new_pos, Self::Let(x, _, _) | Self::Const(x, _, _) => x.1 = new_pos, @@ -864,10 +864,10 @@ impl Stmt { /// Is this statement self-terminated (i.e. no need for a semicolon terminator)? pub fn is_self_terminated(&self) -> bool { match self { - Self::IfThenElse(_, _, _, _) + Self::IfThenElse(_, _, _) | Self::While(_, _, _) | Self::Loop(_, _) - | Self::For(_, _, _, _) + | Self::For(_, _, _) | Self::Block(_, _) | Self::TryCatch(_) => true, @@ -894,15 +894,13 @@ impl Stmt { match self { Self::Noop(_) => true, Self::Expr(expr) => expr.is_pure(), - Self::IfThenElse(condition, if_block, Some(else_block), _) => { - condition.is_pure() && if_block.is_pure() && else_block.is_pure() - } - Self::IfThenElse(condition, if_block, None, _) => { - condition.is_pure() && if_block.is_pure() + Self::IfThenElse(condition, x, _) if x.1.is_some() => { + condition.is_pure() && x.0.is_pure() && x.1.as_ref().unwrap().is_pure() } + Self::IfThenElse(condition, x, _) => condition.is_pure() && x.0.is_pure(), Self::While(condition, block, _) => condition.is_pure() && block.is_pure(), Self::Loop(block, _) => block.is_pure(), - Self::For(_, iterable, block, _) => iterable.is_pure() && block.is_pure(), + Self::For(iterable, x, _) => iterable.is_pure() && x.1.is_pure(), Self::Let(_, _, _) | Self::Const(_, _, _) => false, Self::Block(block, _) => block.iter().all(|stmt| stmt.is_pure()), Self::Continue(_) | Self::Break(_) | Self::ReturnWithVal(_, _, _) => false, @@ -2865,22 +2863,26 @@ fn parse_if( ensure_not_statement_expr(input, "a boolean")?; let guard = parse_expr(input, state, lib, settings.level_up())?; ensure_not_assignment(input)?; - let if_body = Box::new(parse_block(input, state, lib, settings.level_up())?); + let if_body = parse_block(input, state, lib, settings.level_up())?; // if guard { if_body } else ... let else_body = if match_token(input, Token::Else).0 { - Some(Box::new(if let (Token::If, _) = input.peek().unwrap() { + Some(if let (Token::If, _) = input.peek().unwrap() { // if guard { if_body } else if ... parse_if(input, state, lib, settings.level_up())? } else { // if guard { if_body } else { else-body } parse_block(input, state, lib, settings.level_up())? - })) + }) } else { None }; - Ok(Stmt::IfThenElse(guard, if_body, else_body, token_pos)) + Ok(Stmt::IfThenElse( + guard, + Box::new((if_body, else_body)), + token_pos, + )) } /// Parse a while loop. @@ -2977,11 +2979,11 @@ fn parse_for( state.stack.push((name.clone(), ScopeEntryType::Normal)); settings.is_breakable = true; - let body = Box::new(parse_block(input, state, lib, settings.level_up())?); + let body = parse_block(input, state, lib, settings.level_up())?; state.stack.truncate(prev_stack_len); - Ok(Stmt::For(Box::new(name), expr, body, token_pos)) + Ok(Stmt::For(expr, Box::new((name, body)), token_pos)) } /// Parse a variable definition statement. @@ -3068,7 +3070,7 @@ fn parse_import( Ok(Stmt::Import( expr, - Some((name.into(), settings.pos)), + Some(Box::new((name.into(), settings.pos))), token_pos, )) } @@ -3932,10 +3934,3 @@ pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option { _ => None, } } - -#[test] -fn test() { - println!("{}", std::mem::size_of::()); - println!("{}", std::mem::size_of::()); - println!("{}", std::mem::size_of::()); -}