nova-interpreter 0.1.1

An interpreter library for the nova language
Documentation
use std::alloc::{self, Layout};

use vera_prim_macro::prim;

use crate as nova_interpreter;
use crate::utils::PrimitiveFn;

use crate::utils::interner::Interner;

/// A wrapper for a `Vec` of builtins so that functions
/// can be added to it
pub struct Builtins<'a> {
    pub builtins: &'a mut Vec<(Box<[usize]>, PrimitiveFn)>,
}

impl<'a> Builtins<'a> {
    pub fn new(builtins: &'a mut Vec<(Box<[usize]>, PrimitiveFn)>) -> Self {
        Builtins { builtins }
    }

    pub fn add_builtin(&mut self, conditions: Vec<usize>, prim: PrimitiveFn) {
        self.builtins.push((conditions.into_boxed_slice(), prim))
    }
}

/// Add the memory manipulation builtins to the passed in builtins object
pub fn add_memory_manipulation_builtins(interner: &mut Interner<String>, builtins: &mut Builtins) {
    prim!(
        mem_alloc,
        |mem_bytes| {
            let bytes = mem_bytes;
            let layout_size = size_of::<Layout>();

            let layout = Layout::from_size_align(bytes + layout_size, 8).unwrap();
            let mem = unsafe { alloc::alloc(layout) };

            unsafe { *(mem as *mut Layout) = layout };

            (mem as usize + layout_size,)
        },
        (mem_pointer,)
    );

    prim!(
        mem_write,
        |mem_value, mem_pointer| {
            unsafe { *(mem_pointer as *mut u8) = mem_value as u8 };
        },
        ()
    );

    prim!(
        mem_read,
        |mem_pointer| { (unsafe { *(mem_pointer as *mut u8) as usize },) },
        (mem_value,)
    );

    prim!(
        mem_copy,
        |mem_src, mem_dest, mem_bytes| unsafe {
            std::ptr::copy_nonoverlapping(mem_src as *mut u8, mem_dest as *mut u8, mem_bytes)
        },
        ()
    );

    prim!(
        mem_free,
        |mem_pointer| {
            let layout_size = size_of::<Layout>();

            let ptr = (mem_pointer - layout_size) as *mut u8;
            let layout = unsafe { *(ptr as *mut Layout) };
            unsafe { alloc::dealloc(ptr, layout) }
        },
        ()
    );
}