Simplify deref_mut to &mut *.

This commit is contained in:
Stephen Chung 2021-12-15 23:21:05 +08:00
parent abbfa3777d
commit 2adb4ba4a8
3 changed files with 54 additions and 119 deletions

View File

@ -756,7 +756,7 @@ impl DerefMut for Target<'_> {
match self { match self {
Self::RefMut(r) => *r, Self::RefMut(r) => *r,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Self::LockGuard((r, _)) => r.deref_mut(), Self::LockGuard((r, _)) => &mut *r,
Self::TempValue(ref mut r) => r, Self::TempValue(ref mut r) => r,
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Self::Bit(_, ref mut r, _) Self::Bit(_, ref mut r, _)

View File

@ -16,7 +16,6 @@ use std::{
convert::TryFrom, convert::TryFrom,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
mem, mem,
ops::DerefMut,
}; };
/// Level of optimization performed. /// Level of optimization performed.
@ -389,8 +388,10 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
let value = mem::take(&mut x2.args[1]); let value = mem::take(&mut x2.args[1]);
if let Expr::Stack(slot, pos) = value { if let Expr::Stack(slot, pos) = value {
let value = mem::take(x2.constants.get_mut(slot).expect("valid slot")); x.2 = Expr::from_dynamic(
x.2 = Expr::from_dynamic(value, pos); mem::take(x2.constants.get_mut(slot).expect("valid slot")),
pos,
);
} else { } else {
x.2 = value; x.2 = value;
} }
@ -432,8 +433,9 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
// if false { if_block } else { else_block } -> else_block // if false { if_block } else { else_block } -> else_block
Stmt::If(Expr::BoolConstant(false, _), x, _) => { Stmt::If(Expr::BoolConstant(false, _), x, _) => {
state.set_dirty(); state.set_dirty();
let else_block = mem::take(&mut *x.1); *stmt =
*stmt = match optimize_stmt_block(else_block, state, preserve_result, true, false) { match optimize_stmt_block(mem::take(&mut *x.1), state, preserve_result, true, false)
{
statements if statements.is_empty() => Stmt::Noop(x.1.position()), statements if statements.is_empty() => Stmt::Noop(x.1.position()),
statements => Stmt::Block(statements.into_boxed_slice(), x.1.position()), statements => Stmt::Block(statements.into_boxed_slice(), x.1.position()),
} }
@ -441,8 +443,9 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
// if true { if_block } else { else_block } -> if_block // if true { if_block } else { else_block } -> if_block
Stmt::If(Expr::BoolConstant(true, _), x, _) => { Stmt::If(Expr::BoolConstant(true, _), x, _) => {
state.set_dirty(); state.set_dirty();
let if_block = mem::take(&mut *x.0); *stmt =
*stmt = match optimize_stmt_block(if_block, state, preserve_result, true, false) { match optimize_stmt_block(mem::take(&mut *x.0), state, preserve_result, true, false)
{
statements if statements.is_empty() => Stmt::Noop(x.0.position()), statements if statements.is_empty() => Stmt::Noop(x.0.position()),
statements => Stmt::Block(statements.into_boxed_slice(), x.0.position()), statements => Stmt::Block(statements.into_boxed_slice(), x.0.position()),
} }
@ -450,10 +453,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
// if expr { if_block } else { else_block } // if expr { if_block } else { else_block }
Stmt::If(condition, x, _) => { Stmt::If(condition, x, _) => {
optimize_expr(condition, state, false); optimize_expr(condition, state, false);
let if_block = mem::take(x.0.deref_mut()); *x.0 = optimize_stmt_block(mem::take(&mut *x.0), state, preserve_result, true, false);
*x.0 = optimize_stmt_block(if_block, state, preserve_result, true, false); *x.1 = optimize_stmt_block(mem::take(&mut *x.1), 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 { ... } // switch const { ... }
@ -584,7 +585,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
Stmt::Switch(match_expr, x, _) => { Stmt::Switch(match_expr, x, _) => {
optimize_expr(match_expr, state, false); optimize_expr(match_expr, state, false);
x.0.values_mut().for_each(|block| { x.0.values_mut().for_each(|block| {
let statements = mem::take(block.1.deref_mut()); let statements = mem::take(&mut *block.1);
*block.1 = optimize_stmt_block(statements, state, preserve_result, true, false); *block.1 = optimize_stmt_block(statements, state, preserve_result, true, false);
if let Some(mut condition) = mem::take(&mut block.0) { if let Some(mut condition) = mem::take(&mut block.0) {
@ -605,8 +606,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
x.0.remove(&key); x.0.remove(&key);
} }
let def_block = mem::take(x.1.deref_mut()); *x.1 = optimize_stmt_block(mem::take(&mut *x.1), state, preserve_result, true, false);
*x.1 = optimize_stmt_block(def_block, state, preserve_result, true, false);
} }
// while false { block } -> Noop // while false { block } -> Noop
@ -620,8 +620,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
if let Expr::BoolConstant(true, pos) = condition { if let Expr::BoolConstant(true, pos) = condition {
*condition = Expr::Unit(*pos); *condition = Expr::Unit(*pos);
} }
let block = mem::take(body.as_mut().deref_mut()); ***body = optimize_stmt_block(mem::take(&mut **body), state, false, true, false);
*body.as_mut().deref_mut() = optimize_stmt_block(block, state, false, true, false);
if body.len() == 1 { if body.len() == 1 {
match body[0] { match body[0] {
@ -648,24 +647,21 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
if *x == options.contains(AST_OPTION_NEGATED) => if *x == options.contains(AST_OPTION_NEGATED) =>
{ {
state.set_dirty(); state.set_dirty();
let block_pos = body.position();
let block = mem::take(body.as_mut().deref_mut());
*stmt = Stmt::Block( *stmt = Stmt::Block(
optimize_stmt_block(block, state, false, true, false).into_boxed_slice(), optimize_stmt_block(mem::take(&mut **body), state, false, true, false)
block_pos, .into_boxed_slice(),
body.position(),
); );
} }
// do { block } while|until expr // do { block } while|until expr
Stmt::Do(body, condition, _, _) => { Stmt::Do(body, condition, _, _) => {
optimize_expr(condition, state, false); optimize_expr(condition, state, false);
let block = mem::take(body.as_mut().deref_mut()); ***body = optimize_stmt_block(mem::take(&mut **body), state, false, true, false);
*body.as_mut().deref_mut() = optimize_stmt_block(block, state, false, true, false);
} }
// for id in expr { block } // for id in expr { block }
Stmt::For(iterable, x, _) => { Stmt::For(iterable, x, _) => {
optimize_expr(iterable, state, false); optimize_expr(iterable, state, false);
let body = mem::take(x.2.deref_mut()); *x.2 = optimize_stmt_block(mem::take(&mut *x.2), state, false, true, false);
*x.2 = optimize_stmt_block(body, state, false, true, false);
} }
// let id = expr; // let id = expr;
Stmt::Var(expr, _, options, _) if !options.contains(AST_OPTION_CONSTANT) => { Stmt::Var(expr, _, options, _) if !options.contains(AST_OPTION_CONSTANT) => {
@ -696,19 +692,16 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
Stmt::TryCatch(x, _) if x.0.iter().all(Stmt::is_pure) => { Stmt::TryCatch(x, _) if x.0.iter().all(Stmt::is_pure) => {
// If try block is pure, there will never be any exceptions // If try block is pure, there will never be any exceptions
state.set_dirty(); state.set_dirty();
let try_pos = x.0.position();
let try_block = mem::take(&mut *x.0);
*stmt = Stmt::Block( *stmt = Stmt::Block(
optimize_stmt_block(try_block, state, false, true, false).into_boxed_slice(), optimize_stmt_block(mem::take(&mut *x.0), state, false, true, false)
try_pos, .into_boxed_slice(),
x.0.position(),
); );
} }
// try { try_block } catch ( var ) { catch_block } // try { try_block } catch ( var ) { catch_block }
Stmt::TryCatch(x, _) => { Stmt::TryCatch(x, _) => {
let try_block = mem::take(x.0.deref_mut()); *x.0 = optimize_stmt_block(mem::take(&mut *x.0), state, false, true, false);
*x.0 = optimize_stmt_block(try_block, state, false, true, false); *x.2 = optimize_stmt_block(mem::take(&mut *x.2), 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(...) // func(...)
Stmt::Expr(expr @ Expr::FnCall(_, _)) => { Stmt::Expr(expr @ Expr::FnCall(_, _)) => {
@ -729,7 +722,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
// {...}; // {...};
Stmt::Expr(Expr::Stmt(x)) => { Stmt::Expr(Expr::Stmt(x)) => {
state.set_dirty(); state.set_dirty();
*stmt = mem::take(x.as_mut()).into(); *stmt = mem::take(&mut **x).into();
} }
// expr; // expr;
Stmt::Expr(expr) => optimize_expr(expr, state, false), Stmt::Expr(expr) => optimize_expr(expr, state, false),
@ -757,8 +750,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
Expr::Stmt(x) if x.is_empty() => { state.set_dirty(); *expr = Expr::Unit(x.position()) } Expr::Stmt(x) if x.is_empty() => { state.set_dirty(); *expr = Expr::Unit(x.position()) }
// { stmt; ... } - do not count promotion as dirty because it gets turned back into an array // { stmt; ... } - do not count promotion as dirty because it gets turned back into an array
Expr::Stmt(x) => { Expr::Stmt(x) => {
*x.as_mut().deref_mut() = ***x = optimize_stmt_block(mem::take(&mut **x), state, true, true, false);
optimize_stmt_block(mem::take(x.as_mut().deref_mut()), state, true, true, false);
// { Stmt(Expr) } - promote // { Stmt(Expr) } - promote
match x.as_mut().as_mut() { match x.as_mut().as_mut() {
@ -792,9 +784,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Expr::Index(x, _, _) if !_chaining => match (&mut x.lhs, &mut x.rhs) { Expr::Index(x, _, _) if !_chaining => match (&mut x.lhs, &mut x.rhs) {
// array[int] // array[int]
(Expr::Array(a, pos), Expr::IntegerConstant(i, _)) (Expr::Array(a, pos), Expr::IntegerConstant(i, _)) if *i >= 0 && (*i as usize) < a.len() && a.iter().all(Expr::is_pure) => {
if *i >= 0 && (*i as usize) < a.len() && a.iter().all(Expr::is_pure) =>
{
// Array literal where everything is pure - promote the indexed item. // Array literal where everything is pure - promote the indexed item.
// All other items can be thrown away. // All other items can be thrown away.
state.set_dirty(); state.set_dirty();
@ -803,9 +793,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
*expr = result; *expr = result;
} }
// array[-int] // array[-int]
(Expr::Array(a, pos), Expr::IntegerConstant(i, _)) (Expr::Array(a, pos), Expr::IntegerConstant(i, _)) if *i < 0 && i.checked_abs().map(|n| n as usize <= a.len()).unwrap_or(false) && a.iter().all(Expr::is_pure) => {
if *i < 0 && i.checked_abs().map(|n| n as usize <= a.len()).unwrap_or(false) && a.iter().all(Expr::is_pure) =>
{
// Array literal where everything is pure - promote the indexed item. // Array literal where everything is pure - promote the indexed item.
// All other items can be thrown away. // All other items can be thrown away.
state.set_dirty(); state.set_dirty();
@ -874,37 +862,12 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
// Merge consecutive strings // Merge consecutive strings
while n < x.len() - 1 { while n < x.len() - 1 {
match (mem::take(&mut x[n]), mem::take(&mut x[n+1])) { match (mem::take(&mut x[n]), mem::take(&mut x[n+1])) {
(Expr::StringConstant(mut s1, pos), Expr::StringConstant(s2, _)) => { (Expr::StringConstant(mut s1, pos), Expr::StringConstant(s2, _)) => { s1 += s2; x[n] = Expr::StringConstant(s1, pos); x.remove(n+1); state.set_dirty(); }
s1 += s2; (expr1, Expr::Unit(_)) => { x[n] = expr1; x.remove(n+1); state.set_dirty(); }
x[n] = Expr::StringConstant(s1, pos); (Expr::Unit(_), expr2) => { x[n+1] = expr2; x.remove(n); state.set_dirty(); }
x.remove(n+1); (expr1, Expr::StringConstant(s, _)) if s.is_empty() => { x[n] = expr1; x.remove(n+1); state.set_dirty(); }
state.set_dirty(); (Expr::StringConstant(s, _), expr2) if s.is_empty()=> { x[n+1] = expr2; x.remove(n); state.set_dirty(); }
} (expr1, expr2) => { x[n] = expr1; x[n+1] = expr2; n += 1; }
(expr1, Expr::Unit(_)) => {
x[n] = expr1;
x.remove(n+1);
state.set_dirty();
}
(Expr::Unit(_), expr2) => {
x[n+1] = expr2;
x.remove(n);
state.set_dirty();
}
(expr1, Expr::StringConstant(s, _)) if s.is_empty() => {
x[n] = expr1;
x.remove(n+1);
state.set_dirty();
}
(Expr::StringConstant(s, _), expr2) if s.is_empty()=> {
x[n+1] = expr2;
x.remove(n);
state.set_dirty();
}
(expr1, expr2) => {
x[n] = expr1;
x[n+1] = expr2;
n += 1;
}
} }
} }
@ -931,52 +894,24 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
// lhs && rhs // lhs && rhs
Expr::And(x, _) => match (&mut x.lhs, &mut x.rhs) { Expr::And(x, _) => match (&mut x.lhs, &mut x.rhs) {
// true && rhs -> rhs // true && rhs -> rhs
(Expr::BoolConstant(true, _), rhs) => { (Expr::BoolConstant(true, _), rhs) => { state.set_dirty(); optimize_expr(rhs, state, false); *expr = mem::take(rhs); }
state.set_dirty();
optimize_expr(rhs, state, false);
*expr = mem::take(rhs);
}
// false && rhs -> false // false && rhs -> false
(Expr::BoolConstant(false, pos), _) => { (Expr::BoolConstant(false, pos), _) => { state.set_dirty(); *expr = Expr::BoolConstant(false, *pos); }
state.set_dirty();
*expr = Expr::BoolConstant(false, *pos);
}
// lhs && true -> lhs // lhs && true -> lhs
(lhs, Expr::BoolConstant(true, _)) => { (lhs, Expr::BoolConstant(true, _)) => { state.set_dirty(); optimize_expr(lhs, state, false); *expr = mem::take(lhs); }
state.set_dirty();
optimize_expr(lhs, state, false);
*expr = mem::take(lhs);
}
// lhs && rhs // lhs && rhs
(lhs, rhs) => { (lhs, rhs) => { optimize_expr(lhs, state, false); optimize_expr(rhs, state, false); }
optimize_expr(lhs, state, false);
optimize_expr(rhs, state, false);
}
}, },
// lhs || rhs // lhs || rhs
Expr::Or(ref mut x, _) => match (&mut x.lhs, &mut x.rhs) { Expr::Or(ref mut x, _) => match (&mut x.lhs, &mut x.rhs) {
// false || rhs -> rhs // false || rhs -> rhs
(Expr::BoolConstant(false, _), rhs) => { (Expr::BoolConstant(false, _), rhs) => { state.set_dirty(); optimize_expr(rhs, state, false); *expr = mem::take(rhs); }
state.set_dirty();
optimize_expr(rhs, state, false);
*expr = mem::take(rhs);
}
// true || rhs -> true // true || rhs -> true
(Expr::BoolConstant(true, pos), _) => { (Expr::BoolConstant(true, pos), _) => { state.set_dirty(); *expr = Expr::BoolConstant(true, *pos); }
state.set_dirty();
*expr = Expr::BoolConstant(true, *pos);
}
// lhs || false // lhs || false
(lhs, Expr::BoolConstant(false, _)) => { (lhs, Expr::BoolConstant(false, _)) => { state.set_dirty(); optimize_expr(lhs, state, false); *expr = mem::take(lhs); }
state.set_dirty();
optimize_expr(lhs, state, false);
*expr = mem::take(lhs);
}
// lhs || rhs // lhs || rhs
(lhs, rhs) => { (lhs, rhs) => { optimize_expr(lhs, state, false); optimize_expr(rhs, state, false); }
optimize_expr(lhs, state, false);
optimize_expr(rhs, state, false);
}
}, },
// eval! // eval!
@ -1222,7 +1157,7 @@ pub fn optimize_into_ast(
let mut fn_def = crate::func::native::shared_take_or_clone(fn_def); let mut fn_def = crate::func::native::shared_take_or_clone(fn_def);
// Optimize the function body // Optimize the function body
let body = mem::take(fn_def.body.deref_mut()); let body = mem::take(&mut *fn_def.body);
*fn_def.body = *fn_def.body =
optimize_top_level(body, engine, scope, lib2, optimization_level); optimize_top_level(body, engine, scope, lib2, optimization_level);

View File

@ -108,9 +108,9 @@ pub enum ParseErrorType {
DuplicatedSwitchCase, DuplicatedSwitchCase,
/// A variable name is duplicated. Wrapped value is the variable name. /// A variable name is duplicated. Wrapped value is the variable name.
DuplicatedVariable(String), DuplicatedVariable(String),
/// An integer case of a `switch` statement is after a range case. /// An integer case of a `switch` statement is in an appropriate place.
WrongSwitchIntegerCase, WrongSwitchIntegerCase,
/// The default case of a `switch` statement is not the last. /// The default case of a `switch` statement is in an appropriate place.
WrongSwitchDefaultCase, WrongSwitchDefaultCase,
/// The case condition of a `switch` statement is not appropriate. /// The case condition of a `switch` statement is not appropriate.
WrongSwitchCaseCondition, WrongSwitchCaseCondition,