//! trident-silicon โ€” nox formula โ†’ native code, one emitter per machine.
//!
//! Sketches, not warriors: every emitter here walks a nox formula tree and
//! writes bytes/text for its machine. None of them executes the result and
//! none produces a trace, so none can be proved โ€” see
//! `trident/.claude/plans/warrior-owns-lowering.md`. Phase 1: atom-only
//! formulas (no cells in output). Subject = cons-list of atoms โ†’ function
//! parameters. Patterns 0,1,4,5-14 supported; 2 (compose), 3 (cons), 15
//! (hash), 16 (call/divine), 17 (look) are refused with
//! `CompileError::UnsupportedPattern`.

use nox::{data::Data as Noun, Order as NounId, Reduction as Order};

pub mod wasm;
pub mod arm64;
pub mod rv32;
pub mod rv64;
pub mod rvv;
pub mod x86_64;
pub mod ebpf;
pub mod ptx;
pub mod tensor_cores;
pub mod wgsl;
pub mod spirv;
pub mod amx;
pub mod ane;
pub mod thumb2;
pub mod hexagon;
pub mod verilog;
pub mod systemverilog;
pub mod vhdl;
pub mod qasm;
pub mod xla;
pub mod qir;
pub mod onnx;
pub mod cerebras;
pub mod upmem;
pub mod intel_amx;

/// Compiled value โ€” either a constant or derived from computation.
/// The compiler walks the formula tree and produces a sequence of
/// typed operations in the target's native format.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompileError {
    /// Pattern not supported in Phase 1 (compose, cons, hash, call, look)
    UnsupportedPattern(u64),
    /// Malformed formula structure
    Malformed,
    /// Axis navigates into non-existent subject position
    AxisError(u64),
    /// Subject has no parameters (axis beyond available params)
    NoParams,
}

/// Resolve nox axis address to parameter index.
///
/// Subject layout: `[argN [argN-1 [... [arg1 0]]]]`
/// - axis 1 = whole subject (not a single param)
/// - axis 2 = head = param 0
/// - axis 6 = head of tail = param 1  (6 = 2*3)
/// - axis 14 = head of tail of tail = param 2 (14 = 2*7)
/// - axis 30 = param 3 (30 = 2*15)
///
/// Pattern: start at axis, walk bits from MSB.
/// Bit 0 = go left (head), bit 1 = go right (tail).
/// The last step must be head (bit 0) to reach an atom param.
pub fn axis_to_param(axis: u64) -> Result<u32, CompileError> {
    if axis < 2 {
        return Err(CompileError::AxisError(axis));
    }
    // Walk the binary representation of axis (skip leading 1)
    let bits = 64 - axis.leading_zeros() - 1; // number of navigation steps
    let mut depth = 0u32;
    for i in (0..bits).rev() {
        let bit = (axis >> i) & 1;
        if bit == 0 {
            // head โ€” this should be the final step for a param access
            if i == 0 {
                return Ok(depth);
            }
            // head then more navigation โ€” nested cell in subject
            // For Phase 1, subject is flat cons-list, so head is always atom
            return Err(CompileError::AxisError(axis));
        } else {
            // tail โ€” go deeper into cons-list
            depth += 1;
        }
    }
    // Reached end without taking head โ€” axis points to tail (the rest of list)
    Err(CompileError::AxisError(axis))
}

/// Extract pattern tag and body from a formula noun.
pub fn formula_parts<const N: usize>(order: &Order<N>, formula: NounId) -> Result<(u64, NounId), CompileError> {
    match order.get(formula).ok_or(CompileError::Malformed)?.inner {
        Noun::Pair { left, right } => {
            match order.atom_value(left) {
                Some(v) => Ok((v.as_u64(), right)),
                None => Err(CompileError::Malformed),
            }
        }
        Noun::Atom { .. } => Err(CompileError::Malformed),
    }
}

/// Extract binary op pair [a b] from body.
pub fn body_pair<const N: usize>(order: &Order<N>, body: NounId) -> Result<(NounId, NounId), CompileError> {
    match order.get(body).ok_or(CompileError::Malformed)?.inner {
        Noun::Pair { left, right } => Ok((left, right)),
        _ => Err(CompileError::Malformed),
    }
}

/// Extract branch triple [test yes no] from body.
pub fn body_triple<const N: usize>(order: &Order<N>, body: NounId) -> Result<(NounId, NounId, NounId), CompileError> {
    let (test, rest) = body_pair(order, body)?;
    let (yes, no) = body_pair(order, rest)?;
    Ok((test, yes, no))
}

