Skip to main content

vyre_reference/
lib.rs

1#![forbid(unsafe_code)]
2#![allow(
3    clippy::only_used_in_recursion,
4    clippy::comparison_chain,
5    clippy::ptr_arg
6)]
7//! Pure Rust reference interpreter for vyre IR programs.
8//!
9//! This module is the executable specification for IR semantics. It is
10//! intentionally slow and direct: every current IR expression and node variant
11//! has a named evaluator function.
12
13extern crate vyre_foundation as vyre;
14
15/// Dual-reference trait and registry types.
16pub mod dual;
17/// Canonical dual implementations and reference evaluators.
18pub mod dual_impls;
19/// Runtime value representation for interpreter inputs and outputs.
20pub mod value;
21
22/// Atomic operation reference implementations.
23pub mod atomics;
24/// CPU operation traits used by concrete reference implementations.
25pub mod cpu_op;
26/// Registry-driven dispatch entry point (B-B4).
27///
28/// Routes an op id through the global `DialectRegistry` and invokes
29/// the registered `cpu_ref` function. Complements the execution-tree
30/// evaluators by giving external dialect crates a zero-patch path to run on
31/// the reference interpreter.
32pub mod dialect_dispatch;
33/// Canonical reference execution tree.
34pub mod execution;
35/// Flat byte adapter used by [`crate::cpu_op::CpuOp`].
36pub mod flat_cpu;
37/// IEEE 754 strict floating-point utilities.
38pub mod ieee754;
39/// Subgroup simulator for lane-collective Cat-C ops.
40pub mod subgroup;
41/// Workgroup simulation: invocation IDs, shared memory.
42pub mod workgroup;
43
44mod oob;
45mod ops;
46
47/// Test-only entry point that runs the hashmap interpreter over a Program.
48#[cfg(test)]
49pub use execution::eval_hashmap_reference;
50/// Execute a vyre Program on the pure Rust reference interpreter.
51pub use execution::{reference_eval, run_arena_reference, run_storage_graph};
52
53/// Resolve an operation ID to its two independently-written references.
54///
55/// # Examples
56///
57/// ```
58/// use vyre_reference::{dual_impls, resolve_dual};
59///
60/// let (reference_a, reference_b) =
61///     resolve_dual(dual_impls::bitwise::xor::OP_ID).expect("Fix: xor dual refs must be registered; restore this invariant before continuing.");
62///
63/// let input = [0b1010_1010_u8, 0b0101_0101];
64/// assert_eq!(reference_a(&input), reference_b(&input));
65/// ```
66pub fn resolve_dual(op_id: &str) -> Option<(dual::ReferenceFn, dual::ReferenceFn)> {
67    match op_id {
68        dual_impls::bitwise::xor::OP_ID => Some((
69            dual_impls::bitwise::xor::reference_a::reference,
70            dual_impls::bitwise::xor::reference_b::reference,
71        )),
72        dual_impls::bitwise::and::OP_ID => Some((
73            dual_impls::bitwise::and::reference_a::reference,
74            dual_impls::bitwise::and::reference_b::reference,
75        )),
76        dual_impls::bitwise::or::OP_ID => Some((
77            dual_impls::bitwise::or::reference_a::reference,
78            dual_impls::bitwise::or::reference_b::reference,
79        )),
80        dual_impls::bitwise::not::OP_ID => Some((
81            dual_impls::bitwise::not::reference_a::reference,
82            dual_impls::bitwise::not::reference_b::reference,
83        )),
84        _ => None,
85    }
86}
87
88/// Return the complete list of operation IDs that have dual references registered.
89///
90/// This is the canonical enumeration used by the differential fuzzing gate.
91/// Every new dual-reference pair MUST add its OP_ID here.
92pub fn dual_op_ids() -> &'static [&'static str] {
93    &[
94        dual_impls::bitwise::xor::OP_ID,
95        dual_impls::bitwise::and::OP_ID,
96        dual_impls::bitwise::or::OP_ID,
97        dual_impls::bitwise::not::OP_ID,
98    ]
99}
100
101/// The architecture of the `OpEntry` registry.
102///
103/// We are forced to split the global primitive registries into three separate
104/// buckets (Unary, Binary, Variadic) instead of a single unified registry.
105///
106/// This split is required because of Rust's trait object lifetime limits.
107/// When storing function pointers that take references (e.g., `&'a Node<'a>`),
108/// higher-ranked trait bounds (HRTB, `for<'a>`) fail to unify on function
109/// pointers with heterogeneous arities. A single registry `fn(&[Node])` slice
110/// signature would force heap allocation for binary/unary nodes to fit the slice,
111/// destroying the zero-allocation invariant of the reference interpreter.
112///
113/// Thus, we split by arity to allow zero-cost static dispatch.
114pub mod registry_architecture {}