lisette-semantics 0.2.13

Little language inspired by Rust that compiles to Go
Documentation
use diagnostics::LisetteDiagnostic;
use syntax::ast::{BinaryOperator, Expression, Literal};

pub fn check_unsigned_comparison(
    expression: &Expression,
    diagnostics: &mut Vec<LisetteDiagnostic>,
) {
    let Expression::Binary {
        operator,
        left,
        right,
        span,
        ..
    } = expression
    else {
        return;
    };

    use BinaryOperator::*;
    if !matches!(
        operator,
        Equal | NotEqual | LessThan | LessThanOrEqual | GreaterThan | GreaterThanOrEqual
    ) {
        return;
    }

    let operator = match (
        is_zero_literal(left.unwrap_parens()),
        is_zero_literal(right.unwrap_parens()),
    ) {
        (true, false) if right.get_type().is_unsigned_int() => flip_comparison(*operator),
        (false, true) if left.get_type().is_unsigned_int() => *operator,
        _ => return,
    };

    let always_true = match operator {
        LessThan => false,
        GreaterThanOrEqual => true,
        _ => return,
    };

    diagnostics.push(diagnostics::lint::unsigned_comparison(span, always_true));
}

fn is_zero_literal(expression: &Expression) -> bool {
    matches!(
        expression,
        Expression::Literal {
            literal: Literal::Integer { value: 0, .. },
            ..
        }
    )
}

fn flip_comparison(operator: BinaryOperator) -> BinaryOperator {
    use BinaryOperator::*;
    match operator {
        LessThan => GreaterThan,
        LessThanOrEqual => GreaterThanOrEqual,
        GreaterThan => LessThan,
        GreaterThanOrEqual => LessThanOrEqual,
        other => other,
    }
}