ellie_vm 0.6.5

Ellie VM for running Ellie ByteCode
Documentation
use crate::raw_type::{MutatableRawType, RawType};
use alloc::{
    boxed::Box,
    collections::BTreeMap,
    format,
    string::{String, ToString},
    vec::Vec,
};

pub type HeapOutOfMemoryCallback = Box<dyn FnMut()>;

pub struct HeapMemory {
    pub data: BTreeMap<usize, Vec<u8>>,
    pub on_heap_out_of_memory: Option<HeapOutOfMemoryCallback>,
}

impl Clone for HeapMemory {
    fn clone(&self) -> Self {
        HeapMemory {
            data: self.data.clone(),
            on_heap_out_of_memory: None,
        }
    }
}

impl Default for HeapMemory {
    fn default() -> Self {
        Self::new()
    }
}

impl HeapMemory {
    pub fn new() -> HeapMemory {
        HeapMemory {
            data: BTreeMap::new(),
            on_heap_out_of_memory: None,
        }
    }

    pub fn set_on_heap_out_of_memory(&mut self, callback: HeapOutOfMemoryCallback) {
        self.on_heap_out_of_memory = Some(callback);
    }

    pub fn get_mut(&mut self, key: &usize) -> Option<MutatableRawType> {
        self.data.get_mut(key).map(|data| MutatableRawType { data })
    }

    pub fn get(&self, key: &usize) -> Option<RawType> {
        self.data.get(key).map(|data| RawType::from_bytes(data))
    }

    pub fn get_def(&self, key: &usize) -> Option<RawType> {
        match self.get(key) {
            Some(e) => {
                if e.type_id.id == 13 {
                    self.get_def(&(e.to_int() as usize))
                } else {
                    Some(e)
                }
            }
            None => None,
        }
    }

    pub fn set(&mut self, key: &usize, value: RawType) {
        self.data.insert(*key, value.to_bytes());
    }

    pub fn dea(&mut self, key: &usize) {
        self.data.remove(key);
    }

    pub fn dump(&self) -> String {
        let mut result = String::new();
        for key in &self.data {
            let value = self.get(key.0).unwrap();
            result.push_str(&format!(
                "{} : {} = {:?} =! {:?}\n",
                key.0,
                value.type_id,
                match value.type_id.id {
                    1 => {
                        isize::from_le_bytes(value.data.clone().try_into().unwrap()).to_string()
                    }
                    2 => {
                        f32::from_le_bytes(value.data.clone().try_into().unwrap()).to_string()
                    }
                    3 => {
                        f64::from_le_bytes(value.data.clone().try_into().unwrap()).to_string()
                    }
                    4 => {
                        u8::from_le_bytes(value.data.clone().try_into().unwrap()).to_string()
                    }
                    5 => {
                        (value.data[0] == 1).to_string()
                    }
                    6 => {
                        let mut new_string = String::new();
                        for i in value.data.chunks(4) {
                            let char = u32::from_le_bytes(i.try_into().unwrap());
                            new_string.push(char::from_u32(char).unwrap());
                        }
                        new_string
                    }
                    7 => value.to_char().to_string(),
                    8 => String::from("void"),
                    9 => String::from("arr"),
                    10 => String::from("null"),
                    11 => String::from("class"),
                    12 => String::from("function"),
                    13 => String::from("stack_reference"),
                    14 => String::from("heap_reference"),
                    _ => unreachable!("Wrong typeid"),
                },
                value.data,
            ));
        }
        result
    }
}