use std::sync::Arc;
use vyre_foundation::ir::model::expr::{GeneratorRef, Ident};
use vyre_foundation::ir::{Expr, Node};
use super::layout::OP_ID;
use crate::graph::program_graph::ProgramGraphShape;
#[must_use]
pub fn csr_forward_or_changed_body(
shape: ProgramGraphShape,
frontier_out: &str,
changed_var: &str,
edge_kind_mask: u32,
) -> Vec<Node> {
csr_forward_or_changed_body_prefixed(shape, frontier_out, changed_var, edge_kind_mask, "")
}
fn local(prefix: &str, name: &str) -> String {
if prefix.is_empty() {
name.to_string()
} else {
format!("{prefix}_{name}")
}
}
#[must_use]
pub fn csr_forward_or_changed_body_prefixed(
shape: ProgramGraphShape,
frontier_out: &str,
changed_var: &str,
edge_kind_mask: u32,
prefix: &str,
) -> Vec<Node> {
let src = local(prefix, "src");
let per_source = crate::graph::edge_scan::csr_edge_scan_nodes(
shape,
frontier_out,
Expr::var(src.as_str()),
|word| word,
|| vec![Node::assign(changed_var, Expr::u32(1))],
edge_kind_mask,
prefix,
);
vec![Node::if_then(
Expr::eq(Expr::local_x(), Expr::u32(0)),
vec![Node::loop_for(
src.as_str(),
Expr::u32(0),
Expr::u32(shape.node_count),
per_source,
)],
)]
}
#[must_use]
pub fn csr_forward_or_changed_child(
parent_op_id: &str,
shape: ProgramGraphShape,
frontier_out: &str,
changed_var: &str,
edge_kind_mask: u32,
) -> Node {
csr_forward_or_changed_child_prefixed(
parent_op_id,
shape,
frontier_out,
changed_var,
edge_kind_mask,
"",
)
}
#[must_use]
pub fn csr_forward_or_changed_child_prefixed(
parent_op_id: &str,
shape: ProgramGraphShape,
frontier_out: &str,
changed_var: &str,
edge_kind_mask: u32,
local_prefix: &str,
) -> Node {
Node::Region {
generator: Ident::from(OP_ID),
source_region: Some(GeneratorRef {
name: parent_op_id.to_string(),
}),
body: Arc::new(csr_forward_or_changed_body_prefixed(
shape,
frontier_out,
changed_var,
edge_kind_mask,
local_prefix,
)),
}
}