Files
RustIJVM/src/machine.rs
2018-05-23 20:31:53 +02:00

158 lines
4.1 KiB
Rust

use std::io::{Read, Write};
use std::sync::Mutex;
use std::rc::Rc;
use Result;
use block::Block;
use ops::Operation;
use ijvmreader::IJVMReader;
use binread::{BinRead, BinReadable};
use frame::Frame;
use stack::Stack;
use pool::Pool;
#[cfg(feature = "bonus:network")]
use netstack::NetStack;
#[cfg(feature = "bonus:heap")]
use heap::Heap;
const MAGIC_HEADER:u32 = 0x1DEA_DFAD;
const ANTI_BS_SIZE:usize = 0xFFFF;
pub struct Machine {
pub wide: bool,
pub halted: bool,
pub pool: Pool,
pub block: Block,
pub frame: Vec<Frame>,
#[cfg(feature = "bonus:network")]
pub net: NetStack,
#[cfg(feature = "bonus:heap")]
pub heap: Heap,
pub stream_in: Box<Read + Send + Sync>,
pub stream_out: Rc<Mutex<Write + Send + Sync>>,
}
impl Machine {
pub fn new(pool: Pool, block: Block) -> Machine{
Machine {
wide: false,
halted: false,
pool,
block,
frame: vec![Frame::new(ANTI_BS_SIZE)],
stream_in: Box::new(::std::io::stdin()),
stream_out: Rc::new(Mutex::new(::std::io::stdout())),
#[cfg(feature = "bonus:network")]
net: NetStack::new(),
#[cfg(feature = "bonus:heap")]
heap: Heap::new(),
}
}
pub fn new_from_reader(mut reader: IJVMReader) -> Result<Machine> {
let magic = reader.read_u32()?;
if magic != MAGIC_HEADER {
return Err("Invalid magic header");
}
let constants = match reader.read_block() {
Ok(a) => a,
Err(_) => return Err("Failed to read constants block")
};
let text = match reader.read_block() {
Ok(block) => block,
Err(_) => return Err("Failed to read text block")
};
let pool = Pool::new(constants)?;
Ok(Machine::new(pool, text))
}
pub fn new_from_file(file: &str) -> Result<Machine> {
let reader = IJVMReader::new(file).unwrap();
Machine::new_from_reader(reader)
}
pub fn new_from_slice(source: &[u8]) -> Result<Machine> {
let reader = IJVMReader::new_from_slice(source);
Machine::new_from_reader(reader)
}
pub fn step(&mut self) -> Result<()> {
match self.block.read_op() {
Ok(Operation::Op(a, func)) => {
if cfg!(feature = "debug:instr") {
println!("{}", a);
println!("Stack: {:?}", self.cur_frame().stack.data);
let x = func(self);
println!("Stack: {:?}", self.cur_frame().stack.data);
x
} else {
func(self)
}
},
Ok(Operation::Invalid(a)) => {
println!("UNDEFINED OP: 0x{:X}", a);
Err("Invalid op")
},
Err(str) => Err(str)
}
}
pub fn run(&mut self) -> Result<()> {
while self.has_step() {
self.step()?;
}
Ok(())
}
pub fn has_step(&self) -> bool {
!self.halted && self.block.has_i8()
}
pub fn get_program_counter(&self) -> usize {
self.block.cur()
}
pub fn get_tos(&mut self) -> Result<i32> {
self.cur_stack().top()
}
pub fn cur_frame(&mut self) -> &mut Frame {
self.frame.last_mut().unwrap()
}
pub fn cur_stack(&mut self) -> &mut Stack {
&mut self.cur_frame().stack
}
pub fn cur_instruction(&mut self) -> u8 {
self.block[self.get_program_counter()]
}
// pub fn get_stack_pointer(&self) -> usize {
// return self.frame.last().unwrap().stack.len();
// }
pub fn read_index(&mut self) -> Result<usize> {
if self.wide {
self.wide = false;
return Ok(self.block.read_u16()? as usize)
}
Ok(self.block.read_u8()? as usize)
}
pub fn set_input(&mut self, instream: Box<Read + Send + Sync>) {
self.stream_in = instream;
}
pub fn set_output(&mut self, outstream: Rc<Mutex<Write + Send + Sync>>) {
self.stream_out = outstream;
}
}