diff --git a/Cargo.toml b/Cargo.toml index 585c8c4..6183d1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,9 @@ authors = ["Jur van den Berg "] [features] default = ["bonus", "extra"] -bonus = ["bonus:network"] +bonus = ["bonus:network", "bonus:heap"] "bonus:network" = [] +"bonus:heap" = [] extra = ["extra:sleep"] "extra:sleep" = [] diff --git a/src/heap.rs b/src/heap.rs new file mode 100644 index 0000000..3028903 --- /dev/null +++ b/src/heap.rs @@ -0,0 +1,25 @@ +#[derive(Debug)] +pub struct Heap { + pub heaps: Vec> +} + +impl Heap { + pub fn new() -> Heap { + Heap { + heaps: Vec::new() + } + } + + pub fn len(&self) -> usize { + self.heaps.len() + } + + pub fn get(&mut self, i: usize) -> &mut Vec { + &mut self.heaps[i] + } + + pub fn alloc(&mut self, size: usize) -> usize { + self.heaps.push(vec![0; size]); + self.len() - 1 + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index db5b52b..9217059 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,9 @@ pub mod pool; pub mod frame; pub mod netstack; +#[cfg(feature = "bonus:heap")] +pub mod heap; + type Result = ::std::result::Result; pub use machine::Machine; diff --git a/src/machine.rs b/src/machine.rs index 6361961..2a26e6e 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -12,6 +12,9 @@ use Result; use std::sync::Mutex; use std::rc::Rc; +#[cfg(feature = "bonus:heap")] +use heap::Heap; + const MAGIC_HEADER:u32 = 0x1DEA_DFAD; const ANTI_BS_SIZE:usize = 0xFFFF; @@ -23,6 +26,9 @@ pub struct Machine { pub frame: Vec, pub net: NetStack, + #[cfg(feature = "bonus:heap")] + pub heap: Heap, + pub stream_in: Box, pub stream_out: Rc>, @@ -36,9 +42,13 @@ impl Machine { pool, block, frame: vec![Frame::new(ANTI_BS_SIZE)], - net: NetStack::new(), stream_in: Box::new(::std::io::stdin()), stream_out: Rc::new(Mutex::new(::std::io::stdout())), + + net: NetStack::new(), + + #[cfg(feature = "bonus:heap")] + heap: Heap::new(), } } diff --git a/src/ops.rs b/src/ops.rs index 9bdff0a..b4ce7be 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -53,6 +53,13 @@ pub fn num_to_op(op: u8) -> Operation { #[cfg(feature = "bonus:network")] 0xE5 => Operation::Op("NETCLOSE", netclose), + #[cfg(feature = "bonus:heap")] + 0xD1 => Operation::Op("NEWARRAY", newarray), + #[cfg(feature = "bonus:heap")] + 0xD2 => Operation::Op("IALOAD", iaload), + #[cfg(feature = "bonus:heap")] + 0xD3 => Operation::Op("IASTORE", iastore), + x => Operation::Invalid(x) } } @@ -282,4 +289,39 @@ fn netout(machine: &mut Machine) -> Result<()> { #[cfg(feature = "bonus:network")] fn netclose(machine: &mut Machine) -> Result<()> { machine.net.close() -} \ No newline at end of file +} + +#[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); + 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 heap = machine.heap.get(heapref); + heap[index] = 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 value: i32; + { + let heap = machine.heap.get(heapref); + value = heap[index]; + } + machine.cur_stack().push(value); + + Ok(()) +} diff --git a/tests/bonusheap.rs b/tests/bonusheap.rs new file mode 100644 index 0000000..a763b9b --- /dev/null +++ b/tests/bonusheap.rs @@ -0,0 +1,36 @@ +extern crate rustijvm; + +use std::fs::File; +use std::rc::Rc; +use std::sync::Mutex; +use std::io::{Cursor, Seek, SeekFrom, Read}; + +fn run_bfi(file: &str) -> String { + let file = File::open(file).expect("Missing bf file"); + let rc = Rc::new(Mutex::new(Cursor::new(Vec::new()))); + let mut machine = rustijvm::Machine::new_from_file("files/bonus/bfi.ijvm").unwrap(); + machine.set_output(rc.clone()); + machine.set_input(Box::new(file)); + + machine.run().unwrap(); + + let mut out = rc.lock().unwrap(); + let mut string = String::new(); + + out.seek(SeekFrom::Start(0)).unwrap(); + out.read_to_string(&mut string).unwrap(); + + string +} + +#[test] +fn bonusheap_hello_world() { + let output = run_bfi("files/bonus/brainfuck/hello_world.bf"); + assert_eq!(output, "Hello World!\n"); +} + +#[test] +fn bonusheap_dank() { + let output = run_bfi("files/bonus/brainfuck/dank.bf"); + assert_eq!(output, "MoarTests"); +}