Skip to content

Instantly share code, notes, and snippets.

@llllllllll
Created May 4, 2017 04:36
Show Gist options
  • Save llllllllll/752ec733900387fb66ca6f6cdaaf4b28 to your computer and use it in GitHub Desktop.
Save llllllllll/752ec733900387fb66ca6f6cdaaf4b28 to your computer and use it in GitHub Desktop.
#![feature(use_extern_macros)]
use std::io::Read;
struct State {
program: Vec<u8>,
ipt: usize,
tape: [u8; 30000],
ptr: usize,
control_stack: Vec<usize>,
}
impl State {
pub fn new(program: Vec<u8>) -> State {
State {
program: program,
ipt: 0,
tape: [0; 30000],
ptr: 0,
control_stack: vec![],
}
}
fn step(self) -> Option<State> {
let new = match self.program[self.ipt] {
b'+' => {
let mut new = self;
new.tape[new.ptr] = new.tape[new.ptr].wrapping_add(1);
new.ipt += 1;
new
},
b'-' => {
let mut new = self;
new.tape[new.ptr] = new.tape[new.ptr].wrapping_sub(1);
new.ipt += 1;
new
},
b'>' => Self { ptr: self.ptr + 1, ipt: self.ipt + 1, .. self },
b'<' => Self { ptr: self.ptr - 1, ipt: self.ipt + 1, .. self },
b'.' => {
print!("{}", self.tape[self.ptr] as char);
Self { ipt: self.ipt + 1, .. self }
},
b',' => {
let value = match std::io::stdin().bytes().next() {
Some(v) => v.unwrap(),
_ => std::panic!("failed to read input"),
};
let mut new = self;
new.tape[new.ptr] = value;
new.ipt += 1;
new
},
b'[' => {
let mut new = self;
if new.tape[new.ptr] != 0 {
new.control_stack.push(new.ipt);
}
else {
let mut found = false;
let mut stack = 0;
for n in new.ipt + 1..new.program.len() {
match new.program[n] {
b'[' => {
stack += 1;
},
b']' => {
if stack == 0 {
new.ipt = n;
found = true;
break
}
stack -= 1;
},
_ => {},
}
}
if !found {
std::panic!("unmatched '['");
}
}
new.ipt += 1;
new
},
b']' => {
let mut new = self;
new.ipt = new.control_stack.pop().unwrap();
new
}
_ => Self { ipt: self.ipt + 1, .. self },
};
if new.ipt == new.program.len() {
None
}
else {
Some(new)
}
}
pub fn run(self) {
let mut state = self;
loop {
state = match state.step() {
Some(new) => new,
None => break,
}
}
}
}
fn main() {
let mut program = Vec::new();
match std::io::stdin().read_to_end(&mut program) {
Ok(_) => {
State::new(program).run();
()
},
Err(e) => {
println!("{}", e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment