Last active
January 23, 2024 03:40
-
-
Save eliascotto/a99225ff71a81ec31219fc3a834872e2 to your computer and use it in GitHub Desktop.
Brainfuck interpreter in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::io::{self, Write}; | |
struct Memory { | |
cells: Vec<i32>, | |
pointer: usize, | |
} | |
fn bf_runtime(m: &mut Memory, s: String) { | |
let instructions: &[u8] = s.as_bytes(); | |
let mut idx: usize = 0; | |
let mut with_output = false; | |
loop { | |
if idx > instructions.len() - 1 { | |
break; | |
} | |
// String is transformed to byte, than indexed, and then transformed into char | |
// UTF-8 | |
let c: char = instructions[idx] as char; | |
match c { | |
'>' => { | |
if m.pointer >= m.cells.len() { | |
m.cells.extend_from_slice(&[0, 1000]); | |
} | |
m.pointer += 1; | |
}, | |
'<' => { | |
m.pointer -= 1; | |
}, | |
'+' => { | |
m.cells[m.pointer] += 1; | |
}, | |
'-' => { | |
m.cells[m.pointer] -= 1; | |
}, | |
'.' => { | |
with_output = true; | |
let n = char::from_u32(m.cells[m.pointer] as u32).unwrap(); | |
print!("{}", n); | |
io::stdout().flush().unwrap(); | |
}, | |
',' => { | |
print!("input: "); | |
io::stdout().flush().unwrap(); | |
let mut input_str = String::new(); | |
let n_bytes = io::stdin() | |
.read_line(&mut input_str) | |
.unwrap(); | |
if n_bytes > 0 { | |
let bytes = input_str.as_bytes(); | |
m.cells[m.pointer] = bytes[0] as i32; | |
} | |
}, | |
'[' => { | |
if m.cells[m.pointer] == 0 { | |
let mut lvl = 0; | |
let mut counter = 1; | |
loop { | |
let nc: char = instructions[idx + counter] as char; | |
match nc { | |
'[' => lvl += 1, | |
']' => { | |
if lvl > 0 { | |
lvl -= 1; | |
} else { | |
break; | |
} | |
}, | |
_ => {}, | |
} | |
counter += 1 | |
} | |
idx += counter + 1; | |
continue; | |
} | |
}, | |
']' => { | |
if m.cells[m.pointer] != 0 { | |
let mut lvl = 0; | |
let mut counter = 1; | |
loop { | |
let nc: char = instructions[idx - counter] as char; | |
match nc { | |
']' => lvl += 1, | |
'[' => { | |
if lvl > 0 { | |
lvl -= 1; | |
} else { | |
break; | |
} | |
}, | |
_ => {}, | |
} | |
counter += 1 | |
} | |
idx -= counter; | |
continue; | |
} | |
}, | |
_ => {}, | |
} | |
idx += 1; | |
} | |
if with_output { | |
println!() | |
} | |
} | |
fn main() { | |
println!("BrainFuck REPL 1.0"); | |
let mut m = Memory { cells: vec![0; 1000], pointer: 0 }; | |
loop { | |
let mut s: String = String::new(); | |
print!("> "); | |
io::stdout().flush().unwrap(); | |
let num_bytes = io::stdin().read_line(&mut s).expect("Did not enter a correct string"); | |
if num_bytes == 0 { | |
break; | |
} else { | |
bf_runtime(&mut m, s); | |
m = Memory { cells: vec![0; 1000], pointer: 0 }; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment