use oxc_allocator::TakeIn;
use oxc_ast::ast::*;
use oxc_ecmascript::constant_evaluation::DetermineValueType;
use oxc_span::GetSpan;
use crate::TraverseCtx;
use super::PeepholeOptimizations;
impl<'a> PeepholeOptimizations {
pub fn minimize_not(
span: Span,
expr: Expression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let mut unary =
Expression::new_unary_expression(span, UnaryOperator::LogicalNot, expr, ctx);
Self::minimize_unary(&mut unary, ctx);
unary
}
pub fn minimize_unary(expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
let Expression::UnaryExpression(e) = expr else { return };
if !e.operator.is_not() {
return;
}
Self::minimize_expression_in_boolean_context(&mut e.argument, ctx);
match &mut e.argument {
Expression::UnaryExpression(e)
if e.operator.is_not() && e.argument.value_type(ctx).is_boolean() =>
{
let new_expr = e.argument.take_in(ctx);
ctx.replace_expression(expr, new_expr);
}
Expression::BinaryExpression(binary_expr) if binary_expr.operator.is_equality() => {
binary_expr.operator = binary_expr.operator.equality_inverse_operator().unwrap();
let new_expr = e.argument.take_in(ctx);
ctx.replace_expression(expr, new_expr);
}
Expression::SequenceExpression(sequence_expr) => {
if let Some(last_expr) = sequence_expr.expressions.last_mut() {
let new_last =
Self::minimize_not(last_expr.span(), last_expr.take_in(ctx), ctx);
ctx.replace_expression(last_expr, new_last);
let new_expr = e.argument.take_in(ctx);
ctx.replace_expression(expr, new_expr);
}
}
_ => {}
}
}
}