use alloc::boxed::Box;
use core::marker::PhantomData;
use crate::isa::{Instr, InstructionSet, ReservedOp};
use crate::library::LibSite;
use crate::reg::CoreRegs;
use crate::Program;
#[derive(Debug, Default)]
pub struct Vm<Isa = Instr<ReservedOp>>
where
Isa: InstructionSet,
{
pub registers: Box<CoreRegs>,
phantom: PhantomData<Isa>,
}
impl<Isa> Vm<Isa>
where
Isa: InstructionSet,
{
pub fn new() -> Self { Self { registers: Box::default(), phantom: Default::default() } }
pub fn run(&mut self, program: &impl Program<Isa = Isa>, context: &Isa::Context<'_>) -> bool {
self.call(program, program.entrypoint(), context)
}
pub fn call(
&mut self,
program: &impl Program<Isa = Isa>,
method: LibSite,
context: &Isa::Context<'_>,
) -> bool {
let mut call = Some(method);
while let Some(ref mut site) = call {
if let Some(lib) = program.lib(site.lib) {
call = lib.exec::<Isa>(site.pos, &mut self.registers, context);
} else if let Some(pos) = site.pos.checked_add(1) {
site.pos = pos;
} else {
call = None;
};
}
self.registers.st0
}
}