Initial stack typing

This commit is contained in:
2019-04-29 15:21:37 +02:00
parent 1381ce7b48
commit ba0fca8755
6 changed files with 106 additions and 59 deletions

View File

@@ -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<i32> = Wrapping(machine.cur_stack().pop()?.try_into()?);
let b: Wrapping<i32> = 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(())
}