diff --git a/src/main.rs b/src/main.rs index f58b4cc..3855b39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use java_rs::vm::runtime::Vm; +use std::cmp::Ordering::Equal; fn main() { let a = 0.0; diff --git a/src/value.rs b/src/value.rs index 47245fc..58289d1 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,4 +1,5 @@ use crate::vm::object::ObjectRef; +use std::ops::{Add, AddAssign}; #[derive(Debug, Clone)] pub enum Value { @@ -12,7 +13,7 @@ pub enum Value { F32(f32), F64(f64), BOOL(bool), - CHAR(char), + CHAR(i32), // objects and arrays Ref(ObjectRef), // special object @@ -38,8 +39,7 @@ impl Value { | Value::CHAR(_) | Value::Ref(_) | Value::Utf8(_) => ComputationalType::C1, - Value::I64(_) - | Value::F64(_) => ComputationalType::C2 + Value::I64(_) | Value::F64(_) => ComputationalType::C2, } } @@ -83,4 +83,12 @@ impl Value { panic!(); } } + + pub fn into_utf8(self) -> String { + if let Value::Utf8(v) = self { + v + } else { + panic!(); + } + } } diff --git a/src/vm/array.rs b/src/vm/array.rs index fbb955f..838187c 100644 --- a/src/vm/array.rs +++ b/src/vm/array.rs @@ -95,11 +95,11 @@ pub(crate) fn array_store(value: Value, index: Value, arrayref: Value) -> Result } CharArray(ref mut array) => { if let I32(value) = value { - array[index as usize] = char::from_u32(value as u32).unwrap(); + array[index as usize] = value } else { unreachable!() } - }, + } LongArray(ref mut array) => { if let I64(value) = value { array[index as usize] = value; diff --git a/src/vm/object.rs b/src/vm/object.rs index a2c23bb..2ec6edd 100644 --- a/src/vm/object.rs +++ b/src/vm/object.rs @@ -16,7 +16,7 @@ pub enum ObjectRef { FloatArray(Vec), DoubleArray(Vec), BooleanArray(Vec), - CharArray(Vec), + CharArray(Vec), StringArray(Vec), ObjectArray(ClassId, Vec), Object(Rc>), @@ -86,7 +86,7 @@ impl ObjectRef { 6 => FloatArray(vec![0.0; size]), 7 => DoubleArray(vec![0.0; size]), 4 => BooleanArray(vec![false; size]), - 5 => CharArray(vec![0 as char; size]), + 5 => CharArray(vec![0; size]), _ => unreachable!("impossible array type"), } } diff --git a/src/vm/runtime.rs b/src/vm/runtime.rs index eae96db..0dcb819 100644 --- a/src/vm/runtime.rs +++ b/src/vm/runtime.rs @@ -421,19 +421,87 @@ impl Stackframe { value1.into_i32() >> (value2.into_i32() & MASK_LOWER_5BITS) )); } + LCMP => { + let value2 = self.pop().into_i64(); + let value1 = self.pop().into_i64(); + self.push(I32(compare(value1, value2))); + } + IINC(index8, const8) => { + self.increment(*index8 as usize, *const8 as u16); + } + I2L => { + let value = self.pop().into_i32() as i64; + self.push(I64(value)); + } + I2F => { + let value = self.pop().into_i32() as f32; + self.push(F32(value)); + } + I2D => { + let value = self.pop().into_i32() as f64; + self.push(F64(value)); + } + L2I => { + let value = self.pop().into_i64() as i32; + self.push(I32(value)); + } + L2F => { + let value = self.pop().into_i64() as f32; + self.push(F32(value)); + } + L2D => { + let value = self.pop().into_i64() as f64; + self.push(F64(value)); + } + WIDE_IINC(index16, const16) => { + self.increment(*index16 as usize, *const16); + } + F2I => { + let value = self.pop().into_f32() as i32; + self.push(I32(value)); + } + F2L => { + let value = self.pop().into_f32() as i64; + self.push(I64(value)); + } + F2D => { + let value = self.pop().into_f32() as f64; + self.push(F64(value)); + } + D2I => { + let value = self.pop().into_f64() as i32; + self.push(I32(value)); + } + D2L => { + let value = self.pop().into_f64() as i64; + self.push(I64(value)); + } + D2F => { + let value = self.pop().into_f64() as f32; + self.push(F32(value)); + } + I2B => { + let value = self.pop().into_i32() as u8; + self.push(I32(value as i32)); + } + I2C => { + let value = self.pop().into_i32(); + self.push(CHAR(value)); + } + I2S => { + let value = self.pop().into_i32() as i16; //semantics for narrowing seems same as java + self.push(I32(value as i32)); + } FCMPG | FCMPL => { let value2 = self.pop().into_f32(); let value1 = self.pop().into_f32(); - if value1 == value2 { - self.push(I32(0)) - } else if value1 < value2 { - self.push(I32(-1)) - } else if value1 > value2 { - self.push(I32(1)) - } - //TODO something with NaN + self.push(I32(compare(value1, value2))); + } + DCMPG | DCMPL => { + let value2 = self.pop().into_f64(); + let value1 = self.pop().into_f64(); + self.push(I32(compare(value1, value2))); } - IFEQ(jmp_to) | IFNE(jmp_to) | IFLT(jmp_to) | IFGE(jmp_to) | IFGT(jmp_to) | IFLE(jmp_to) => { let value = self.pop(); @@ -774,21 +842,11 @@ impl Stackframe { let value = self.pop().into_f64(); self.push(F64(-value)); } - ISHL => { - let value2 = self.pop().into_i32(); - let value1 = self.pop().into_i32(); - self.push(I32(value1 << value2)); - } LSHL => { let value2 = self.pop().into_i64(); let value1 = self.pop().into_i64(); self.push(I64(value1 << value2)); } - ISHR => { - let value2 = self.pop().into_i32(); - let value1 = self.pop().into_i32(); - self.push(I32(value1 >> value2)); - } LSHR => { let value2 = self.pop().into_i64(); let value1 = self.pop().into_i64(); @@ -820,6 +878,16 @@ impl Stackframe { Void } + fn increment(&mut self, index: usize, inc: u16) { + match &mut self.locals[index] { + I32(l) => *l += (inc as i32), + I64(l) => *l += (inc as i64), + F32(l) => *l += (inc as f32), + F64(l) => *l += (inc as f64), + _ => {} + } + } + fn store(&mut self, index: u8) -> Result<(), Error> { let index = index as usize; let value = self.pop(); @@ -933,3 +1001,10 @@ impl MethodSignature { MethodSignature { name, num_args } } } + +fn compare(a: T, b: T) -> i32 +where + T: PartialOrd, +{ + a.partial_cmp(&b).unwrap() as i32 +}