Last active
April 16, 2016 09:55
-
-
Save bjorn3/6ee69ede6961527b627c377b6e132712 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::VecDeque; | |
use std::iter::Peekable; | |
use std::str::Chars; | |
use std::mem; | |
#[derive(Debug, Clone, Hash, Eq, PartialEq)] | |
enum Instruction{ | |
Nop, | |
Next, | |
Prev, | |
Inc, | |
Dec, | |
Print, | |
Input, | |
Loop(Vec<Instruction>) | |
} | |
impl Instruction{ | |
pub fn from_iter(iter: &mut Peekable<Chars>) -> Vec<Instruction>{ | |
let mut instructions = Vec::new(); | |
let mut stop = false; | |
loop{ | |
let instr = match iter.peek(){ | |
Some(instr) => instr, | |
None => break | |
}.clone(); | |
instructions.push(match instr{ | |
'>' => { | |
iter.next(); | |
Instruction::Next | |
}, | |
'<' => { | |
iter.next(); | |
Instruction::Prev | |
}, | |
'+' => { | |
iter.next(); | |
Instruction::Inc | |
}, | |
'-' => { | |
iter.next(); | |
Instruction::Dec | |
}, | |
'.' => { | |
iter.next(); | |
Instruction::Print | |
}, | |
',' => { | |
iter.next(); | |
Instruction::Input | |
}, | |
'[' => { | |
iter.next(); | |
Instruction::Loop(Instruction::from_iter(iter)) | |
}, | |
']' => { | |
stop = true; | |
iter.next(); | |
Instruction::Nop | |
}, | |
char => { | |
println!("{}", char); | |
unreachable!(); | |
} | |
}); | |
if stop{ | |
break; | |
} | |
} | |
instructions | |
} | |
pub fn run(&self, pc: &mut usize, mem: &mut [u8], memnum: &mut usize){ | |
{ | |
let mut instr = format!("{:#?}", self); | |
while instr.len() < 5{ | |
instr.push(' '); | |
} | |
let mut pc = format!("{}", pc); | |
while pc.len() < 2{ | |
pc.push(' '); | |
} | |
let mut mem = mem.iter().map(|num|{ | |
let mut num = format!("{}", num); | |
while num.len() < 2{ | |
num.push(' '); | |
} | |
num | |
}).fold("".to_owned(), |acc, num| acc + &num); | |
// +----uncomment this for debug information | |
// v | |
//println!("instr: {}, pc: {}, mem: {:?}, memnum: {}", instr, pc, mem.to_owned(), memnum); | |
} | |
match *self{ | |
Instruction::Nop => { | |
*pc += 1; | |
}, | |
Instruction::Next => { | |
*memnum += 1; | |
*pc += 1; | |
}, | |
Instruction::Prev => { | |
*memnum -= 1; | |
*pc += 1; | |
}, | |
Instruction::Inc => { | |
(*mem)[*memnum] += 1; | |
*pc += 1; | |
}, | |
Instruction::Dec => { | |
(*mem)[*memnum] -= 1; | |
*pc += 1; | |
}, | |
Instruction::Print => { | |
use ::std::io::Write; | |
let mut stdout = ::std::io::stdout(); | |
let num = [mem[*memnum]]; | |
stdout.write(&num).unwrap(); | |
stdout.flush().unwrap(); | |
*pc += 1; | |
}, | |
Instruction::Loop(ref instructions) => { | |
let mut loop_pc = 0; | |
while mem[*memnum] != 0{ | |
while loop_pc < instructions.len(){ | |
instructions[loop_pc].run(&mut loop_pc, mem, memnum); | |
} | |
loop_pc = 0; | |
} | |
*pc += 1; | |
} | |
_ => panic!("Invalid key") | |
} | |
} | |
} | |
fn main(){ | |
let program: &str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; | |
let program: Vec<Instruction> = Instruction::from_iter(&mut program.chars().peekable()); | |
let mut pc = 0; | |
let mut mem = [0u8;30000]; | |
let mut memnum = 0; | |
// +----uncomment this for debug information | |
// v | |
//println!("{:#?}", program); | |
loop{ | |
program[pc].run(&mut pc, &mut mem, &mut memnum); | |
if pc >= program.len() { | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a fully functional implementation.