use std::collections::HashMap; use std::env; use std::fs::File; use std::io::prelude::*; use std::io::stdin; use std::num::Wrapping; fn main() { let args: Vec<_> = env::args().collect(); if args.len() < 2 { println!("Usage: {} [path] (--debug)", args[0]); return; } let src: Vec = { let mut buf = String::new(); match File::open(&args[1]) { Ok(mut f) => { f.read_to_string(&mut buf).unwrap(); } Err(e) => { println!("Error opening '{}': {}", args[1], e); return; } } buf.chars().collect() }; // Launch options let debug = args.contains(&"--debug".to_owned()); // One pass to find bracket pairs. let brackets: HashMap = { let mut m = HashMap::new(); let mut scope_stack = Vec::new(); for (idx, ch) in src.iter().enumerate() { match ch { &'[' => { scope_stack.push(idx); } &']' => { m.insert(scope_stack.pop().unwrap(), idx); } _ => { /* ignore */ } } } m }; let mut pc: usize = 0; // Program counter let mut mem: [Wrapping;5000] = [Wrapping(0);5000]; // Program cemory let mut ptr: usize = 0; // Pointer let mut stack: Vec = Vec::new(); // Bracket stack let stdin_ = stdin(); let mut reader = stdin_.lock().bytes(); while pc < src.len() { let Wrapping(val) = mem[ptr]; if debug { println!("(BFDB) PC: {:04} \tPTR: {:04} \t$PTR: {:03} \tSTACK_DEPTH: {} \tSYMBOL: {}", pc, ptr, val, stack.len(), src[pc]); } const ONE: Wrapping = Wrapping(1); match src[pc] { '>' => { ptr += 1; } '<' => { ptr -= 1; } '+' => { mem[ptr] = mem[ptr] + ONE; } '-' => { mem[ptr] = mem[ptr] - ONE; } '[' => { if val == 0 { pc = brackets[&pc]; } else { stack.push(pc); } } ']' => { let matching_bracket = stack.pop().unwrap(); if val != 0 { pc = matching_bracket - 1; } } '.' => { if debug { println!("(BFDB) STDOUT: '{}'", val as char); // Intercept output } else { print!("{}", val as char); } } ',' => { mem[ptr] = Wrapping(reader.next().unwrap().unwrap()); } _ => { /* ignore */ } } pc += 1; } }