diff --git a/src/frame.rs b/src/frame.rs index 884a337..f4b4275 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -1,11 +1,12 @@ use stack::Stack; use Result; +use value::Value; #[derive(Debug)] pub struct Frame { pub base: usize, pub stack: Stack, - pub locals: Vec, + pub locals: Vec, } impl Frame { @@ -16,7 +17,7 @@ impl Frame { Frame { base, stack: Stack::new(), - locals: vec![0; num_locals], + locals: vec![Value::Int(0); num_locals], } } @@ -28,14 +29,14 @@ impl Frame { self.locals.is_empty() } - pub fn get(&self, offset: usize) -> Result { + pub fn get(&self, offset: usize) -> Result<&Value> { if offset >= self.locals.len() { return Err("Local variable out of range"); } - Ok(self.locals[offset]) + Ok(&self.locals[offset]) } - pub fn set(&mut self, offset: usize, val: i32) -> Result<()> { + pub fn set(&mut self, offset: usize, val: Value) -> Result<()> { if offset >= self.locals.len() { return Err("Local variable out of range"); } diff --git a/src/lib.rs b/src/lib.rs index df4f386..994c2b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ extern crate lazy_static; pub mod ijvmreader; pub mod binread; pub mod block; +pub mod value; pub mod ops; pub mod stack; pub mod pool; diff --git a/src/machine.rs b/src/machine.rs index b49cb8a..57b8ac0 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -14,6 +14,7 @@ use Result; use heap::Heap; #[cfg(feature = "bonus:network")] use netstack::NetStack; +use std::convert::TryInto; pub const MAGIC_HEADER: u32 = 0x1DEA_DFAD; const ANTI_BS_SIZE: usize = 0xFF; @@ -119,7 +120,7 @@ impl Machine { } pub fn get_tos(&mut self) -> Result { - self.cur_stack().top() + self.cur_stack().top()?.try_into() } pub fn cur_frame(&mut self) -> &mut Frame { diff --git a/src/ops.rs b/src/ops.rs index 36ad400..76c1189 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -4,6 +4,8 @@ use machine::Machine; use std::io::Read; use std::num::Wrapping; use Result; +use value::Value; +use std::convert::TryInto; pub type OpFunc = fn(&mut Machine) -> Result<()>; @@ -91,23 +93,24 @@ fn bipush(machine: &mut Machine) -> Result<()> { Ok(a) => i32::from(a), Err(_) => return Err("Expected argument"), }; - machine.cur_stack().push(val); + machine.cur_stack().push(Value::Int(val)); Ok(()) } fn dup(machine: &mut Machine) -> Result<()> { - let val = machine.cur_stack().top()?; + let val = machine.cur_stack().top()?.clone(); machine.cur_stack().push(val); Ok(()) } fn out(machine: &mut Machine) -> Result<()> { - let val = machine.cur_stack().pop()?; + let val: i32 = machine.cur_stack().pop()?.try_into()?; + let buffer = [val as u8]; let mut out = machine.stream_out.lock().unwrap(); out.write_all(&buffer).unwrap(); out.flush().unwrap(); - Ok(()) + return Ok(()); } fn pop(machine: &mut Machine) -> Result<()> { @@ -116,16 +119,17 @@ fn pop(machine: &mut Machine) -> Result<()> { } fn iadd(machine: &mut Machine) -> Result<()> { - let a = Wrapping(machine.cur_stack().pop()?); - let b = Wrapping(machine.cur_stack().pop()?); - machine.cur_stack().push((a + b).0); + let a: i32 = machine.cur_stack().pop()?.try_into()?; + let b: i32 = machine.cur_stack().pop()?.try_into()?; + let res = Wrapping(a) + Wrapping(b); + machine.cur_stack().push(Value::Int(res.0)); Ok(()) } fn isub(machine: &mut Machine) -> Result<()> { - let a = Wrapping(machine.cur_stack().pop()?); - let b = Wrapping(machine.cur_stack().pop()?); - machine.cur_stack().push((b - a).0); + let a: Wrapping = Wrapping(machine.cur_stack().pop()?.try_into()?); + let b: Wrapping = Wrapping(machine.cur_stack().pop()?.try_into()?); + machine.cur_stack().push(Value::Int((b - a).0)); Ok(()) } @@ -135,7 +139,7 @@ fn _in(machine: &mut Machine) -> Result<()> { Err(_) => 0i32, Ok(_) => i32::from(buffer[0]), }; - machine.cur_stack().push(val); + machine.cur_stack().push(Value::Int(val)); Ok(()) } @@ -157,7 +161,8 @@ fn halt(machine: &mut Machine) -> Result<()> { fn ifeq(machine: &mut Machine) -> Result<()> { let offset = i32::from(machine.block.read_i16()?) - JUMP_OFFSET; - if machine.cur_stack().pop()? == 0 { + let compare: i32 = machine.cur_stack().pop()?.try_into()?; + if compare == 0 { return machine.block.jump(offset); } Ok(()) @@ -165,7 +170,8 @@ fn ifeq(machine: &mut Machine) -> Result<()> { fn iflt(machine: &mut Machine) -> Result<()> { let offset = i32::from(machine.block.read_i16()?) - JUMP_OFFSET; - if machine.cur_stack().pop()? < 0 { + let compare: i32 = machine.cur_stack().pop()?.try_into()?; + if compare < 0 { return machine.block.jump(offset); } Ok(()) @@ -180,23 +186,23 @@ fn if_icmpeq(machine: &mut Machine) -> Result<()> { } fn iand(machine: &mut Machine) -> Result<()> { - let a = machine.cur_stack().pop()?; - let b = machine.cur_stack().pop()?; - machine.cur_stack().push(a & b); + let a: i32 = machine.cur_stack().pop()?.try_into()?; + let b: i32 = machine.cur_stack().pop()?.try_into()?; + machine.cur_stack().push(Value::Int(a & b)); Ok(()) } fn ior(machine: &mut Machine) -> Result<()> { - let a = machine.cur_stack().pop()?; - let b = machine.cur_stack().pop()?; - machine.cur_stack().push(a | b); + let a: i32 = machine.cur_stack().pop()?.try_into()?; + let b: i32 = machine.cur_stack().pop()?.try_into()?; + machine.cur_stack().push(Value::Int(a | b)); Ok(()) } fn ldc_w(machine: &mut Machine) -> Result<()> { let offset = machine.block.read_i16()? as usize; let val = machine.pool.get(offset)?; - machine.cur_stack().push(val); + machine.cur_stack().push(Value::Int(val)); Ok(()) } @@ -215,7 +221,7 @@ fn wide(machine: &mut Machine) -> Result<()> { fn iload(machine: &mut Machine) -> Result<()> { let a = machine.read_index()?; - let val = machine.cur_frame().get(a)?; + let val = machine.cur_frame().get(a)?.clone(); machine.cur_stack().push(val); Ok(()) } @@ -229,8 +235,8 @@ fn istore(machine: &mut Machine) -> Result<()> { fn iinc(machine: &mut Machine) -> Result<()> { let a = machine.read_index()?; let b = i32::from(machine.block.read_i8()?); - let val = machine.cur_frame().get(a)?; - machine.cur_frame().set(a, val + b) + let val: i32 = machine.cur_frame().get(a)?.try_into()?; + machine.cur_frame().set(a, Value::Int(val + b)) } fn invokevirtual(machine: &mut Machine) -> Result<()> { @@ -253,7 +259,7 @@ fn invokevirtual(machine: &mut Machine) -> Result<()> { cur_stack.pop()?; // Nuke the OBJREF } - newframe.set(0, return_addr as i32)?; + newframe.set(0, Value::Int(return_addr as i32))?; machine.frame.push(newframe); Ok(()) @@ -265,7 +271,7 @@ fn ireturn(machine: &mut Machine) -> Result<()> { None => return Err("Got no frame... somehow..."), }; let result = prev_frame.stack.pop()?; - let return_addr = prev_frame.get(0)?; + let return_addr: i32 = prev_frame.get(0)?.try_into()?; machine.cur_stack().push(result); machine.block.seek(return_addr as usize) } @@ -285,28 +291,28 @@ fn slp(machine: &mut Machine) -> Result<()> { #[cfg(feature = "bonus:network")] fn netbind(machine: &mut Machine) -> Result<()> { - let port = machine.cur_stack().pop()? as u16; - machine.net.bind(port) + let port: i32 = machine.cur_stack().pop()?.try_into()?; + machine.net.bind(port as u16) } #[cfg(feature = "bonus:network")] fn netconnect(machine: &mut Machine) -> Result<()> { - let port = machine.cur_stack().pop()? as u16; - let host = machine.cur_stack().pop()? as u32; - machine.net.connect(host, port) + let port: i32 = machine.cur_stack().pop()?.try_into()?; + let host: i32 = machine.cur_stack().pop()?.try_into()?; + machine.net.connect(host as u32, port as u16) } #[cfg(feature = "bonus:network")] fn netin(machine: &mut Machine) -> Result<()> { let byte = i32::from(machine.net.read_byte()?); - machine.cur_stack().push(byte); + machine.cur_stack().push(Value::Int(byte)); Ok(()) } #[cfg(feature = "bonus:network")] fn netout(machine: &mut Machine) -> Result<()> { - let val = machine.cur_stack().pop()? as u8; - machine.net.write_byte(val) + let val: i32 = machine.cur_stack().pop()?.try_into()?; + machine.net.write_byte(val as u8) } #[cfg(feature = "bonus:network")] @@ -316,35 +322,41 @@ fn netclose(machine: &mut Machine) -> Result<()> { #[cfg(feature = "bonus:heap")] fn newarray(machine: &mut Machine) -> Result<()> { - let size = machine.cur_stack().pop()? as usize; - let heapref = machine.heap.alloc(size); - machine.cur_stack().push(heapref as i32); + let size: i32 = machine.cur_stack().pop()?.try_into()?; + let heapref = machine.heap.alloc(size as usize); + machine.cur_stack().push(Value::HeapRef(heapref)); Ok(()) } #[cfg(feature = "bonus:heap")] fn iastore(machine: &mut Machine) -> Result<()> { - let heapref = machine.cur_stack().pop()? as usize; - let index = machine.cur_stack().pop()? as usize; - let value = machine.cur_stack().pop()?; + let heapref = match machine.cur_stack().pop()? { + Value::HeapRef(a) => a, + _ => return Err("Cannot use int as heapref"), + }; + let index: i32 = machine.cur_stack().pop()?.try_into()?; + let value: i32 = machine.cur_stack().pop()?.try_into()?; let heap = machine.heap.get(heapref); - heap[index] = value; + heap[index as usize] = value; Ok(()) } #[cfg(feature = "bonus:heap")] fn iaload(machine: &mut Machine) -> Result<()> { - let heapref = machine.cur_stack().pop()? as usize; - let index = machine.cur_stack().pop()? as usize; + let heapref = match machine.cur_stack().pop()? { + Value::HeapRef(a) => a, + _ => return Err("Cannot use int as heapref"), + }; + let index: i32 = machine.cur_stack().pop()?.try_into()?; let value: i32; { let heap = machine.heap.get(heapref); - value = heap[index]; + value = heap[index as usize]; } - machine.cur_stack().push(value); + machine.cur_stack().push(Value::Int(value)); Ok(()) } diff --git a/src/stack.rs b/src/stack.rs index c94e182..ae38ae9 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -1,8 +1,10 @@ use Result; +use value::Value; + #[derive(Debug, Default)] pub struct Stack { - pub data: Vec + pub data: Vec } impl Stack { @@ -20,25 +22,25 @@ impl Stack { self.len() == 0 } - pub fn get(&self, i: usize) -> i32 { - self.data[i] + pub fn get(&self, i: usize) -> &Value { + &self.data[i] } - pub fn top(&self) -> Result { - Ok(match self.data.last() { - Some(a) => *a, + pub fn top(&self) -> Result<&Value> { + Ok(match self.data.last() { + Some(a) => a, None => return Err("Stack empty"), }) } - pub fn pop(&mut self) -> Result { + pub fn pop(&mut self) -> Result { Ok(match self.data.pop() { Some(a) => a, None => return Err("Stack empty"), }) } - pub fn push(&mut self, val: i32) { + pub fn push(&mut self, val: Value) { self.data.push(val); } -} \ No newline at end of file +} diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 0000000..9c2b1a6 --- /dev/null +++ b/src/value.rs @@ -0,0 +1,30 @@ +use Result; +use std::convert::TryInto; + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum Value { + Int(i32), + HeapRef(usize), +} + +impl TryInto for Value { + type Error = &'static str; + + fn try_into(self) -> Result { + match self { + Value::Int(a) => Ok(a), + Value::HeapRef(_) => Err("Cannot use HeapRef as i32"), + } + } +} + +impl TryInto for &Value { + type Error = &'static str; + + fn try_into(self) -> Result { + match self { + &Value::Int(a) => Ok(a), + &Value::HeapRef(_) => Err("Cannot use HeapRef as i32"), + } + } +}