I have found this page with various benchmarks, some of them are in Rust:
So I’ve written various improved versions of them, in Python, D and Rust.
Here I’ve just explained some of my improvements to the Brainfuck D version:
I have tried to port some of the D improvements to Rust, but I am not yet very good in Rust, and I think Rust offers less ways to improve this kind of code:
use std::io::{ stdout, Read, Write };
struct Tape {
pos: usize,
tape: Vec<u32>
}
impl Tape {
fn new() -> Tape { Tape { pos: 0, tape: vec![0; 100_000] } }
fn get(&self) -> u32 { self.tape[self.pos] }
fn getc(&self) -> char { self.get() as u8 as char }
fn inc(&mut self) { self.tape[self.pos] += 1; }
fn dec(&mut self) { self.tape[self.pos] -= 1; }
fn advance(&mut self) { self.pos += 1; }
fn devance(&mut self) { if self.pos > 0 { self.pos -= 1; } }
}
struct Program {
code: Vec<char>,
bracket_map: Vec<usize>
}
impl Program {
fn new(content: String) -> Program {
let mut code = Vec::new();
let mut bracket_map = vec![0; content.len()];
let mut leftstack = Vec::new();
let mut pc = 0;
for c in content.chars() {
match c {
'+' | '-' | '.' | ',' | '<' | '>' => (),
'[' => { leftstack.push(pc); },
']' => match leftstack.pop() {
Some(left) => { bracket_map[left] = pc;
bracket_map[pc] = left; }
None => () // Error?
},
_ => { continue; } // ',' ignored.
}
code.push(c);
pc += 1;
}
Program { code: code, bracket_map: bracket_map }
}
fn run(&self) {
let mut pc = 0;
let len = self.code.len();
let mut tape = Tape::new();
unsafe {
while pc < len {
match *self.code.get_unchecked(pc) {
'+' => tape.inc(),
'-' => tape.dec(),
'>' => tape.advance(),
'<' => tape.devance(),
'[' => { if tape.get() == 0 { pc = *self.bracket_map.get_unchecked(pc); } },
']' => { if tape.get() != 0 { pc = *self.bracket_map.get_unchecked(pc); } },
'.' => { print!("{}", tape.getc()); stdout().flush().unwrap() },
_ => () // ',' ignored.
}
pc += 1;
}
}
}
}
fn main() {
use std::fs::{ File };
use std::env::{ args };
let file_name = args().nth(1).unwrap();
let mut code = String::new();
File::open(&file_name).unwrap().read_to_string(&mut code).unwrap();
Program::new(code).run()
}
Currently D language unfortunately doesn’t have computed gotos, but I’ve found a workaround. In Rust how do you write a fast interpreter? (https://en.wikipedia.org/wiki/Threaded_code ). The final D version is much faster than this improved Rust version. Help and suggestions are welcome.
Edit: the main point of this thread is to ask for ideas for possible improvements of Rust to implement simple but “fast enough” interpreters and FSMs. A possible idea is some restricted version of goto like in my last D version, but more explicit, so the optimization is deterministic.