/// Get atom value from a noun (for quote literals).
pub fn atom_u64<const N: usize>(order: &Order<N>, r: NounId) -> Result<u64, CompileError> {
    match order.get(r).ok_or(CompileError::Malformed)?.inner {
        Noun::Atom { value, .. } => Ok(value.as_u64()),
        _ => Err(CompileError::Malformed),
    }
}

/// Detect if a formula is a quote of an atom (pattern 1 with atom body).
pub fn is_quote_atom<const N: usize>(order: &Order<N>, formula: NounId) -> Option<u64> {
    let (tag, body) = formula_parts(order, formula).ok()?;
    if tag != 1 { return None; }
    atom_u64(order, body).ok()
}

/// Loop setup compose: `[2 [init_cons [1 loop_body]]]`
/// where init_cons = `[3 [[1 formula] [3 [init0 [3 [init1 ... [0 1]]]]]]]`
/// Returns (loop_body, list of init formulas for carried locals) if this is a loop.
pub fn detect_loop_setup<const N: usize>(
    order: &Order<N>, compose_body: NounId,
) -> Option<(NounId, Vec<NounId>)> {
    let (a, b) = body_pair(order, compose_body).ok()?;
    // B must be [1 body] (quoted)
    let (b_tag, loop_body) = formula_parts(order, b).ok()?;
    if b_tag != 1 { return None; }
    // A must be [3 [[1 formula] cons_tail]]
    let (a_tag, a_body) = formula_parts(order, a).ok()?;
    if a_tag != 3 { return None; }
    let (formula_slot, rest) = body_pair(order, a_body).ok()?;
    // formula_slot must be [1 X] (quoted formula)
    let (fs_tag, _) = formula_parts(order, formula_slot).ok()?;
    if fs_tag != 1 { return None; }
    // rest is a cons chain of init values ending with [0 1]
    let mut inits = Vec::new();
    let mut cur = rest;
    loop {
        let (tag, body) = formula_parts(order, cur).ok()?;
        if tag == 0 { break; } // [0 1] = identity, end of init chain
        if tag != 3 { return None; }
        let (val, tail) = body_pair(order, body).ok()?;
        inits.push(val);
        cur = tail;
    }
    Some((loop_body, inits))
}

/// Back-edge compose: `[2 [new_subj [0 N]]]` โ€” code part is axis (not quoted).
/// Returns (new_subject_formula, axis_number) if this is a back-edge.
pub fn detect_back_edge<const N: usize>(
    order: &Order<N>, compose_body: NounId,
) -> Option<(NounId, u64)> {
    let (a, b) = body_pair(order, compose_body).ok()?;
    let (b_tag, b_body) = formula_parts(order, b).ok()?;
    if b_tag != 0 { return None; } // must be axis
    let axis = atom_u64(order, b_body).ok()?;
    Some((a, axis))
}

/// Extract carried-local init values and count from a loop's init cons chain.
/// Walks the cons chain built by mir2nox: cons(init_last, cons(init..., cons(init_first, params)))
pub fn count_loop_slots(inits: &[NounId]) -> u32 {
    inits.len() as u32
}

#[cfg(test)]
mod tests {
    use super::*;
    use nox::Reduction as Order;
    use nebu::Goldilocks;

    fn g(v: u64) -> Goldilocks { Goldilocks::new(v) }

    /// Helper: build a formula noun in an order from a text-like structure.
    fn make_cell<const N: usize>(order: &mut Order<N>, left: NounId, right: NounId) -> NounId {
        order.pair(left, right).unwrap()
    }
    fn make_atom<const N: usize>(order: &mut Order<N>, v: u64) -> NounId {
        order.atom(g(v)).unwrap()
    }
    /// Build [tag body]
    fn make_formula<const N: usize>(order: &mut Order<N>, tag: u64, body: NounId) -> NounId {
        let t = make_atom(order, tag);
        make_cell(order, t, body)
    }
    /// Build [tag [left right]]
    fn make_binary<const N: usize>(order: &mut Order<N>, tag: u64, left: NounId, right: NounId) -> NounId {
        let body = make_cell(order, left, right);
        make_formula(order, tag, body)
    }

    #[test]
    fn axis_param_mapping() {
        assert_eq!(axis_to_param(2), Ok(0));
        assert_eq!(axis_to_param(6), Ok(1));
        assert_eq!(axis_to_param(14), Ok(2));
        assert_eq!(axis_to_param(30), Ok(3));
        assert_eq!(axis_to_param(62), Ok(4));
    }

    #[test]
    fn axis_errors() {
        assert!(axis_to_param(0).is_err());
        assert!(axis_to_param(1).is_err());
        assert!(axis_to_param(3).is_err());
    }

