fn logical_not()

in checker/src/abstract_value.rs [3919:3988]


    fn logical_not(&self) -> Rc<AbstractValue> {
        match &self.expression {
            Expression::Bottom => self.clone(),
            Expression::Equals { left: x, right: y }
                if !x.expression.infer_type().is_floating_point_number() =>
            {
                // [!(x == y)] -> x != y
                x.not_equals(y.clone())
            }
            Expression::GreaterThan { left: x, right: y }
                if x.expression.infer_type().is_integer() =>
            {
                // [!(x > y)] -> x <= y
                x.less_or_equal(y.clone())
            }
            Expression::GreaterOrEqual { left: x, right: y }
                if x.expression.infer_type().is_integer() =>
            {
                // [!(x >= y)] -> x < y
                x.less_than(y.clone())
            }
            Expression::LessThan { left: x, right: y }
                if x.expression.infer_type().is_integer() =>
            {
                // [!(x < y)] -> x >= y
                x.greater_or_equal(y.clone())
            }
            Expression::LessOrEqual { left: x, right: y }
                if x.expression.infer_type().is_integer() =>
            {
                // [!(x <= y)] -> x > y
                x.greater_than(y.clone())
            }
            Expression::LogicalNot { operand } => {
                // [!!x] -> x
                operand.clone()
            }
            Expression::Ne { left: x, right: y }
                if !x.expression.infer_type().is_floating_point_number() =>
            {
                // [!(x != y)] -> x == y
                x.equals(y.clone())
            }
            Expression::Or { left: x, right }
                if matches!(right.expression, Expression::LogicalNot { .. }) =>
            {
                // [!(x || !y)] -> !x && y
                if let Expression::LogicalNot { operand: y } = &right.expression {
                    x.logical_not().and(y.clone())
                } else {
                    unreachable!()
                }
            }
            Expression::Or { left, right: y }
                if matches!(left.expression, Expression::LogicalNot { .. }) =>
            {
                // [!(!x || y)] -> x && !y
                if let Expression::LogicalNot { operand: x } = &left.expression {
                    x.and(y.logical_not())
                } else {
                    unreachable!()
                }
            }
            _ => self.try_to_constant_fold_and_distribute_unary_op(
                ConstantDomain::logical_not,
                Self::logical_not,
                |o| AbstractValue::make_unary(o, |operand| Expression::LogicalNot { operand }),
            ),
        }
    }