wrote interpreter source code
This commit is contained in:
+96
-2
@@ -1,3 +1,97 @@
|
|||||||
fn main() {
|
use anyhow::Result;
|
||||||
println!("Hello, world!");
|
use anyhow::anyhow;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
use std::fs;
|
||||||
|
fn clean_code(code: &str) -> Vec<char> {
|
||||||
|
let vec: Vec<char> = code.chars().collect();
|
||||||
|
let clean = vec
|
||||||
|
.into_iter()
|
||||||
|
.filter(|b| "+-<>,.[]".contains(*b))
|
||||||
|
.collect();
|
||||||
|
clean
|
||||||
|
}
|
||||||
|
fn precompute_jump_table(code: &[char]) -> Result<HashMap<usize, usize>> {
|
||||||
|
let mut jump_table = HashMap::new();
|
||||||
|
let mut stack = Vec::new();
|
||||||
|
for (i, &char) in code.iter().enumerate() {
|
||||||
|
if char == '[' {
|
||||||
|
stack.push(i);
|
||||||
|
} else if char == ']' {
|
||||||
|
match stack.pop() {
|
||||||
|
Some(start_index) => {
|
||||||
|
jump_table.insert(start_index, i);
|
||||||
|
jump_table.insert(i, start_index);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(anyhow!("miss matching closing brackets at index {}", i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !stack.is_empty() {
|
||||||
|
return Err(anyhow!("open brackets unclosed"));
|
||||||
|
}
|
||||||
|
Ok(jump_table)
|
||||||
|
}
|
||||||
|
fn execute(raw_code: &str) -> Result<()> {
|
||||||
|
let clean = clean_code(raw_code);
|
||||||
|
let jump_table = precompute_jump_table(&clean)?;
|
||||||
|
let mut tape: [u8; 30000] = [0; 30000];
|
||||||
|
let mut data_ptr: usize = 0;
|
||||||
|
let mut exec_ptr: usize = 0;
|
||||||
|
while exec_ptr < clean.len() {
|
||||||
|
let cmd = clean[exec_ptr];
|
||||||
|
match cmd {
|
||||||
|
'+' => {
|
||||||
|
tape[data_ptr] = tape[data_ptr].wrapping_add(1);
|
||||||
|
}
|
||||||
|
'-' => {
|
||||||
|
tape[data_ptr] = tape[data_ptr].wrapping_sub(1);
|
||||||
|
}
|
||||||
|
'>' => {
|
||||||
|
data_ptr += 1;
|
||||||
|
if data_ptr > 29999 {
|
||||||
|
data_ptr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'<' => {
|
||||||
|
if data_ptr == 0 {
|
||||||
|
data_ptr = 29999;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data_ptr -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
',' => {
|
||||||
|
let mut buf = [0; 1];
|
||||||
|
if io::stdin().read_exact(&mut buf).is_ok() {
|
||||||
|
tape[data_ptr] = buf[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'.' => {
|
||||||
|
print!("{}", tape[data_ptr] as char);
|
||||||
|
let _ = io::stdout().flush();
|
||||||
|
}
|
||||||
|
'[' => {
|
||||||
|
if tape[data_ptr] == 0 {
|
||||||
|
exec_ptr = *jump_table.get(&exec_ptr).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
']' => {
|
||||||
|
if tape[data_ptr] != 0 {
|
||||||
|
exec_ptr = *jump_table.get(&exec_ptr).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
exec_ptr += 1;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let code_path = std::env::args().nth(1).ok_or_else(|| anyhow!("Usage: bf <path to file.bf>"))?;
|
||||||
|
let code = fs::read_to_string(&code_path)?;
|
||||||
|
execute(&code)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user