Pack Stmt tighter.

This commit is contained in:
Stephen Chung 2020-10-27 19:23:43 +08:00
parent 93b5df6b3c
commit f62f7908ab
3 changed files with 68 additions and 69 deletions

View File

@ -1830,19 +1830,21 @@ impl Engine {
} }
// If-else statement // If-else statement
Stmt::IfThenElse(expr, if_block, else_block, _) => self Stmt::IfThenElse(expr, x, _) => {
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)? let (if_block, else_block) = x.as_ref();
.as_bool() self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position())) .as_bool()
.and_then(|guard_val| { .map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position()))
if guard_val { .and_then(|guard_val| {
self.eval_stmt(scope, mods, state, lib, this_ptr, if_block, level) if guard_val {
} else if let Some(stmt) = else_block { self.eval_stmt(scope, mods, state, lib, this_ptr, if_block, level)
self.eval_stmt(scope, mods, state, lib, this_ptr, stmt, level) } else if let Some(stmt) = else_block {
} else { self.eval_stmt(scope, mods, state, lib, this_ptr, stmt, level)
Ok(Default::default()) } else {
} Ok(Default::default())
}), }
})
}
// While loop // While loop
Stmt::While(expr, body, _) => loop { Stmt::While(expr, body, _) => loop {
@ -1880,7 +1882,8 @@ impl Engine {
}, },
// For loop // 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_obj = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
let iter_type = iter_obj.type_id(); let iter_type = iter_obj.type_id();
@ -2043,9 +2046,9 @@ impl Engine {
if let Some(resolver) = &self.module_resolver { if let Some(resolver) = &self.module_resolver {
let mut module = resolver.resolve(self, &path, expr.position())?; 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(); module.index_all_sub_modules();
mods.push((name.clone(), module)); mods.push((name_def.0.clone(), module));
} }
state.modules += 1; state.modules += 1;

View File

@ -164,16 +164,14 @@ fn call_fn_with_constant_arguments(
fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt { fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt {
match stmt { match stmt {
// if false { if_block } -> Noop // 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(); state.set_dirty();
Stmt::Noop(pos) Stmt::Noop(pos)
} }
// if true { if_block } -> if_block // 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 } // if expr { Noop }
Stmt::IfThenElse(condition, if_block, None, _) Stmt::IfThenElse(condition, x, _) if x.1.is_none() && matches!(x.0, Stmt::Noop(_)) => {
if matches!(if_block.as_ref(), Stmt::Noop(_)) =>
{
state.set_dirty(); state.set_dirty();
let pos = condition.position(); let pos = condition.position();
@ -183,7 +181,7 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt {
// -> { expr, Noop } // -> { expr, Noop }
let mut statements = Vec::new(); let mut statements = Vec::new();
statements.push(Stmt::Expr(expr)); statements.push(Stmt::Expr(expr));
statements.push(*if_block); statements.push(x.0);
Stmt::Block(statements, pos) Stmt::Block(statements, pos)
} else { } else {
@ -192,26 +190,27 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt {
} }
} }
// if expr { if_block } // 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), optimize_expr(condition, state),
Box::new(optimize_stmt(*if_block, state, true)), Box::new((optimize_stmt(x.0, state, true), None)),
None,
pos, pos,
), ),
// if false { if_block } else { else_block } -> else_block // if false { if_block } else { else_block } -> else_block
Stmt::IfThenElse(Expr::False(_), _, Some(else_block), _) => { Stmt::IfThenElse(Expr::False(_), x, _) if x.1.is_some() => {
optimize_stmt(*else_block, state, true) optimize_stmt(x.1.unwrap(), state, true)
} }
// if true { if_block } else { else_block } -> if_block // 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 } // 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), optimize_expr(condition, state),
Box::new(optimize_stmt(*if_block, state, true)), Box::new((
match optimize_stmt(*else_block, state, true) { optimize_stmt(x.0, state, true),
Stmt::Noop(_) => None, // Noop -> no else block match optimize_stmt(x.1.unwrap(), state, true) {
stmt => Some(Box::new(stmt)), Stmt::Noop(_) => None, // Noop -> no else block
}, stmt => Some(stmt),
},
)),
pos, pos,
), ),
@ -254,12 +253,14 @@ fn optimize_stmt(stmt: Stmt, state: &mut State, preserve_result: bool) -> Stmt {
stmt => Stmt::Loop(Box::new(stmt), pos), stmt => Stmt::Loop(Box::new(stmt), pos),
}, },
// for id in expr { block } // for id in expr { block }
Stmt::For(var_name, iterable, block, pos) => Stmt::For( Stmt::For(iterable, x, pos) => {
var_name, let (var_name, block) = *x;
optimize_expr(iterable, state), Stmt::For(
Box::new(optimize_stmt(*block, state, false)), optimize_expr(iterable, state),
pos, Box::new((var_name, optimize_stmt(block, state, false))),
), pos,
)
}
// let id = expr; // let id = expr;
Stmt::Let(name, Some(expr), pos) => Stmt::Let(name, Some(optimize_expr(expr, state)), pos), Stmt::Let(name, Some(expr), pos) => Stmt::Let(name, Some(optimize_expr(expr, state)), pos),
// let id; // let id;

