weirflow 0.1.0

GPU-first dataflow analysis primitives for Vyre and Santh compiler pipelines.
Documentation
use super::*;

#[test]
fn fixed_point_analysis_plan_retains_graph_and_program() {
    let graph = FixedPointForwardGraph::new(
        "fixed_point_analysis_plan_test",
        2,
        &[0, 1, 1],
        &[1],
        &[vyre_primitives::predicate::edge_kind::CONTROL],
    )
    .expect("valid graph must pack");
    let program = vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse(
        vyre_primitives::graph::program_graph::ProgramGraphShape::new(2, 1),
        "fin",
        "fout",
        u32::MAX,
    );
    let plan = FixedPointAnalysisPlan::new(graph, program);
    assert_eq!(plan.graph().node_count(), 2);
    assert_eq!(plan.kind(), FixedPointAnalysisKind::Generic);
    assert!(!plan.program().entry().is_empty());
    assert!(plan.retained_graph_bytes() >= 28);
}

#[test]
fn fixed_point_analysis_plan_rejects_wrong_analysis_family() {
    let graph = FixedPointForwardGraph::new_for_kind(
        FixedPointAnalysisKind::Live,
        "fixed_point_analysis_plan_kind_test",
        2,
        &[0, 1, 1],
        &[1],
        &[vyre_primitives::predicate::edge_kind::CONTROL],
    )
    .expect("valid graph must pack");
    let program = vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse(
        vyre_primitives::graph::program_graph::ProgramGraphShape::new(2, 1),
        "fin",
        "fout",
        u32::MAX,
    );
    let plan = FixedPointAnalysisPlan::new_for_kind(FixedPointAnalysisKind::Live, graph, program);

    let err = plan
        .require_kind(FixedPointAnalysisKind::Reaching, "reaching_plan")
        .expect_err("wrong analysis-family plan must be rejected");
    assert!(
        err.contains("expected Reaching"),
        "unexpected diagnostic: {err}"
    );
    assert!(plan
        .require_kind(FixedPointAnalysisKind::Live, "live_plan")
        .is_ok());
}

#[test]
fn fixed_point_forward_graph_rejects_wrong_analysis_family() {
    let graph = FixedPointForwardGraph::new_for_kind(
        FixedPointAnalysisKind::Live,
        "fixed_point_graph_kind_test",
        2,
        &[0, 1, 1],
        &[1],
        &[vyre_primitives::predicate::edge_kind::CONTROL],
    )
    .expect("valid graph must pack");

    let err = graph
        .require_kind(FixedPointAnalysisKind::Reaching, "reaching_prepared")
        .expect_err("wrong analysis-family graph must be rejected");

    assert!(
        err.contains("expected Reaching"),
        "unexpected diagnostic: {err}"
    );
    assert_eq!(graph.kind(), FixedPointAnalysisKind::Live);
}

#[test]
fn fixed_point_analysis_plan_rejects_mismatched_graph_family() {
    let graph = FixedPointForwardGraph::new_for_kind(
        FixedPointAnalysisKind::Live,
        "fixed_point_plan_graph_kind_test",
        2,
        &[0, 1, 1],
        &[1],
        &[vyre_primitives::predicate::edge_kind::CONTROL],
    )
    .expect("valid graph must pack");
    let program = vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse(
        vyre_primitives::graph::program_graph::ProgramGraphShape::new(2, 1),
        "fin",
        "fout",
        u32::MAX,
    );
    let plan =
        FixedPointAnalysisPlan::new_for_kind(FixedPointAnalysisKind::Reaching, graph, program);

    let err = plan
        .require_kind(FixedPointAnalysisKind::Reaching, "reaching_plan")
        .expect_err("plan with mismatched graph family must be rejected");

    assert!(
        err.contains("fixed-point graph"),
        "unexpected diagnostic: {err}"
    );
}

#[test]
fn fixed_point_analysis_plan_exposes_stable_graph_layout_hash() {
    let graph = FixedPointForwardGraph::new(
        "fixed_point_analysis_plan_hash_test",
        2,
        &[0, 1, 1],
        &[1],
        &[vyre_primitives::predicate::edge_kind::CONTROL],
    )
    .expect("valid graph must pack");
    let expected_hash = graph.stable_layout_hash();
    let program = vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse(
        vyre_primitives::graph::program_graph::ProgramGraphShape::new(2, 1),
        "fin",
        "fout",
        u32::MAX,
    );
    let plan = FixedPointAnalysisPlan::new(graph, program);

    assert_eq!(plan.stable_layout_hash(), expected_hash);
    assert_ne!(plan.stable_layout_hash(), 0);
}

#[test]
fn production_fixed_point_paths_do_not_construct_generic_graphs_or_plans() {
    fn scan_rs_files(
        dir: &std::path::Path,
        findings: &mut Vec<String>,
    ) -> Result<(), std::io::Error> {
        for entry in std::fs::read_dir(dir)? {
            let entry = entry?;
            let path = entry.path();
            if path.is_dir() {
                scan_rs_files(&path, findings)?;
                continue;
            }
            if path.extension().and_then(std::ffi::OsStr::to_str) != Some("rs") {
                continue;
            }
            let Some(name) = path.file_name().and_then(std::ffi::OsStr::to_str) else {
                continue;
            };
            if name == "tests.rs" || name == "lib.rs" {
                continue;
            }
            let source = std::fs::read_to_string(&path)?;
            let production_source = source.split("#[cfg(test)]").next().unwrap_or(&source);
            if production_source.contains("FixedPointForwardGraph::new(")
                || production_source.contains("FixedPointAnalysisPlan::new(")
            {
                findings.push(path.display().to_string());
            }
        }
        Ok(())
    }

    let mut findings = Vec::new();
    let src = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
    scan_rs_files(&src, &mut findings).expect("source tree scan must succeed");
    assert!(
        findings.is_empty(),
        "production fixed-point paths must use analysis-typed constructors, not Generic compatibility constructors: {findings:?}"
    );
}