use std::alloc::{self, Layout};
use vera_prim_macro::prim;
use crate as nova_interpreter;
use crate::utils::PrimitiveFn;
use crate::utils::interner::Interner;
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))
}
}
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) }
},
()
);
}