Heap bonus!
This commit is contained in:
@@ -8,8 +8,9 @@ authors = ["Jur van den Berg <Jurl.berg@gmail.com>"]
|
||||
[features]
|
||||
default = ["bonus", "extra"]
|
||||
|
||||
bonus = ["bonus:network"]
|
||||
bonus = ["bonus:network", "bonus:heap"]
|
||||
"bonus:network" = []
|
||||
"bonus:heap" = []
|
||||
|
||||
extra = ["extra:sleep"]
|
||||
"extra:sleep" = []
|
||||
|
||||
25
src/heap.rs
Normal file
25
src/heap.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
#[derive(Debug)]
|
||||
pub struct Heap {
|
||||
pub heaps: Vec<Vec<i32>>
|
||||
}
|
||||
|
||||
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<i32> {
|
||||
&mut self.heaps[i]
|
||||
}
|
||||
|
||||
pub fn alloc(&mut self, size: usize) -> usize {
|
||||
self.heaps.push(vec![0; size]);
|
||||
self.len() - 1
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,9 @@ pub mod pool;
|
||||
pub mod frame;
|
||||
pub mod netstack;
|
||||
|
||||
#[cfg(feature = "bonus:heap")]
|
||||
pub mod heap;
|
||||
|
||||
type Result<T> = ::std::result::Result<T, &'static str>;
|
||||
|
||||
pub use machine::Machine;
|
||||
|
||||
@@ -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<Frame>,
|
||||
pub net: NetStack,
|
||||
|
||||
#[cfg(feature = "bonus:heap")]
|
||||
pub heap: Heap,
|
||||
|
||||
pub stream_in: Box<Read>,
|
||||
pub stream_out: Rc<Mutex<Write>>,
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
44
src/ops.rs
44
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()
|
||||
}
|
||||
}
|
||||
|
||||
#[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(())
|
||||
}
|
||||
|
||||
36
tests/bonusheap.rs
Normal file
36
tests/bonusheap.rs
Normal file
@@ -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");
|
||||
}
|
||||
Reference in New Issue
Block a user