    #[test]
    fn wasm_quote_compiles() {
        let mut order = Order::<1024>::new();
        let body = make_atom(&mut order, 42);
        let formula = make_formula(&mut order, 1, body);
        let wasm = wasm::compile_to_wasm(&order, formula, 0).unwrap();
        // Valid WASM magic
        assert_eq!(&wasm[0..4], b"\0asm");
        assert!(wasm.len() > 8);
    }

    #[test]
    fn wasm_add_compiles() {
        let mut o = Order::<1024>::new();
        let a3 = make_atom(&mut o, 3);
        let q3 = make_formula(&mut o, 1, a3);
        let a5 = make_atom(&mut o, 5);
        let q5 = make_formula(&mut o, 1, a5);
        let formula = make_binary(&mut o, 5, q3, q5);
        let wasm = wasm::compile_to_wasm(&o, formula, 0).unwrap();
        assert_eq!(&wasm[0..4], b"\0asm");
    }

    #[test]
    fn wasm_axis_param_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 5, a0, a1);
        let wasm = wasm::compile_to_wasm(&o, formula, 2).unwrap();
        assert_eq!(&wasm[0..4], b"\0asm");
    }

    #[test]
    fn wasm_branch_compiles() {
        let mut o = Order::<1024>::new();
        let v0 = make_atom(&mut o, 0);
        let test = make_formula(&mut o, 1, v0);
        let v10 = make_atom(&mut o, 10);
        let yes = make_formula(&mut o, 1, v10);
        let v20 = make_atom(&mut o, 20);
        let no = make_formula(&mut o, 1, v20);
        let yes_no = make_cell(&mut o, yes, no);
        let body = make_cell(&mut o, test, yes_no);
        let formula = make_formula(&mut o, 4, body);
        let wasm = wasm::compile_to_wasm(&o, formula, 0).unwrap();
        assert_eq!(&wasm[0..4], b"\0asm");
    }

    #[test]
    fn wasm_mul_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 7, a0, a1);
        let wasm = wasm::compile_to_wasm(&o, formula, 2).unwrap();
        assert_eq!(&wasm[0..4], b"\0asm");
    }

    #[test]
    fn arm64_add_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 5, a0, a1);
        let code = arm64::compile_to_arm64(&o, formula, 2).unwrap();
        let len = code.len();
        assert!(len >= 4);
        let last4 = u32::from_le_bytes([code[len-4], code[len-3], code[len-2], code[len-1]]);
        assert_eq!(last4, 0xD65F03C0, "should end with RET");
    }

    #[test]
    fn arm64_mul_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 7, a0, a1);
        let code = arm64::compile_to_arm64(&o, formula, 2).unwrap();
        let len = code.len();
        let last4 = u32::from_le_bytes([code[len-4], code[len-3], code[len-2], code[len-1]]);
        assert_eq!(last4, 0xD65F03C0, "should end with RET");
    }

    #[test]
    fn x86_64_add_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 5, a0, a1);
        let code = x86_64::compile_to_x86_64(&o, formula, 2).unwrap();
        // Should end with RET (0xC3)
        assert!(!code.is_empty());
        assert_eq!(*code.last().unwrap(), 0xC3, "should end with RET");
    }

    #[test]
    fn x86_64_mul_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 7, a0, a1);
        let code = x86_64::compile_to_x86_64(&o, formula, 2).unwrap();
        assert_eq!(*code.last().unwrap(), 0xC3, "should end with RET");
    }

    #[test]
    fn rv32_add_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 5, a0, a1);
        let code = rv32::compile_to_rv32(&o, formula, 2).unwrap();
        let len = code.len();
        assert!(len >= 4);
        // Should end with RET = JALR x0, x1, 0 = 0x00008067
        let last4 = u32::from_le_bytes([code[len-4], code[len-3], code[len-2], code[len-1]]);
        assert_eq!(last4, 0x00008067, "should end with RET");
    }

    #[test]
    fn rv64_add_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 5, a0, a1);
        let code = rv64::compile_to_rv64(&o, formula, 2).unwrap();
        let len = code.len();
        assert!(len >= 4);
        // Should end with RET = JALR x0, x1, 0 = 0x00008067
        let last4 = u32::from_le_bytes([code[len-4], code[len-3], code[len-2], code[len-1]]);
        assert_eq!(last4, 0x00008067, "should end with RET");
    }

    #[test]
    fn ebpf_add_compiles() {
        let mut o = Order::<1024>::new();
        let ax2 = make_atom(&mut o, 2);
        let a0 = make_formula(&mut o, 0, ax2);
        let ax6 = make_atom(&mut o, 6);
        let a1 = make_formula(&mut o, 0, ax6);
        let formula = make_binary(&mut o, 5, a0, a1);
        let code = ebpf::compile_to_ebpf(&o, formula, 2).unwrap();
        // Should end with EXIT = 0x95
        let len = code.len();
        assert!(len >= 8);
        let last8 = u64::from_le_bytes(code[len-8..len].try_into().unwrap());
        assert_eq!(last8 & 0xFF, 0x95, "should end with EXIT");
    }

    #[test]
    fn unsupported_pattern_errors() {
        let mut o = Order::<1024>::new();
        let a1 = make_atom(&mut o, 1);
        let body = make_formula(&mut o, 0, a1);
        let formula = make_formula(&mut o, 15, body);
        assert!(matches!(
            wasm::compile_to_wasm(&o, formula, 1),
            Err(CompileError::UnsupportedPattern(15))
        ));
    }
}

