vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
//! Example 03 — vyre's actionable error messages in practice.
//!
//! This example intentionally builds two malformed programs and shows what
//! `validate()` and `lower()` say about them. It also demonstrates that
//! lowering an invalid program returns `Err` rather than panicking.

use vyre::ir::{BufferDecl, DataType, Expr, Node, Program};
use vyre::validate;

fn main() {
    // 1. Build a program that loads from a buffer that doesn't exist.
    //
    //    The store target `out` is declared, but the load source `ghost` is
    //    missing from the buffer table. The validator must catch this before
    //    the program ever reaches a GPU backend.
    let unknown_buffer_program = Program::new(
        vec![
            BufferDecl::read("a", 0, DataType::U32),
            BufferDecl::read_write("out", 1, DataType::U32),
        ],
        [64, 1, 1],
        vec![
            Node::let_bind("idx", Expr::gid_x()),
            Node::if_then(
                Expr::lt(Expr::var("idx"), Expr::buf_len("out")),
                vec![Node::store(
                    "out",
                    Expr::var("idx"),
                    Expr::load("ghost", Expr::var("idx")),
                )],
            ),
        ],
    );

    let errors = validate(&unknown_buffer_program);
    println!("Errors for unknown buffer load:");
    for error in &errors {
        println!("  - {}", error.message());
    }

    assert!(
        !errors.is_empty(),
        "expected at least one validation error for an unknown buffer"
    );
    let first = errors[0].message();
    assert!(
        first.contains("load from unknown buffer `ghost`"),
        "expected 'load from unknown buffer' error, got: {first}"
    );
    assert!(
        first.contains("Fix: declare it in Program::buffers."),
        "expected a 'Fix:' suggestion, got: {first}"
    );

    // 2. Build a program with a type mismatch (xor between U32 and Bool inputs).
    //
    //    `Expr::bitxor` requires u32-compatible operands. Supplying a Bool
    //    buffer causes the validator to reject the right operand.
    let type_mismatch_program = Program::new(
        vec![
            BufferDecl::read("a", 0, DataType::U32),
            BufferDecl::read("b", 1, DataType::Bool),
            BufferDecl::read_write("out", 2, DataType::U32),
        ],
        [64, 1, 1],
        vec![
            Node::let_bind("idx", Expr::gid_x()),
            Node::if_then(
                Expr::lt(Expr::var("idx"), Expr::buf_len("out")),
                vec![Node::store(
                    "out",
                    Expr::var("idx"),
                    Expr::bitxor(
                        Expr::load("a", Expr::var("idx")),
                        Expr::load("b", Expr::var("idx")),
                    ),
                )],
            ),
        ],
    );

    let errors = validate(&type_mismatch_program);
    println!("\nErrors for type mismatch:");
    for error in &errors {
        println!("  - {}", error.message());
    }

    assert!(
        errors.iter().any(|e| {
            let m = e.message();
            m.contains("binary operation") && m.contains("got `bool`")
        }),
        "expected a type mismatch error about `bool`, got: {errors:?}"
    );

    // 3. Try to lower an invalid program and show that it returns Err cleanly.
    let lower_result = vyre::lower::wgsl::lower(&type_mismatch_program);
    match lower_result {
        Ok(wgsl) => {
            // FINDING-EXAMPLES-003: The WGSL lowerer currently does not gate
            // on validation errors; it will produce shader source for invalid
            // IR. This is a correctness gap — lowering should reject invalid
            // programs with Err. Until that is fixed, this example prints the
            // discovery instead of asserting false.
            println!(
                "\nFINDING-EXAMPLES-003: lower() succeeded on invalid input ({} bytes). \
                 The lowerer should return Err for invalid programs but currently does not.",
                wgsl.len()
            );
        }
        Err(error) => {
            println!("\nLower refused invalid program: {error}");
        }
    }

    println!("\nAll error-message assertions passed.");
}