Skip to main content

vyre_primitives/predicate/
node_kind_eq.rs

1//! `node_kind_eq`  -  `NodeSet = { v : nodes[v] == kind }`.
2
3use vyre_foundation::ir::Program;
4
5#[cfg(any(test, feature = "cpu-parity"))]
6use crate::nodeset_filter::{nodeset_filter_cpu_ref, nodeset_filter_cpu_ref_into};
7use crate::nodeset_filter::{nodeset_filter_program, NodeSetFilter};
8
9/// Canonical op id.
10pub const OP_ID: &str = "vyre-primitives::predicate::node_kind_eq";
11
12/// Build a Program: `NodeSet = { v : nodes[v] == kind }`.
13#[must_use]
14pub fn node_kind_eq(nodes: &str, nodeset_out: &str, node_count: u32, kind: u32) -> Program {
15    node_kind_eq_with_op_id(OP_ID, nodes, nodeset_out, node_count, kind)
16}
17
18/// Build a node-kind predicate Program under a caller-owned op id.
19#[must_use]
20pub(crate) fn node_kind_eq_with_op_id(
21    op_id: &'static str,
22    nodes: &str,
23    nodeset_out: &str,
24    node_count: u32,
25    kind: u32,
26) -> Program {
27    nodeset_filter_program(
28        op_id,
29        nodes,
30        nodeset_out,
31        node_count,
32        NodeSetFilter::Eq(kind),
33    )
34}
35
36/// CPU reference.
37#[must_use]
38#[cfg(any(test, feature = "cpu-parity"))]
39pub fn cpu_ref(nodes: &[u32], kind: u32) -> Vec<u32> {
40    nodeset_filter_cpu_ref(nodes, NodeSetFilter::Eq(kind))
41}
42
43/// CPU reference using a caller-owned nodeset bitset.
44#[cfg(any(test, feature = "cpu-parity"))]
45pub fn cpu_ref_into(nodes: &[u32], kind: u32, out: &mut Vec<u32>) {
46    nodeset_filter_cpu_ref_into(nodes, NodeSetFilter::Eq(kind), out);
47}
48
49#[cfg(feature = "inventory-registry")]
50inventory::submit! {
51    vyre_foundation::operation::OperationRegistration::primitive(
52        OP_ID,
53        || node_kind_eq("nodes", "nodeset", 4, crate::predicate::node_kind::CALL),
54        Some(|| {
55            let to_bytes = |w: &[u32]| crate::wire::pack_u32_slice(w);
56            vec![vec![
57                to_bytes(&[2, 1, 2, 4]), // nodes: CALL, VARIABLE, CALL, LITERAL
58                to_bytes(&[0]),          // nodeset_out
59            ]]
60        }),
61        Some(|| {
62            let to_bytes = |w: &[u32]| crate::wire::pack_u32_slice(w);
63            vec![vec![to_bytes(&[0b0101])]] // nodes 0 and 2 (CALL)
64        }),
65    )
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use crate::predicate::node_kind;
72
73    #[test]
74    fn filters_by_kind() {
75        let got = cpu_ref(
76            &[
77                node_kind::CALL,
78                node_kind::VARIABLE,
79                node_kind::CALL,
80                node_kind::LITERAL,
81            ],
82            node_kind::CALL,
83        );
84        assert_eq!(got, vec![0b0101]);
85    }
86
87    #[test]
88    fn cpu_ref_into_reuses_nodeset_buffer() {
89        let mut out = Vec::with_capacity(4);
90        let ptr = out.as_ptr();
91        cpu_ref_into(
92            &[
93                node_kind::CALL,
94                node_kind::VARIABLE,
95                node_kind::CALL,
96                node_kind::LITERAL,
97            ],
98            node_kind::CALL,
99            &mut out,
100        );
101        assert_eq!(out, vec![0b0101]);
102        assert_eq!(out.as_ptr(), ptr);
103    }
104}