use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
use crate::{
compiler::compiled_code::CompiledCode,
compiler::{compiled_code::Symbol, graph::Graph, Compiler},
};
use super::registry::VM_REGISTRY;
pub struct VirtualMachine {
pub(crate) registry_index: usize,
pub(crate) compiler: Compiler,
uncompiled_functions: Mutex<HashMap<Symbol, Box<Graph>>>,
symbol_resolver: Mutex<Option<Box<dyn Fn(&Symbol) + Sync + Send>>>,
}
impl VirtualMachine {
pub fn new() -> Arc<Self> {
crate::init_logger();
VM_REGISTRY.add(Self {
registry_index: 0,
compiler: Compiler::new(),
uncompiled_functions: Mutex::new(HashMap::new()),
symbol_resolver: Mutex::new(None),
})
}
pub fn set_symbol_resolver(&self, resolver: Box<dyn Fn(&Symbol) + Sync + Send>) {
*self.symbol_resolver.lock().unwrap() = Some(resolver);
}
pub fn contains(&self, name: &Symbol) -> bool {
if self.uncompiled_functions.lock().unwrap().contains_key(name) {
return true;
}
self.compiler.contains(name)
}
pub fn add(&self, name: Symbol, graph: Box<Graph>) {
self.uncompiled_functions
.lock()
.unwrap()
.insert(name, graph);
}
fn compile(&self, name: &Symbol) {
let mut uncompiled_functions = self.uncompiled_functions.lock().unwrap();
if let Some(graph) = uncompiled_functions.remove(name) {
std::mem::drop(uncompiled_functions);
self.compiler.compile(name.to_owned(), graph);
}
}
pub fn resolve(&self, name: &Symbol) -> Arc<dyn CompiledCode> {
if !self.compiler.contains(name) {
let resolver = self.symbol_resolver.lock().unwrap();
if let Some(f) = resolver.as_ref() {
f(name);
}
}
self.compile(name);
self.compiler.get(name)
}
pub fn get_instance_by_code_interior_pointer(ptr: *const u8) -> Option<Arc<Self>> {
VM_REGISTRY.get_vm_by_code_interior_pointer(ptr)
}
pub fn get_compiled_code_by_code_interior_pointer(
&self,
ptr: *const u8,
) -> Option<&dyn CompiledCode> {
self.compiler.code.get_code_by_interior_pointer(ptr)
}
}