Skip to content

Instantly share code, notes, and snippets.

@Benricheson101
Created September 9, 2020 21:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Benricheson101/76c48d74e036dc7afd538aa43b90205f to your computer and use it in GitHub Desktop.
Save Benricheson101/76c48d74e036dc7afd538aa43b90205f to your computer and use it in GitHub Desktop.
brainfuck but its all `a`s
ââââââââÄÁââââÄÁââÁâââÁâââÁâÀÀÀÀãäÁâÁâÁãÁÁâÄÀäÀãäÁÁàÁãããàâââââââààâââàÁÁàÀãàÀàâââàããããããàããããããããàÁÁâàÁââà
use std::io;
use unicode_segmentation::UnicodeSegmentation;
#[derive(PartialEq)]
enum BFOperations {
IncreasePointer,
DecreasePointer,
IncreaseCell,
DecreaseCell,
ReadStdin,
WriteStdout,
StartLoop,
EndLoop,
WriteToDebugTape,
Other,
}
pub struct BF {
tape: Vec<char>,
instructions: Vec<BFOperations>,
pos: usize,
cell: usize,
debug: Vec<char>
}
impl BF {
pub fn new(code: String) -> Self {
Self {
tape: Vec::new(),
instructions: UnicodeSegmentation::graphemes(&code[..], true).map(Self::map_chars).collect::<Vec<BFOperations>>(),
pos: 0,
cell: 0,
debug: Vec::new(),
}
}
fn map_chars(c: &str) -> BFOperations {
match c {
"Á" => BFOperations::IncreasePointer,
"À" => BFOperations::DecreasePointer,
"â" => BFOperations::IncreaseCell,
"ã" => BFOperations::DecreaseCell,
"á" => BFOperations::ReadStdin,
"à" => BFOperations::WriteStdout,
"Ä" => BFOperations::StartLoop,
"ä" => BFOperations::EndLoop,
"?" => BFOperations::WriteToDebugTape,
_ => BFOperations::Other,
}
}
fn exec(&mut self, skip: bool) -> bool {
while self.pos < self.instructions.len() {
if self.cell >= self.tape.len() {
self.tape.push('\0');
}
if self.instructions[self.pos] == BFOperations::StartLoop {
self.pos += 1;
let old = self.pos;
while self.exec(self.tape[self.cell] == '\0') == true {
self.pos = old;
}
} else if self.instructions[self.pos] == BFOperations::EndLoop {
return self.tape[self.cell] != '\0';
} else if skip == false {
match self.instructions[self.pos] {
BFOperations::IncreasePointer => self.cell += 1,
BFOperations::DecreasePointer => self.cell -= 1,
BFOperations::IncreaseCell => {
let i = self.tape[self.cell] as u8;
self.tape[self.cell] = if i == 255 {
'\0'
} else {
(i + 1u8) as char
}
},
BFOperations::DecreaseCell => {
let i = self.tape[self.cell] as u8;
self.tape[self.cell] = if i == 0 {
254u8 as char
} else {
(i - 1u8) as char
}
},
BFOperations::WriteStdout => print!("{}", self.tape[self.cell]),
BFOperations::ReadStdin => {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
let bytes = input.bytes().nth(0).expect("no byte read") as char;
self.tape[self.cell] = bytes;
},
BFOperations::WriteToDebugTape => self.debug.push(self.tape[self.cell]),
_ => {
self.pos += 1;
continue;
},
};
};
self.pos += 1;
};
return false;
}
pub fn run(&mut self) {
self.exec(false);
}
}
#[cfg(test)]
mod test {
use super::BF;
#[test]
fn hello_world() {
let mut b = BF::new(
String::from("ââââââââÄÁââââÄÁââÁâââÁâââÁâÀÀÀÀãäÁâÁâÁãÁÁâÄÀäÀãäÁÁ?Áããã?âââââââ??âââ?ÁÁ?Àã?À?âââ?ãããããã?ãããããããã?ÁÁâ?")
);
b.run();
assert_eq!(
b.debug,
vec!['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!']
)
}
}
mod interpreter;
use std::{env, fs};
fn main() {
let path = env::args()
.nth(1)
.expect("no path given");
let contents = fs::read_to_string(path).expect("Error opening file");
interpreter::BF::new(contents).run();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment