lisette-semantics 0.2.14

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

pub(crate) fn run(typed_ast: &[Expression], sink: &LocalSink) {
    for item in typed_ast {
        visit_expression(item, sink);
    }
}

fn visit_expression(expression: &Expression, sink: &LocalSink) {
    if let Expression::Binary {
        operator,
        left,
        right,
        span,
        ..
    } = expression
        && matches!(
            operator,
            BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight
        )
        && let Some(kind) = left.get_type().as_simple()
        && let Some(bit_width) = fixed_bit_width(kind)
        && let Expression::Literal {
            literal: Literal::Integer { value, .. },
            ..
        } = right.unwrap_parens()
        && *value >= u64::from(bit_width)
    {
        sink.push(diagnostics::infer::oversized_shift(
            span,
            kind.leaf_name(),
            bit_width,
            *value,
        ));
    }

    for child in expression.children() {
        visit_expression(child, sink);
    }
}

fn fixed_bit_width(kind: SimpleKind) -> Option<u32> {
    match kind {
        SimpleKind::Int8 | SimpleKind::Uint8 | SimpleKind::Byte => Some(8),
        SimpleKind::Int16 | SimpleKind::Uint16 => Some(16),
        SimpleKind::Int32 | SimpleKind::Uint32 | SimpleKind::Rune => Some(32),
        SimpleKind::Int64 | SimpleKind::Uint64 => Some(64),
        _ => None,
    }
}