Homonyms

soft3/cybergraph/src/lib.rs
soft3/crate/src/lib.rs
soft3/glia/import/lib.rs
warriors/joy/rs/lib.rs
neural/trident/src/lib.rs
cyb/shell/src/lib.rs
warriors/trisha/rs/lib.rs
soft3/nox/rs/lib.rs
soft3/tru/rs/lib.rs
soft3/glia/run/lib.rs
warriors/trisha/honeycrisp/lib.rs
warriors/trisha/wgpu/lib.rs
soft3/mudra/src/lib.rs
soft3/strata/src/lib.rs
cyb/prysm/rs/lib.rs
cyb/honeycrisp/src/lib.rs
soft3/foculus/src/lib.rs
warriors/trisha/neptune/lib.rs
cyb/core/src/lib.rs
soft3/lens/src/lib.rs
cyb/optica/src/lib.rs
soft3/mir/src/lib.rs
soft3/tok/rs/src/lib.rs
neural/rune/rs/ast/lib.rs
soft3/hemera/rs/src/lib.rs
neural/rs/dialect/src/lib.rs
neural/rune/rs/interp/lib.rs
soft3/neuron/rune/src/lib.rs
cyb/honeycrisp/rane/src/lib.rs
soft3/radio/iroh-ffi/src/lib.rs
soft3/zheng/rs/src/lib.rs
soft3/strata/core/src/lib.rs
soft3/lens/ikat/src/lib.rs
neural/rs/mir-format/src/lib.rs
neural/rune/rs/compile/lib.rs
cyb/crates/cyb-reserve/src/lib.rs
soft3/radio/cyber-bao/src/lib.rs
soft3/radio/iroh-willow/src/lib.rs
cyb/crates/cyb/src/lib.rs
neural/rs/link/src/lib.rs
soft3/strata/proof/src/lib.rs
soft3/conformance/rs/src/lib.rs
soft3/neuron/node/src/lib.rs
neural/rune/rs/subject/lib.rs
soft3/radio/iroh-gossip/src/lib.rs
soft3/lens/binius/src/lib.rs
soft3/radio/iroh-blobs/src/lib.rs
neural/rs/codegen/src/lib.rs
soft3/neuron/model/src/lib.rs
neural/rune/rs/mold/lib.rs
neural/rune/rs/parse/lib.rs
neural/eidos/rs/src/lib.rs
neural/rs/macros/src/lib.rs
soft3/bbg/rs/src/lib.rs
soft3/radio/iroh-base/src/lib.rs
cyb/honeycrisp/unimem/src/lib.rs
soft3/neuron/engine/src/lib.rs
soft3/radio/iroh/src/lib.rs
soft3/radio/iroh-docs/src/lib.rs
soft3/radio/iroh-relay/src/lib.rs
neural/rs/sigil/src/lib.rs
soft3/lens/brakedown/src/lib.rs
neural/rune/rs/prysm/lib.rs
cyb/honeycrisp/aruminium/src/lib.rs
soft3/strata/kuro/rs/lib.rs
neural/rune/rs/parse-pure/lib.rs
soft3/lens/porphyry/src/lib.rs
cyb/honeycrisp/acpu/src/lib.rs
neural/rune/rs/lower/lib.rs
soft3/lens/assayer/src/lib.rs
soft3/radio/iroh-car/src/lib.rs
soft3/lens/core/src/lib.rs
soft3/hemera/wgsl/src/lib.rs
soft3/strata/ext/src/lib.rs
soft3/strata/nebu/rs/lib.rs
neural/rs/darwin-sys/src/lib.rs
neural/rune/rs/lex/lib.rs
soft3/strata/compute/src/lib.rs
neural/rs/core/src/lib.rs
soft3/radio/iroh-dns-server/src/lib.rs
soft3/radio/quinn/bench/src/lib.rs
cyb/evy/forks/bevy_tasks/src/lib.rs
soft3/radio/nettools/netwatch/src/lib.rs
soft3/lytics/rs/event/src/lib.rs
neural/inf/rs/plan/src/lib.rs
cyb/evy/crates/evy_engine_dispatch/src/lib.rs
cyb/evy/crates/evy_engine_core/src/lib.rs
soft3/strata/kuro/wgsl/src/lib.rs
soft3/radio/quinn/quinn-udp/src/lib.rs
cyb/wysm/crates/wasi/src/lib.rs
cyb/evy/forks/bevy_diagnostic/src/lib.rs
cyb/evy/forks/naga/src/lib.rs
warriors/erga/rs/mine-bench/src/lib.rs
soft3/radio/quinn/quinn-proto/src/lib.rs
cyb/evy/crates/evy_platform_caps/src/lib.rs
cyb/wysm/crates/wasmi/src/lib.rs
cyb/evy/crates/evy_engine_tasks/src/lib.rs
warriors/erga/rs/wallet/src/lib.rs
neural/inf/rs/eval/src/lib.rs
soft3/radio/tests/integration/src/lib.rs
cyb/evy/forks/bevy_image/src/lib.rs
neural/inf/rs/parse/src/lib.rs
soft3/strata/genies/wgsl/src/lib.rs
cyb/evy/crates/evy_prysm_core/src/lib.rs
cyb/evy/forks/bevy_sprite/src/lib.rs
neural/inf/rs/lex/src/lib.rs
soft3/strata/jali/rs/src/lib.rs
neural/inf/rs/source/src/lib.rs
cyb/evy/forks/bevy_core_pipeline/src/lib.rs
cyb/evy/forks/bevy_mesh/src/lib.rs
soft3/strata/genies/rs/src/lib.rs
cyb/wysm/crates/c_api/src/lib.rs
cyb/evy/forks/bevy_transform/src/lib.rs
cyb/wysm/crates/fuzz/src/lib.rs
soft3/radio/nettools/portmapper/src/lib.rs
neural/rs/tests/macro-integration/src/lib.rs
neural/inf/rs/lower/src/lib.rs
cyb/evy/forks/bevy_render/src/lib.rs
cyb/wysm/crates/ir/src/lib.rs
cyb/evy/forks/bevy_ecs/src/lib.rs
cyb/wysm/crates/wast/src/lib.rs
cyb/evy/forks/bevy_animation/src/lib.rs
cyb/wysm/crates/core/src/lib.rs
warriors/erga/rs/rtable-bench/src/lib.rs
cyb/evy/forks/bevy_post_process/src/lib.rs
soft3/strata/jali/wgsl/src/lib.rs
soft3/radio/quinn/quinn/src/lib.rs
soft3/tade/impl/rust/src/lib.rs
soft3/strata/trop/rs/src/lib.rs
cyb/wysm/crates/c_api/artifact/lib.rs
neural/inf/rs/value/src/lib.rs
cyb/evy/crates/evy_dialect/src/lib.rs
warriors/erga/rs/autolykos/src/lib.rs
warriors/erga/rs/app/src/lib.rs
neural/trident/editor/zed/src/lib.rs
warriors/erga/rs/blake-bench/src/lib.rs
cyb/evy/crates/evy_diagnostic/src/lib.rs
cyb/evy/forks/bevy_anti_alias/src/lib.rs
soft3/lytics/rs/core/src/lib.rs
soft3/radio/iroh-ffi/iroh-js/src/lib.rs
neural/inf/rs/oracle/src/lib.rs
cyb/evy/crates/evy_ecs_storage/src/lib.rs
soft3/radio/quinn/perf/src/lib.rs
cyb/evy/crates/evy_radio/src/lib.rs
cyb/evy/forks/bevy_pbr/src/lib.rs
warriors/erga/rs/miner/src/lib.rs
cyb/evy/forks/bevy_gizmos_render/src/lib.rs
soft3/strata/nebu/wgsl/src/lib.rs
soft3/radio/iroh/bench/src/lib.rs
cyb/wysm/crates/collections/src/lib.rs
warriors/erga/rs/pool/src/lib.rs
soft3/strata/trop/wgsl/src/lib.rs
cyb/evy/forks/bevy_sprite_render/src/lib.rs
cyb/wysm/crates/c_api/macro/lib.rs
cyb/evy/forks/bevy_gizmos/src/lib.rs
neural/inf/rs/ast/src/lib.rs

Graph