veryl-analyzer 0.20.0

A modern hardware description language
Documentation
use crate::AnalyzerError;
use crate::conv::Context;
use crate::ir::{ArrayLiteralItem, Expression, Factor};
use veryl_parser::token_range::TokenRange;

pub fn check_anonymous(
    context: &mut Context,
    expr: &Expression,
    allow_anonymous: bool,
    token: TokenRange,
) {
    let is_anonymous = is_anonymous(expr);
    let has_anonymous = has_anonymous(expr);

    if has_anonymous && !is_anonymous {
        context.insert_error(AnalyzerError::anonymous_identifier_usage(&token));
    }

    if is_anonymous && !allow_anonymous {
        context.insert_error(AnalyzerError::anonymous_identifier_usage(&token));
    }
}

fn is_anonymous(expr: &Expression) -> bool {
    if let Expression::Term(x) = expr {
        matches!(x.as_ref(), Factor::Anonymous(_))
    } else {
        false
    }
}

fn has_anonymous(expr: &Expression) -> bool {
    match expr {
        Expression::Term(x) => matches!(x.as_ref(), Factor::Anonymous(_)),
        Expression::Unary(_, x, _) => has_anonymous(x),
        Expression::Binary(x, _, y, _) => has_anonymous(x) | has_anonymous(y),
        Expression::Ternary(x, y, z, _) => has_anonymous(x) | has_anonymous(y) | has_anonymous(z),
        Expression::Concatenation(x, _) => {
            let mut ret = false;
            for x in x {
                ret |= has_anonymous(&x.0);

                if let Some(x) = &x.1 {
                    ret |= has_anonymous(x);
                }
            }
            ret
        }
        Expression::ArrayLiteral(x, _) => {
            let mut ret = false;
            for x in x {
                match x {
                    ArrayLiteralItem::Value(x, y) => {
                        ret |= has_anonymous(x);

                        if let Some(y) = &y {
                            ret |= has_anonymous(y);
                        }
                    }
                    ArrayLiteralItem::Defaul(x) => {
                        ret |= has_anonymous(x);
                    }
                }
            }
            ret
        }
        Expression::StructConstructor(_, x, _) => {
            let mut ret = false;
            for (_, x) in x {
                ret |= has_anonymous(x);
            }
            ret
        }
    }
}