use super::ffi;
use super::host;
use super::mem;
use super::parent;
use mtk::result;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct VM {
pub(crate) mstack: mem::MemStack,
pub(crate) bstack: mem::ByteStack,
pub(crate) flag: ffi::ULong,
pub(crate) instances: Vec<VM>,
pub(crate) def: Box<[ffi::Byte]>,
pub(crate) regset: Box<[ffi::ULong]>,
pub(crate) parent: parent::Parent,
pub(crate) refpool: Vec<ffi::Ref>,
pub(crate) run: bool,
}
impl VM {
pub fn new() -> Self {
VM {
mstack: mem::MemStack::new(),
bstack: mem::ByteStack::new(),
flag: 0,
instances: Vec::new(),
def: Box::new([0; 0]),
regset: Box::new([0; 8 * 256]),
parent: parent::Parent::from_host(&host::Host::connect()),
refpool: Vec::new(),
run: false,
}
}
pub fn as_child(parent: &mut VM) -> Self {
VM {
mstack: mem::MemStack::new(),
bstack: mem::ByteStack::new(),
flag: 0,
instances: Vec::new(),
def: Box::new([0; 0]),
regset: Box::new([0; 8 * 256]),
parent: parent::Parent::from_vm(parent),
refpool: Vec::new(),
run: false,
}
}
pub fn with_def(def: &[ffi::Byte]) -> Self {
VM {
mstack: mem::MemStack::new(),
bstack: mem::ByteStack::new(),
flag: 0,
instances: Vec::new(),
def: def.to_vec().into_boxed_slice(),
regset: Box::new([0; 8 * 256]),
parent: parent::Parent::from_host(&host::Host::connect()),
refpool: Vec::new(),
run: false,
}
}
pub fn with_def_as_child(def: &[ffi::Byte], parent: &mut VM) -> Self {
VM {
mstack: mem::MemStack::new(),
bstack: mem::ByteStack::new(),
flag: 0,
instances: Vec::new(),
def: def.to_vec().into_boxed_slice(),
regset: Box::new([0; 8 * 256]),
parent: parent::Parent::from_vm(parent),
refpool: Vec::new(),
run: false,
}
}
pub fn load(&mut self, def: &[ffi::Byte]) {
self.def = def.to_vec().into_boxed_slice();
}
pub fn start(&mut self) -> result::Result<Result<ffi::Byte, ffi::Err>> {
let mut clock = 0;
while self.run && clock < self.def.len() {
if self.def[clock] == ffi::exit() {
return Ok(Ok(self.def[clock + 1]));
} else if self.def[clock] == ffi::throw() {
return Ok(Err(self.def[clock + 1]));
} else if self.def[clock] == ffi::alloc() {
let mut bytes: Vec<ffi::Byte> = Vec::new();
for _ in clock..clock + 8 {
bytes.push(self.def[clock]);
clock += 1;
}
let size = match mtk::bytemerge::bytemerge(&bytes) {
Ok(ok) => ok as usize,
Err(err) => return err.to_err(),
};
self.refpool.push(match self.mstack.alloc(size) {
Ok(ok) => ok,
Err(err) => return err.to_err(),
});
} else if self.def[clock] == ffi::dealloc() {
let mut bytes: Vec<ffi::Byte> = Vec::new();
for _ in clock..clock + 8 {
bytes.push(self.def[clock]);
clock += 1;
}
let ref_ = match mtk::bytemerge::bytemerge(&bytes) {
Ok(ok) => ok as ffi::Ref,
Err(err) => return err.to_err(),
};
self.regset[ffi::CARRY] = match self.mstack.dealloc(ref_) {
Ok(ok) => ok as ffi::ULong,
Err(err) => return err.to_err(),
};
} else if self.def[clock] == ffi::push() {
clock += 1;
let byte = self.def[clock];
self.bstack.push(byte);
} else if self.def[clock] == ffi::pop() {
self.regset[ffi::CARRY] = match self.bstack.pop() {
Some(some) => some as ffi::ULong,
None => return result::Error::quick("could not pop from byte stack"),
};
} else if self.def[clock] == ffi::vmcreate() {
let mut vm = VM::new();
let mut def = Vec::new();
let mut bytes: Vec<ffi::Byte> = Vec::new();
for _ in clock..clock + 8 {
bytes.push(self.def[clock]);
clock += 1;
}
let def_size = match mtk::bytemerge::bytemerge(&bytes) {
Ok(ok) => ok as ffi::Ref,
Err(err) => return err.to_err(),
};
for _ in clock..clock + def_size as usize {
def.push(self.def[clock]);
clock += 1;
}
vm.load(&def);
self.instances.push(vm.clone());
self.regset[ffi::CARRY] = (self.instances.len() - 1) as ffi::ULong;
} else if self.def[clock] == ffi::vmstart() {
let mut bytes: Vec<ffi::Byte> = Vec::new();
for _ in clock..clock + 8 {
bytes.push(self.def[clock]);
clock += 1;
}
let vm_index = match mtk::bytemerge::bytemerge(&bytes) {
Ok(ok) => ok as usize,
Err(err) => return err.to_err(),
};
self.regset[ffi::CARRY] = match self.instances[vm_index].start() {
Ok(ok) => match ok {
Ok(ok) => ok as ffi::ULong,
Err(err) => {
self.regset[ffi::ERROR] = err as ffi::ULong;
0xFFFFFFFF
}
},
Err(err) => return err.to_err(),
};
} else if self.def[clock] == ffi::vmdestroy() {
let mut bytes: Vec<ffi::Byte> = Vec::new();
for _ in clock..clock + 8 {
bytes.push(self.def[clock]);
clock += 1;
}
let vm_index = match mtk::bytemerge::bytemerge(&bytes) {
Ok(ok) => ok as usize,
Err(err) => return err.to_err(),
};
self.instances[vm_index].stop();
} else if self.def[clock] == ffi::vmload() {
let mut bytes: Vec<ffi::Byte> = Vec::new();
for _ in clock..clock + 8 {
bytes.push(self.def[clock]);
clock += 1;
}
let vm_index = match mtk::bytemerge::bytemerge(&bytes) {
Ok(ok) => ok as usize,
Err(err) => return err.to_err(),
};
let mut def = Vec::new();
for _ in clock..clock + 8 {
def.push(self.def[clock]);
clock += 1;
}
let _def_size = match mtk::bytemerge::bytemerge(&def) {
Ok(ok) => ok as ffi::Ref,
Err(err) => return err.to_err(),
};
self.instances[vm_index].load(&def);
} else {
clock += 1;
}
}
Ok(Err(1))
}
pub fn stop(&mut self) {
self.run = false;
}
}