View File

@ -742,13 +742,13 @@ pub enum Stmt {
/// No-op. /// No-op.
Noop(Position), Noop(Position),
/// if expr { stmt } else { stmt } /// if expr { stmt } else { stmt }
IfThenElse(Expr, Box<Stmt>, Option<Box<Stmt>>, Position), IfThenElse(Expr, Box<(Stmt, Option<Stmt>)>, Position),
/// while expr { stmt } /// while expr { stmt }
While(Expr, Box<Stmt>, Position), While(Expr, Box<Stmt>, Position),
/// loop { stmt } /// loop { stmt }
Loop(Box<Stmt>, Position), Loop(Box<Stmt>, Position),
/// for id in expr { stmt } /// for id in expr { stmt }
For(Box<String>, Expr, Box<Stmt>, Position), For(Expr, Box<(String, Stmt)>, Position),
/// let id = expr /// let id = expr
Let(Box<(String, Position)>, Option<Expr>, Position), Let(Box<(String, Position)>, Option<Expr>, Position),
/// const id = expr /// const id = expr
@ -773,7 +773,7 @@ pub enum Stmt {
ReturnWithVal((ReturnType, Position), Option<Expr>, Position), ReturnWithVal((ReturnType, Position), Option<Expr>, Position),
/// import expr as var /// import expr as var
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Import(Expr, Option<(ImmutableString, Position)>, Position), Import(Expr, Option<Box<(ImmutableString, Position)>>, Position),
/// export var as var, ... /// export var as var, ...
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Export( Export(
@ -808,10 +808,10 @@ impl Stmt {
| Self::Continue(pos) | Self::Continue(pos)
| Self::Break(pos) | Self::Break(pos)
| Self::Block(_, pos) | Self::Block(_, pos)
| Self::IfThenElse(_, _, _, pos) | Self::IfThenElse(_, _, pos)
| Self::While(_, _, pos) | Self::While(_, _, pos)
| Self::Loop(_, pos) | Self::Loop(_, pos)
| Self::For(_, _, _, pos) | Self::For(_, _, pos)
| Self::ReturnWithVal((_, pos), _, _) => *pos, | Self::ReturnWithVal((_, pos), _, _) => *pos,
Self::Let(x, _, _) | Self::Const(x, _, _) => x.1, Self::Let(x, _, _) | Self::Const(x, _, _) => x.1,
@ -836,10 +836,10 @@ impl Stmt {
| Self::Continue(pos) | Self::Continue(pos)
| Self::Break(pos) | Self::Break(pos)
| Self::Block(_, pos) | Self::Block(_, pos)
| Self::IfThenElse(_, _, _, pos) | Self::IfThenElse(_, _, pos)
| Self::While(_, _, pos) | Self::While(_, _, pos)
| Self::Loop(_, pos) | Self::Loop(_, pos)
| Self::For(_, _, _, pos) | Self::For(_, _, pos)
| Self::ReturnWithVal((_, pos), _, _) => *pos = new_pos, | Self::ReturnWithVal((_, pos), _, _) => *pos = new_pos,
Self::Let(x, _, _) | Self::Const(x, _, _) => x.1 = 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)? /// Is this statement self-terminated (i.e. no need for a semicolon terminator)?
pub fn is_self_terminated(&self) -> bool { pub fn is_self_terminated(&self) -> bool {
match self { match self {
Self::IfThenElse(_, _, _, _) Self::IfThenElse(_, _, _)
| Self::While(_, _, _) | Self::While(_, _, _)
| Self::Loop(_, _) | Self::Loop(_, _)
| Self::For(_, _, _, _) | Self::For(_, _, _)
| Self::Block(_, _) | Self::Block(_, _)
| Self::TryCatch(_) => true, | Self::TryCatch(_) => true,
@ -894,15 +894,13 @@ impl Stmt {
match self { match self {
Self::Noop(_) => true, Self::Noop(_) => true,
Self::Expr(expr) => expr.is_pure(), Self::Expr(expr) => expr.is_pure(),
Self::IfThenElse(condition, if_block, Some(else_block), _) => { Self::IfThenElse(condition, x, _) if x.1.is_some() => {
condition.is_pure() && if_block.is_pure() && else_block.is_pure() condition.is_pure() && x.0.is_pure() && x.1.as_ref().unwrap().is_pure()
}
Self::IfThenElse(condition, if_block, None, _) => {
condition.is_pure() && if_block.is_pure()
} }
Self::IfThenElse(condition, x, _) => condition.is_pure() && x.0.is_pure(),
Self::While(condition, block, _) => condition.is_pure() && block.is_pure(), Self::While(condition, block, _) => condition.is_pure() && block.is_pure(),
Self::Loop(block, _) => 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::Let(_, _, _) | Self::Const(_, _, _) => 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::ReturnWithVal(_, _, _) => false, Self::Continue(_) | Self::Break(_) | Self::ReturnWithVal(_, _, _) => false,
@ -2865,22 +2863,26 @@ fn parse_if(
ensure_not_statement_expr(input, "a boolean")?; ensure_not_statement_expr(input, "a boolean")?;
let guard = parse_expr(input, state, lib, settings.level_up())?; let guard = parse_expr(input, state, lib, settings.level_up())?;
ensure_not_assignment(input)?; 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 ... // if guard { if_body } else ...
let else_body = if match_token(input, Token::Else).0 { 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 ... // if guard { if_body } else if ...
parse_if(input, state, lib, settings.level_up())? parse_if(input, state, lib, settings.level_up())?
} else { } else {
// if guard { if_body } else { else-body } // if guard { if_body } else { else-body }
parse_block(input, state, lib, settings.level_up())? parse_block(input, state, lib, settings.level_up())?
})) })
} else { } else {
None 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. /// Parse a while loop.
@ -2977,11 +2979,11 @@ fn parse_for(
state.stack.push((name.clone(), ScopeEntryType::Normal)); state.stack.push((name.clone(), ScopeEntryType::Normal));
settings.is_breakable = true; 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); 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. /// Parse a variable definition statement.
@ -3068,7 +3070,7 @@ fn parse_import(
Ok(Stmt::Import( Ok(Stmt::Import(
expr, expr,
Some((name.into(), settings.pos)), Some(Box::new((name.into(), settings.pos))),
token_pos, token_pos,
)) ))
} }
@ -3932,10 +3934,3 @@ pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
_ => None, _ => None,
} }
} }
#[test]
fn test() {
println!("{}", std::mem::size_of::<Position>());
println!("{}", std::mem::size_of::<Expr>());
println!("{}", std::mem::size_of::<Stmt>());
}