rue-lir 0.7.0

Provides a low-level intermediate representation that compiles to CLVM.
Documentation
use id_arena::Arena;

use crate::{Lir, LirId, optimize::optimize};

pub fn opt_truthy(arena: &mut Arena<Lir>, value: LirId) -> Result<bool, LirId> {
    match arena[value].clone() {
        Lir::Atom(atom) => Ok(!atom.is_empty()),
        Lir::Cons(..) => Ok(true),
        Lir::Listp(inner, atom_can_be_truthy) => {
            if atom_can_be_truthy {
                Err(value)
            } else {
                opt_truthy(arena, inner)
            }
        }
        Lir::Not(inner) => {
            if let Lir::Eq(left, right) = arena[inner].clone() {
                if let Lir::Atom(left) = arena[left].clone()
                    && left.is_empty()
                {
                    return Err(right);
                }

                if let Lir::Atom(right) = arena[right].clone()
                    && right.is_empty()
                {
                    return Err(left);
                }
            }

            Err(value)
        }
        Lir::Eq(left, right) => {
            if let Lir::Atom(left) = arena[left].clone()
                && left.is_empty()
            {
                let not = arena.alloc(Lir::Not(right));
                let not = optimize(arena, not);
                return opt_truthy(arena, not);
            }

            if let Lir::Atom(right) = arena[right].clone()
                && right.is_empty()
            {
                let not = arena.alloc(Lir::Not(left));
                let not = optimize(arena, not);
                return opt_truthy(arena, not);
            }

            Err(value)
        }
        _ => Err(value),
    }
}