alpaca_ir 0.0.1

AlpacaIR is a intermediate represenation meant to make making compilers easier.
Documentation
use std::{cell::RefCell, rc::Rc};
use std::ops::Index;

use index_vec::{Idx, IndexVec};

use crate::exprs::core::{AlpacaBasicBlock, AlpacaFunction};

#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct AlpacaProgramIndex {
    index: usize,
}

impl Idx for AlpacaProgramIndex {
    fn index(self) -> usize { self.index }
    
    fn from_usize(idx: usize) -> Self {
        Self { index: idx, }
    }
}

/// ```AlpacaProgram``` is the container of the program, recommended
/// to use ```AlpacaBuilder``` for a more abstracted way
#[derive(Debug)]
pub struct AlpacaProgram {
    program: IndexVec<AlpacaProgramIndex, Rc<RefCell<AlpacaFunction>>>,
}

impl Index<AlpacaProgramIndex> for AlpacaProgram {
    type Output = Rc<RefCell<AlpacaFunction>>;
    
    fn index(&self, index: AlpacaProgramIndex) -> &Self::Output { &self.program[index] }
}

impl AlpacaProgram {
    pub fn new() -> Self {
        Self { program: IndexVec::new() }
    }
    
    pub fn add_func(&mut self, expr: AlpacaFunction) -> AlpacaProgramIndex { self.program.push(Rc::new(RefCell::new(expr))) }
    pub fn get_functions(&self) -> impl Iterator<Item = &Rc<RefCell<AlpacaFunction>>> { self.program.iter() }
    pub fn find_function(&self, name: &str) -> Option<AlpacaProgramIndex> {
        self.program.iter().position(|func| func.borrow().name == name).map(AlpacaProgramIndex::from_usize)
    }
    
    pub fn get_blocks_ref(&self, func: AlpacaProgramIndex) -> Vec<Rc<RefCell<AlpacaBasicBlock>>> {
        self.program[func].borrow().body.clone()
    }
    
    pub fn get_blocks_mut(&self, func: AlpacaProgramIndex) -> Vec<Rc<RefCell<AlpacaBasicBlock>>> {
        self.program[func].borrow_mut().body.clone()
    }
    
    pub fn remove(&mut self, index: AlpacaProgramIndex) -> Rc<RefCell<AlpacaFunction>> { self.program.remove(index) }
    
    pub fn swap(&mut self, index1: AlpacaProgramIndex, index2: AlpacaProgramIndex) {
        let temp = self.program[index1].clone();
        self.program[index1] = self.program[index2].clone();
        self.program[index2] = temp;
    }
}