lisette-semantics 0.4.1

Little language inspired by Rust that compiles to Go
Documentation
use crate::passes::walk::NodeCtx;
use syntax::ast::{BinaryOperator, Expression, Literal};

use super::helpers::is_float_operand;

pub fn check_float_equality_without_abs(expression: &Expression, ctx: &NodeCtx) {
    let Expression::Binary {
        operator,
        left,
        right,
        span,
        ..
    } = expression
    else {
        return;
    };

    use BinaryOperator::*;
    let (difference, margin) = match operator {
        LessThan | LessThanOrEqual => (left.unwrap_parens(), right.unwrap_parens()),
        GreaterThan | GreaterThanOrEqual => (right.unwrap_parens(), left.unwrap_parens()),
        _ => return,
    };

    let Expression::Binary {
        operator: BinaryOperator::Subtraction,
        left: minuend,
        right: subtrahend,
        span: difference_span,
        ..
    } = difference
    else {
        return;
    };
    if ctx.facts.type_error_spans.contains(difference_span) {
        return;
    }
    if !is_float_operand(ctx.store, minuend) || !is_float_operand(ctx.store, subtrahend) {
        return;
    }

    if !is_positive_numeric_literal(margin) {
        return;
    }

    ctx.sink
        .push(diagnostics::lint::float_equality_without_abs(span));
}

fn is_positive_numeric_literal(expression: &Expression) -> bool {
    match expression {
        Expression::Literal {
            literal: Literal::Float { value, .. },
            ..
        } => *value > 0.0,
        Expression::Literal {
            literal: Literal::Integer { value, .. },
            ..
        } => *value > 0,
        _ => false,
    }
}