1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use std::fmt;

/// An executable instruction in the language.
///
/// There are only 8 instructions in the brainfuck language. A pair for
/// incrementing and decrementing the pointer, and values on the tape.
/// Two instructions for reading and writing a char from `STDIN` and
/// `STDOUT` respectivly. And finally the only control flow
/// instructions for skipping ahead and skipping back. More information
/// on control flow below.
///
/// # Control Flow
///
/// Control flow in brainfuck is achieved by skipping forward, and
/// backward. The `[` instruction skips past it's matching `]`
/// instruction, and the `]` instruction skips back **to** it's
/// matching `[` instruction. Matching brackets follow the intuitive
/// notion, for example `[+[+]+]` has to pairs of matching brackets.
/// Skips are conditional based on the value of the cell behind the
/// pointer. A forward skip only happens when the value of the cell
/// is 0, and the backward skip only happens when the value of the
/// cell is **not** 0. This allows for a relatively simple syntax for
/// decrementing iteration. For example `+++[- > operate on cell 2 < ]>.`
/// is the boilerplate for a loop that operates 3 times.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Instruction {
    /// Increment the pointer moving it up on the tape.
    IncPtr,
    /// Decrement the pointer moving it down on the tape.
    DecPtr,
    /// Increment the value at the pointer on the tape.
    IncVal,
    /// Decrement the value at the pointer on the tape.
    DecVal,
    /// Write the value at the pointer as a `char` to `STDOUT`. This
    /// instruction can fail if writing to the underlying writer fails.
    Output,
    /// Read from `STDIN` as a `char` to value at the pointer. This
    /// instruction can fail if reading from the underlying reader
    /// fails or has no more data.
    Input,
    /// Skip forward if the value at the pointer is `0`. For more
    /// information see the section on control flow above.
    SkipForward(usize),
    /// Skip backward if the value at the pointer is **not** `0`.
    /// For more information see the section on control flow above.
    SkipBackward(usize),
}

impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Instruction::IncPtr          => write!(f, ">"),
            Instruction::DecPtr          => write!(f, "<"),
            Instruction::IncVal          => write!(f, "+"),
            Instruction::DecVal          => write!(f, "-"),
            Instruction::Output          => write!(f, "."),
            Instruction::Input           => write!(f, ","),
            Instruction::SkipForward(_)  => write!(f, "["),
            Instruction::SkipBackward(_) => write!(f, "]"),
        }
    }
}

#[cfg(test)]
mod tests {}