Streamline switch case AST structure.
This commit is contained in:
108
src/optimizer.rs
108
src/optimizer.rs
@@ -527,7 +527,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
let (
|
||||
match_expr,
|
||||
SwitchCasesCollection {
|
||||
case_blocks,
|
||||
expressions,
|
||||
cases,
|
||||
ranges,
|
||||
def_case,
|
||||
@@ -544,26 +544,23 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
match &case_blocks_list[..] {
|
||||
[] => (),
|
||||
[index] => {
|
||||
let mut b = mem::take(&mut case_blocks[*index]);
|
||||
let mut b = mem::take(&mut expressions[*index]);
|
||||
cases.clear();
|
||||
|
||||
if b.is_always_true() {
|
||||
// Promote the matched case
|
||||
let statements: StmtBlockContainer = mem::take(&mut b.statements);
|
||||
let statements =
|
||||
optimize_stmt_block(statements, state, true, true, false);
|
||||
*stmt = (statements, b.statements.span()).into();
|
||||
let mut statements = Stmt::Expr(mem::take(&mut b.expr).into());
|
||||
optimize_stmt(&mut statements, state, true);
|
||||
*stmt = statements;
|
||||
} else {
|
||||
// switch const { case if condition => stmt, _ => def } => if condition { stmt } else { def }
|
||||
optimize_expr(&mut b.condition, state, false);
|
||||
|
||||
let else_stmt = if let Some(index) = def_case {
|
||||
let def_case = &mut case_blocks[*index].statements;
|
||||
let def_span = def_case.span_or_else(*pos, Position::NONE);
|
||||
let def_case: StmtBlockContainer = mem::take(def_case);
|
||||
let def_stmt =
|
||||
optimize_stmt_block(def_case, state, true, true, false);
|
||||
StmtBlock::new_with_span(def_stmt, def_span)
|
||||
let mut def_stmt =
|
||||
Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
||||
optimize_stmt(&mut def_stmt, state, true);
|
||||
def_stmt.into()
|
||||
} else {
|
||||
StmtBlock::NONE
|
||||
};
|
||||
@@ -571,7 +568,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
*stmt = Stmt::If(
|
||||
(
|
||||
mem::take(&mut b.condition),
|
||||
mem::take(&mut b.statements),
|
||||
Stmt::Expr(mem::take(&mut b.expr).into()).into(),
|
||||
else_stmt,
|
||||
)
|
||||
.into(),
|
||||
@@ -584,14 +581,13 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
}
|
||||
_ => {
|
||||
for &index in case_blocks_list {
|
||||
let mut b = mem::take(&mut case_blocks[index]);
|
||||
let mut b = mem::take(&mut expressions[index]);
|
||||
|
||||
if b.is_always_true() {
|
||||
// Promote the matched case
|
||||
let statements: StmtBlockContainer = mem::take(&mut b.statements);
|
||||
let statements =
|
||||
optimize_stmt_block(statements, state, true, true, false);
|
||||
*stmt = (statements, b.statements.span()).into();
|
||||
let mut statements = Stmt::Expr(mem::take(&mut b.expr).into());
|
||||
optimize_stmt(&mut statements, state, true);
|
||||
*stmt = statements;
|
||||
state.set_dirty();
|
||||
return;
|
||||
}
|
||||
@@ -608,18 +604,17 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
if ranges.len() == 1
|
||||
|| ranges
|
||||
.iter()
|
||||
.all(|r| case_blocks[r.index()].is_always_true())
|
||||
.all(|r| expressions[r.index()].is_always_true())
|
||||
{
|
||||
for r in ranges.iter().filter(|r| r.contains(value)) {
|
||||
let range_block = &mut case_blocks[r.index()];
|
||||
let range_block = &mut expressions[r.index()];
|
||||
|
||||
if range_block.is_always_true() {
|
||||
// Promote the matched case
|
||||
let block = &mut case_blocks[r.index()];
|
||||
let statements = mem::take(&mut *block.statements);
|
||||
let statements =
|
||||
optimize_stmt_block(statements, state, true, true, false);
|
||||
*stmt = (statements, block.statements.span()).into();
|
||||
let block = &mut expressions[r.index()];
|
||||
let mut statements = Stmt::Expr(mem::take(&mut block.expr).into());
|
||||
optimize_stmt(&mut statements, state, true);
|
||||
*stmt = statements;
|
||||
} else {
|
||||
let mut condition = mem::take(&mut range_block.condition);
|
||||
|
||||
@@ -627,20 +622,20 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
optimize_expr(&mut condition, state, false);
|
||||
|
||||
let else_stmt = if let Some(index) = def_case {
|
||||
let def_case = &mut case_blocks[*index].statements;
|
||||
let def_span = def_case.span_or_else(*pos, Position::NONE);
|
||||
let def_case: StmtBlockContainer = mem::take(def_case);
|
||||
let def_stmt =
|
||||
optimize_stmt_block(def_case, state, true, true, false);
|
||||
StmtBlock::new_with_span(def_stmt, def_span)
|
||||
let mut def_stmt =
|
||||
Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
||||
optimize_stmt(&mut def_stmt, state, true);
|
||||
def_stmt.into()
|
||||
} else {
|
||||
StmtBlock::NONE
|
||||
};
|
||||
|
||||
let statements = mem::take(&mut case_blocks[r.index()].statements);
|
||||
let if_stmt =
|
||||
Stmt::Expr(mem::take(&mut expressions[r.index()].expr).into())
|
||||
.into();
|
||||
|
||||
*stmt = Stmt::If(
|
||||
(condition, statements, else_stmt).into(),
|
||||
(condition, if_stmt, else_stmt).into(),
|
||||
match_expr.start_position(),
|
||||
);
|
||||
}
|
||||
@@ -664,12 +659,9 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
}
|
||||
|
||||
for r in &*ranges {
|
||||
let b = &mut case_blocks[r.index()];
|
||||
let statements = mem::take(&mut *b.statements);
|
||||
*b.statements =
|
||||
optimize_stmt_block(statements, state, preserve_result, true, false);
|
||||
|
||||
let b = &mut expressions[r.index()];
|
||||
optimize_expr(&mut b.condition, state, false);
|
||||
optimize_expr(&mut b.expr, state, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -679,11 +671,9 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
state.set_dirty();
|
||||
|
||||
if let Some(index) = def_case {
|
||||
let def_case = &mut case_blocks[*index].statements;
|
||||
let def_span = def_case.span_or_else(*pos, Position::NONE);
|
||||
let def_case: StmtBlockContainer = mem::take(def_case);
|
||||
let def_stmt = optimize_stmt_block(def_case, state, true, true, false);
|
||||
*stmt = (def_stmt, def_span).into();
|
||||
let mut def_stmt = Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
||||
optimize_stmt(&mut def_stmt, state, true);
|
||||
*stmt = def_stmt;
|
||||
} else {
|
||||
*stmt = StmtBlock::empty(*pos).into();
|
||||
}
|
||||
@@ -693,7 +683,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
let (
|
||||
match_expr,
|
||||
SwitchCasesCollection {
|
||||
case_blocks,
|
||||
expressions,
|
||||
cases,
|
||||
ranges,
|
||||
def_case,
|
||||
@@ -704,16 +694,13 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
optimize_expr(match_expr, state, false);
|
||||
|
||||
// Optimize blocks
|
||||
for b in case_blocks.iter_mut() {
|
||||
let statements = mem::take(&mut *b.statements);
|
||||
*b.statements =
|
||||
optimize_stmt_block(statements, state, preserve_result, true, false);
|
||||
|
||||
for b in expressions.iter_mut() {
|
||||
optimize_expr(&mut b.condition, state, false);
|
||||
optimize_expr(&mut b.expr, state, false);
|
||||
|
||||
if b.is_always_false() {
|
||||
if !b.statements.is_empty() {
|
||||
b.statements = StmtBlock::NONE;
|
||||
if !b.expr.is_unit() {
|
||||
b.expr = Expr::Unit(b.expr.position());
|
||||
state.set_dirty();
|
||||
}
|
||||
}
|
||||
@@ -723,7 +710,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
cases.retain(|_, list| {
|
||||
// Remove all entries that have false conditions
|
||||
list.retain(|index| {
|
||||
if case_blocks[*index].is_always_false() {
|
||||
if expressions[*index].is_always_false() {
|
||||
state.set_dirty();
|
||||
false
|
||||
} else {
|
||||
@@ -733,7 +720,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
// Remove all entries after a `true` condition
|
||||
if let Some(n) = list
|
||||
.iter()
|
||||
.find(|&&index| case_blocks[index].is_always_true())
|
||||
.find(|&&index| expressions[index].is_always_true())
|
||||
{
|
||||
if n + 1 < list.len() {
|
||||
state.set_dirty();
|
||||
@@ -752,7 +739,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
|
||||
// Remove false ranges
|
||||
ranges.retain(|r| {
|
||||
if case_blocks[r.index()].is_always_false() {
|
||||
if expressions[r.index()].is_always_false() {
|
||||
state.set_dirty();
|
||||
false
|
||||
} else {
|
||||
@@ -761,14 +748,11 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
});
|
||||
|
||||
if let Some(index) = def_case {
|
||||
let def_stmt_block = &mut case_blocks[*index].statements;
|
||||
let def_block = mem::take(&mut **def_stmt_block);
|
||||
**def_stmt_block =
|
||||
optimize_stmt_block(def_block, state, preserve_result, true, false);
|
||||
optimize_expr(&mut expressions[*index].expr, state, false);
|
||||
}
|
||||
|
||||
// Remove unused block statements
|
||||
for index in 0..case_blocks.len() {
|
||||
for index in 0..expressions.len() {
|
||||
if *def_case == Some(index)
|
||||
|| cases.values().flat_map(|c| c.iter()).any(|&n| n == index)
|
||||
|| ranges.iter().any(|r| r.index() == index)
|
||||
@@ -776,10 +760,10 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
continue;
|
||||
}
|
||||
|
||||
let b = &mut case_blocks[index];
|
||||
let b = &mut expressions[index];
|
||||
|
||||
if !b.statements.is_empty() {
|
||||
b.statements = StmtBlock::NONE;
|
||||
if !b.expr.is_unit() {
|
||||
b.expr = Expr::Unit(b.expr.position());
|
||||
state.set_dirty();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user