sundries

Assorted little morsels for your enjoyment

git clone https://code.pdelong.com/sundries.git

 1#[macro_use]
 2extern crate quicli;
 3use quicli::prelude::*;
 4
 5use std::path::PathBuf;
 6
 7/// Interpret a brainfuck program
 8#[derive(Debug, StructOpt)]
 9struct Cli {
10    /// The file to interpret
11    #[structopt(parse(from_os_str))]
12    file: PathBuf,
13
14    /// Pass more times for more logging
15    #[structopt(long = "verbose", short = "v", parse(from_occurrences))]
16    verbosity: u8,
17}
18
19#[derive(Debug)]
20enum Op {
21    Left,
22    Right,
23    Inc,
24    Dec,
25    Output,
26    Input,
27    JumpForward(usize),
28    JumpBackward(usize),
29}
30
31main!(|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();
46
47    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    }
59
60    let mut memory = vec![0 as u8; 2^16];
61    let mut i_ptr = 0;
62    let mut m_ptr = 0;
63
64    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});