lisette-semantics 0.2.13

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

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::Range {
        start: Some(start),
        end: Some(end),
        span,
        ..
    } = expression
        && let Some(start_value) = signed_integer_literal(start.unwrap_parens())
        && let Some(end_value) = signed_integer_literal(end.unwrap_parens())
        && start_value > end_value
    {
        sink.push(diagnostics::infer::empty_range(span));
    }

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

fn signed_integer_literal(expression: &Expression) -> Option<i128> {
    match expression {
        Expression::Literal {
            literal: Literal::Integer { value, .. },
            ..
        } => Some(*value as i128),
        Expression::Unary {
            operator: UnaryOperator::Negative,
            expression,
            ..
        } => {
            let Expression::Literal {
                literal: Literal::Integer { value, .. },
                ..
            } = expression.unwrap_parens()
            else {
                return None;
            };
            Some(-(*value as i128))
        }
        _ => None,
    }
}