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 {}