Skip to content

Commit

Permalink
feat(minifier): implement calculations for NumberValue (#6419)
Browse files Browse the repository at this point in the history
  • Loading branch information
7086cmd committed Oct 10, 2024
1 parent 73d6a4a commit ebbf77d
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 11 deletions.
2 changes: 1 addition & 1 deletion crates/oxc_minifier/src/node_util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ pub trait NodeUtil {
Expression::UnaryExpression(unary_expr) => match unary_expr.operator {
UnaryOperator::UnaryPlus => self.get_number_value(&unary_expr.argument),
UnaryOperator::UnaryNegation => {
self.get_number_value(&unary_expr.argument).map(|v| v.not())
self.get_number_value(&unary_expr.argument).map(|v| -v)
}
UnaryOperator::BitwiseNot => {
self.get_number_value(&unary_expr.argument).map(|value| {
Expand Down
110 changes: 100 additions & 10 deletions crates/oxc_minifier/src/node_util/number_value.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use num_traits::Zero;

#[derive(PartialEq)]
pub enum NumberValue {
Number(f64),
Expand All @@ -7,21 +9,21 @@ pub enum NumberValue {
}

impl NumberValue {
#[must_use]
pub fn not(&self) -> Self {
match self {
Self::Number(num) => Self::Number(-num),
Self::PositiveInfinity => Self::NegativeInfinity,
Self::NegativeInfinity => Self::PositiveInfinity,
Self::NaN => Self::NaN,
}
}

pub fn is_nan(&self) -> bool {
matches!(self, Self::NaN)
}
}

impl Zero for NumberValue {
fn zero() -> Self {
Self::Number(0.0)
}

fn is_zero(&self) -> bool {
matches!(self, Self::Number(num) if num.is_zero())
}
}

impl std::ops::Add<Self> for NumberValue {
type Output = Self;

Expand All @@ -46,6 +48,94 @@ impl std::ops::Add<Self> for NumberValue {
}
}

impl std::ops::Sub<Self> for NumberValue {
type Output = Self;

fn sub(self, other: Self) -> Self {
self + (-other)
}
}

impl std::ops::Mul<Self> for NumberValue {
type Output = Self;

fn mul(self, other: Self) -> Self {
match self {
Self::Number(num) => match other {
Self::Number(other_num) => Self::Number(num * other_num),
Self::PositiveInfinity | Self::NegativeInfinity if num.is_zero() => Self::NaN,
Self::PositiveInfinity => Self::PositiveInfinity,
Self::NegativeInfinity => Self::NegativeInfinity,
Self::NaN => Self::NaN,
},
Self::NaN => Self::NaN,
Self::PositiveInfinity | Self::NegativeInfinity => match other {
Self::Number(num) if num > 0.0 => self,
Self::Number(num) if num < 0.0 => -self,
Self::PositiveInfinity => self,
Self::NegativeInfinity => -self,
_ => Self::NaN,
},
}
}
}

impl std::ops::Div<Self> for NumberValue {
type Output = Self;

fn div(self, other: Self) -> Self {
match self {
Self::Number(num) => match other {
Self::Number(other_num) if other_num.is_zero() => Self::NaN,
Self::Number(other_num) => Self::Number(num / other_num),
Self::PositiveInfinity | Self::NegativeInfinity if num < 0.0 => -other,
Self::PositiveInfinity | Self::NegativeInfinity if num > 0.0 => other,
_ => Self::NaN,
},
Self::NaN => Self::NaN,
Self::PositiveInfinity | Self::NegativeInfinity => match other {
Self::Number(num) if num > 0.0 => self,
Self::Number(num) if num < 0.0 => -self,
_ => Self::NaN,
},
}
}
}

impl std::ops::Rem<Self> for NumberValue {
type Output = Self;

fn rem(self, other: Self) -> Self {
match self {
Self::Number(num) => match other {
Self::Number(other_num) if other_num.is_zero() => Self::NaN,
Self::Number(other_num) => Self::Number(num % other_num),
Self::PositiveInfinity | Self::NegativeInfinity if num.is_zero() => Self::NaN,
Self::PositiveInfinity | Self::NegativeInfinity => self,
Self::NaN => Self::NaN,
},
Self::NaN => Self::NaN,
Self::PositiveInfinity | Self::NegativeInfinity => match other {
Self::Number(num) if !num.is_zero() => self,
_ => Self::NaN,
},
}
}
}

impl std::ops::Neg for NumberValue {
type Output = Self;

fn neg(self) -> Self {
match self {
Self::Number(num) => Self::Number(-num),
Self::PositiveInfinity => Self::NegativeInfinity,
Self::NegativeInfinity => Self::PositiveInfinity,
Self::NaN => Self::NaN,
}
}
}

impl TryFrom<NumberValue> for f64 {
type Error = ();

Expand Down

0 comments on commit ebbf77d

Please sign in to comment.