ttvm 0.4.4

tt64 emulator API for Rust
Documentation
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;
    }
}