rue-lir 0.10.0

Provides a low-level intermediate representation that compiles to CLVM.
Documentation
use clvm_traits::{ToClvm, ToClvmError};
use clvmr::{Allocator, NodePtr};
use id_arena::Id;
use num_bigint::BigUint;

use crate::bigint_atom;

pub type LirId = Id<Lir>;

#[derive(Debug, Clone)]
pub enum Lir {
    Atom(Vec<u8>),
    Path(BigUint),
    Quote(LirId),
    Run(LirId, LirId),
    Closure(LirId, Vec<LirId>, bool),
    First(LirId),
    Rest(LirId),
    Cons(LirId, LirId),
    Listp(LirId, bool),
    Add(Vec<LirId>),
    Sub(Vec<LirId>),
    Mul(Vec<LirId>),
    Div(LirId, LirId),
    Divmod(LirId, LirId),
    Mod(LirId, LirId),
    Modpow(LirId, LirId, LirId),
    Eq(LirId, LirId),
    Gt(LirId, LirId),
    GtBytes(LirId, LirId),
    Not(LirId),
    All(Vec<LirId>),
    Any(Vec<LirId>),
    If(LirId, LirId, LirId, bool),
    Raise(Vec<LirId>),
    Concat(Vec<LirId>),
    Strlen(LirId),
    Substr(LirId, LirId, Option<LirId>),
    Logand(Vec<LirId>),
    Logior(Vec<LirId>),
    Logxor(Vec<LirId>),
    Lognot(LirId),
    Ash(LirId, LirId),
    Lsh(LirId, LirId),
    PubkeyForExp(LirId),
    G1Add(Vec<LirId>),
    G1Subtract(Vec<LirId>),
    G1Multiply(LirId, LirId),
    G1Negate(LirId),
    G1Map(LirId, Option<LirId>),
    G2Add(Vec<LirId>),
    G2Subtract(Vec<LirId>),
    G2Multiply(LirId, LirId),
    G2Negate(LirId),
    G2Map(LirId, Option<LirId>),
    BlsPairingIdentity(Vec<LirId>),
    BlsVerify(LirId, Vec<LirId>),
    Sha256(Vec<LirId>),
    Sha256Inline(Vec<LirId>),
    Keccak256(Vec<LirId>),
    Keccak256Inline(Vec<LirId>),
    CoinId(LirId, LirId, LirId),
    K1Verify(LirId, LirId, LirId),
    R1Verify(LirId, LirId, LirId),
    Op(ClvmOp, LirId),
    DebugPrint(String, LirId),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ClvmOp {
    Quote,
    Apply,
    If,
    Cons,
    First,
    Rest,
    Listp,
    Raise,
    Eq,
    GtBytes,
    Sha256,
    Substr,
    Strlen,
    Concat,
    Add,
    Sub,
    Mul,
    Div,
    Divmod,
    Gt,
    Ash,
    Lsh,
    Logand,
    Logior,
    Logxor,
    Lognot,
    Not,
    Any,
    All,
    Modpow,
    Mod,
    CoinId,
    PubkeyForExp,
    G1Add,
    G1Subtract,
    G1Multiply,
    G1Negate,
    G2Add,
    G2Subtract,
    G2Multiply,
    G2Negate,
    G1Map,
    G2Map,
    BlsPairingIdentity,
    BlsVerify,
    Secp256K1Verify,
    Secp256R1Verify,
    Keccak256,

    // Non-standard
    DebugPrint,
}

impl ClvmOp {
    pub fn to_atom(self) -> Vec<u8> {
        let num = match self {
            Self::Quote => 1,
            Self::Apply => 2,
            Self::If => 3,
            Self::Cons => 4,
            Self::First => 5,
            Self::Rest => 6,
            Self::Listp => 7,
            Self::Raise => 8,
            Self::Eq => 9,
            Self::GtBytes => 10,
            Self::Sha256 => 11,
            Self::Substr => 12,
            Self::Strlen => 13,
            Self::Concat => 14,
            Self::Add => 16,
            Self::Sub => 17,
            Self::Mul => 18,
            Self::Div => 19,
            Self::Divmod => 20,
            Self::Gt => 21,
            Self::Ash => 22,
            Self::Lsh => 23,
            Self::Logand => 24,
            Self::Logior => 25,
            Self::Logxor => 26,
            Self::Lognot => 27,
            Self::Not => 32,
            Self::Any => 33,
            Self::All => 34,
            Self::Modpow => 60,
            Self::Mod => 61,
            Self::PubkeyForExp => 30,
            Self::CoinId => 48,
            Self::G1Add => 29,
            Self::G1Subtract => 49,
            Self::G1Multiply => 50,
            Self::G1Negate => 51,
            Self::G2Add => 52,
            Self::G2Subtract => 53,
            Self::G2Multiply => 54,
            Self::G2Negate => 55,
            Self::G1Map => 56,
            Self::G2Map => 57,
            Self::BlsPairingIdentity => 58,
            Self::BlsVerify => 59,
            Self::Secp256K1Verify => return vec![0x13, 0xd6, 0x1f, 0x00],
            Self::Secp256R1Verify => return vec![0x1c, 0x3a, 0x8f, 0x00],
            Self::Keccak256 => 62,
            Self::DebugPrint => return b"debug_print".into(),
        };

        bigint_atom(num.into())
    }
}

impl ToClvm<Allocator> for ClvmOp {
    fn to_clvm(&self, encoder: &mut Allocator) -> Result<NodePtr, ToClvmError> {
        encoder
            .new_atom(&self.to_atom())
            .map_err(|_| ToClvmError::OutOfMemory)
    }
}