1#[macro_use]2extern crate quicli;3use quicli::prelude::*;45use std::path::PathBuf;67/// Interpret a brainfuck program8#[derive(Debug, StructOpt)]9struct Cli {10 /// The file to interpret11 #[structopt(parse(from_os_str))]12 file: PathBuf,1314 /// Pass more times for more logging15 #[structopt(long = "verbose", short = "v", parse(from_occurrences))]16 verbosity: u8,17}1819#[derive(Debug)]20enum Op {21 Left,22 Right,23 Inc,24 Dec,25 Output,26 Input,27 JumpForward(usize),28 JumpBackward(usize),29}3031main!(|args: Cli, log_level: verbosity| {32 info!("Attempting to execute file {:?}", &args.file);33 let mut ops: Vec<Op> = read_file(&args.file)?34 .chars()35 .filter_map(|ch| match ch {36 '<' => Some(Op::Left),37 '>' => Some(Op::Right),38 '+' => Some(Op::Inc),39 '-' => Some(Op::Dec),40 '.' => Some(Op::Output),41 ',' => Some(Op::Input),42 '[' => Some(Op::JumpForward(0)),43 ']' => Some(Op::JumpBackward(0)),44 _ => None,45 }).collect();4647 let mut forward_stack: Vec<usize> = Vec::new();48 for i in 0..ops.len() {49 match &ops[i] {50 &Op::JumpForward(_) => forward_stack.push(i),51 &Op::JumpBackward(_) => {52 let index: usize = forward_stack.pop().unwrap();53 ops[i] = Op::JumpBackward(index);54 ops[index] = Op::JumpForward(i);55 }56 _ => {}57 }58 }5960 let mut memory = vec![0 as u8; 2^16];61 let mut i_ptr = 0;62 let mut m_ptr = 0;6364 loop {65 match ops[i_ptr] {66 Op::Left => m_ptr -= 1,67 Op::Right => m_ptr += 1,68 Op::Inc => memory[m_ptr] = memory[m_ptr].wrapping_add(1),69 Op::Dec => memory[m_ptr] = memory[m_ptr].wrapping_sub(1),70 Op::Output => print!("{}", memory[m_ptr] as char),71 Op::Input => {}72 Op::JumpForward(index) => i_ptr = if memory[m_ptr] == 0 { index } else { i_ptr },73 Op::JumpBackward(index) => i_ptr = if memory[m_ptr] != 0 { index } else { i_ptr },74 }75 i_ptr += 1;76 if i_ptr >= ops.len() {77 break;78 }79 }80});