vyre-libs 0.6.2

vyre Category A library ecosystem - pure-IR compositions over vyre-ops hardware primitives
Documentation
use super::*;

pub(super) fn expr_is_kind(kind: Expr, expected: u32) -> Expr {
    Expr::eq(kind, Expr::u32(expected))
}

pub(super) fn valid_node_idx(idx: Expr, num_nodes: &Expr) -> Expr {
    Expr::and(
        Expr::ne(idx.clone(), Expr::u32(u32::MAX)),
        Expr::lt(idx, num_nodes.clone()),
    )
}

pub(super) fn common_parent_walk_bound(num_nodes: &Expr) -> Expr {
    Expr::select(
        Expr::lt(num_nodes.clone(), Expr::u32(COMMON_PARENT_WALK_LIMIT)),
        num_nodes.clone(),
        Expr::u32(COMMON_PARENT_WALK_LIMIT),
    )
}

pub(super) fn vast_field(vast_nodes: &str, idx: Expr, field: usize) -> Expr {
    Expr::load(
        vast_nodes,
        Expr::add(
            Expr::mul(idx, Expr::u32(VAST_NODE_STRIDE_U32)),
            Expr::u32(field as u32),
        ),
    )
}

fn emit_root_node_walk(
    vast_nodes: &str,
    num_nodes: &Expr,
    start_idx: Expr,
    root_var: &str,
    parent_var: &str,
    loop_var: &str,
    bind_initial_vars: bool,
) -> Vec<Node> {
    let root_init = if bind_initial_vars {
        Node::let_bind(root_var, start_idx.clone())
    } else {
        Node::assign(root_var, start_idx.clone())
    };
    let parent_init = if bind_initial_vars {
        Node::let_bind(parent_var, Expr::u32(u32::MAX))
    } else {
        Node::assign(parent_var, Expr::u32(u32::MAX))
    };
    vec![
        root_init,
        parent_init,
        Node::if_then(
            valid_node_idx(start_idx.clone(), num_nodes),
            vec![Node::assign(
                parent_var,
                vast_field(vast_nodes, start_idx, IDX_PARENT),
            )],
        ),
        Node::loop_for(
            loop_var,
            Expr::u32(0),
            num_nodes.clone(),
            vec![Node::if_then(
                valid_node_idx(Expr::var(parent_var), num_nodes),
                vec![
                    Node::assign(root_var, Expr::var(parent_var)),
                    Node::assign(
                        parent_var,
                        vast_field(vast_nodes, Expr::var(parent_var), IDX_PARENT),
                    ),
                ],
            )],
        ),
    ]
}

pub(super) fn resolve_root_nodes(
    vast_nodes: &str,
    num_nodes: &Expr,
    start_idx: Expr,
    root_var: &str,
    parent_var: &str,
    loop_var: &str,
) -> Vec<Node> {
    emit_root_node_walk(
        vast_nodes, num_nodes, start_idx, root_var, parent_var, loop_var, true,
    )
}

pub(super) fn assign_root_nodes(
    vast_nodes: &str,
    num_nodes: &Expr,
    start_idx: Expr,
    root_var: &str,
    parent_var: &str,
    loop_var: &str,
) -> Vec<Node> {
    emit_root_node_walk(
        vast_nodes, num_nodes, start_idx, root_var, parent_var, loop_var, false,
    )
}