vyre-libs 0.6.3

vyre Category A library ecosystem - pure-IR compositions over vyre-ops hardware primitives
Documentation
use super::super::*;
use crate::parsing::c::lex::tokens::*;
use vyre::ir::Expr;

pub(crate) fn is_open_token(token: Expr) -> Expr {
    Expr::or(
        Expr::or(
            Expr::eq(token.clone(), Expr::u32(TOK_LPAREN)),
            Expr::eq(token.clone(), Expr::u32(TOK_LBRACE)),
        ),
        Expr::eq(token, Expr::u32(TOK_LBRACKET)),
    )
}

pub(crate) fn is_matching_close(current: Expr, candidate: Expr) -> Expr {
    Expr::or(
        Expr::or(
            Expr::and(
                Expr::eq(current.clone(), Expr::u32(TOK_LPAREN)),
                Expr::eq(candidate.clone(), Expr::u32(TOK_RPAREN)),
            ),
            Expr::and(
                Expr::eq(current.clone(), Expr::u32(TOK_LBRACE)),
                Expr::eq(candidate.clone(), Expr::u32(TOK_RBRACE)),
            ),
        ),
        Expr::and(
            Expr::eq(current, Expr::u32(TOK_LBRACKET)),
            Expr::eq(candidate, Expr::u32(TOK_RBRACKET)),
        ),
    )
}

pub(crate) fn is_c_literal_token(token: Expr) -> Expr {
    Expr::or(
        Expr::or(
            Expr::eq(token.clone(), Expr::u32(TOK_INTEGER)),
            Expr::eq(token.clone(), Expr::u32(TOK_FLOAT)),
        ),
        Expr::or(
            Expr::eq(token.clone(), Expr::u32(TOK_STRING)),
            Expr::eq(token, Expr::u32(TOK_CHAR)),
        ),
    )
}

pub(crate) fn c_statement_kind(token: Expr) -> Expr {
    Expr::select(
        Expr::eq(token.clone(), Expr::u32(TOK_IF)),
        Expr::u32(C_AST_KIND_IF_STMT),
        Expr::select(
            Expr::eq(token.clone(), Expr::u32(TOK_ELSE)),
            Expr::u32(C_AST_KIND_ELSE_STMT),
            Expr::select(
                Expr::eq(token.clone(), Expr::u32(TOK_SWITCH)),
                Expr::u32(C_AST_KIND_SWITCH_STMT),
                Expr::select(
                    Expr::eq(token.clone(), Expr::u32(TOK_CASE)),
                    Expr::u32(C_AST_KIND_CASE_STMT),
                    Expr::select(
                        Expr::eq(token.clone(), Expr::u32(TOK_DEFAULT)),
                        Expr::u32(C_AST_KIND_DEFAULT_STMT),
                        Expr::select(
                            Expr::eq(token.clone(), Expr::u32(TOK_FOR)),
                            Expr::u32(C_AST_KIND_FOR_STMT),
                            Expr::select(
                                Expr::eq(token.clone(), Expr::u32(TOK_WHILE)),
                                Expr::u32(C_AST_KIND_WHILE_STMT),
                                Expr::select(
                                    Expr::eq(token.clone(), Expr::u32(TOK_DO)),
                                    Expr::u32(C_AST_KIND_DO_STMT),
                                    Expr::select(
                                        Expr::eq(token.clone(), Expr::u32(TOK_RETURN)),
                                        Expr::u32(C_AST_KIND_RETURN_STMT),
                                        Expr::select(
                                            Expr::eq(token.clone(), Expr::u32(TOK_BREAK)),
                                            Expr::u32(C_AST_KIND_BREAK_STMT),
                                            Expr::select(
                                                Expr::eq(token.clone(), Expr::u32(TOK_CONTINUE)),
                                                Expr::u32(C_AST_KIND_CONTINUE_STMT),
                                                Expr::select(
                                                    Expr::eq(token, Expr::u32(TOK_GOTO)),
                                                    Expr::u32(C_AST_KIND_GOTO_STMT),
                                                    Expr::u32(0),
                                                ),
                                            ),
                                        ),
                                    ),
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ),
    )
}

pub(crate) fn any_token_eq(token: Expr, values: &[u32]) -> Expr {
    balanced_or(
        merged_token_ranges(values)
            .into_iter()
            .map(|(lo, hi)| token_range_expr(&token, lo, hi))
            .collect(),
    )
}

pub(crate) fn balanced_or(mut exprs: Vec<Expr>) -> Expr {
    if exprs.is_empty() {
        return Expr::bool(false);
    }

    while exprs.len() > 1 {
        let mut next = Vec::with_capacity(exprs.len().div_ceil(2));
        let mut iter = exprs.into_iter();
        while let Some(left) = iter.next() {
            match iter.next() {
                Some(right) => next.push(Expr::or(left, right)),
                None => next.push(left),
            }
        }
        exprs = next;
    }

    match exprs.pop() {
        Some(expr) => expr,
        None => Expr::bool(false),
    }
}

pub(crate) fn token_range_expr(token: &Expr, lo: u32, hi: u32) -> Expr {
    if lo == hi {
        Expr::eq(token.clone(), Expr::u32(lo))
    } else {
        Expr::and(
            Expr::ge(token.clone(), Expr::u32(lo)),
            Expr::le(token.clone(), Expr::u32(hi)),
        )
    }
}

pub(crate) fn merged_token_ranges(values: &[u32]) -> Vec<(u32, u32)> {
    let mut sorted = values.to_vec();
    sorted.sort_unstable();
    sorted.dedup();

    let mut ranges: Vec<(u32, u32)> = Vec::new();
    for value in sorted {
        match ranges.last_mut() {
            Some((_, hi)) if hi.checked_add(1) == Some(value) => *hi = value,
            _ => ranges.push((value, value)),
        }
    }
    ranges
}