alpaca_ir 0.0.1

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

use crate::program::AlpacaProgram;

use crate::exprs::prelude::*;

/// ```AlpacaBuilder``` is an abstraction of ```AlpacaProgram```
pub struct AlpacaBuilder {
    program: AlpacaProgram,
    pointer: Option<Rc<RefCell<AlpacaBasicBlock>>>,
}

impl AlpacaBuilder {
    pub fn new() -> Self {
        Self {
            program: AlpacaProgram::new(),
            pointer: None,
        }
    }

    /// Creates a new function & returns ```AlpacaFunctionBuilder```
    pub fn create_function(
        &mut self,
        name: &'static str,
        ty: AlpacaBasicType,
    ) -> AlpacaFunctionBuilder {
        let function_index = self.program.add_func(AlpacaFunction {
            name,
            ty,
            body: Vec::new(),
        });
        AlpacaFunctionBuilder::new(self.program[function_index].clone())
    }

    /// Sets the pointer to the given block, used mainly for
    /// the ```add_instruction``` function
    pub fn set_pointer(&mut self, block: Option<Rc<RefCell<AlpacaBasicBlock>>>) {
        self.pointer = block;
    }

    /// Adds an ```AlpacaInst``` to a block, that the pointer is looking at
    pub fn add_instruction(&mut self, inst: AlpacaInst) {
        if let Some(block) = &self.pointer {
            let mut block = block.borrow_mut();
            block.insts.push(inst);
        } else {
            log::error!("pointer is not set!");
        }
    }

    /// Gives you the program, then drops ```AlpacaBuilder```
    pub fn get_program(self) -> AlpacaProgram {
        self.program
    }
}

/// ```AlpacaFunctionBuilder``` abstracts the process
/// of setting up a function
pub struct AlpacaFunctionBuilder {
    function: Rc<RefCell<AlpacaFunction>>,
}

impl AlpacaFunctionBuilder {
    fn new(function: Rc<RefCell<AlpacaFunction>>) -> Self {
        Self { function }
    }

    /// Pretty self-explanatory; It creates a new block
    pub fn add_block(&mut self, name: &'static str) -> Rc<RefCell<AlpacaBasicBlock>> {
        let mut function = self.function.borrow_mut();

        let block = Rc::new(RefCell::new(AlpacaBasicBlock {
            name,
            insts: Vec::new(),
        }));

        function.body.push(block.clone());

        block
    }
}