Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::collections::HashMap;
- #[derive(Debug)]
- enum Instruction {
- Move(isize),
- Increment(u8),
- Decrement(u8),
- Loop(Procedure),
- Output,
- Input,
- EOF,
- }
- type Procedure = Vec<Instruction>;
- fn compile_program(program: &str) -> Procedure {
- let mut procedure = compile(program);
- procedure.push(Instruction::EOF);
- procedure
- }
- fn compile(program: &str) -> Procedure {
- let mut procedure: Procedure = vec![];
- let pairs = build_pairs(program);
- let mut i = 0;
- let mut trailing = ' ';
- let mut trailing_val = 0;
- while i < program.len() {
- // Get the current instruction in the feed
- let instr = program.chars().nth(i).expect("No instructions in program");
- // If the trailing character is not already set to the incoming instruction (it's the start
- // of a new possible trail), take whatever was previously trailing, and push it to our
- // procedure
- if trailing != instr {
- match trailing {
- '>' | '<' => procedure.push(Instruction::Move(trailing_val)),
- '+' => procedure.push(Instruction::Increment(trailing_val as u8)),
- '-' => procedure.push(Instruction::Decrement(trailing_val as u8)),
- _ => (),
- }
- trailing = instr;
- trailing_val = 0;
- }
- match instr {
- '>' | '<' | '+' | '-' => match instr {
- '>' | '+' | '-' => trailing_val += 1,
- '<' => trailing_val -= 1,
- _ => (),
- },
- '[' => {
- procedure.push(Instruction::Loop(compile(
- &program[i + 1..pairs[&i]].chars().collect::<String>(),
- )));
- i = pairs[&i];
- }
- '.' => {
- procedure.push(Instruction::Output);
- }
- ',' => {
- procedure.push(Instruction::Input);
- }
- _ => (),
- }
- i += 1;
- }
- match trailing {
- '>' | '<' => procedure.push(Instruction::Move(trailing_val)),
- '+' => procedure.push(Instruction::Increment(trailing_val as u8)),
- '-' => procedure.push(Instruction::Decrement(trailing_val as u8)),
- _ => (),
- }
- procedure
- }
- struct Computer {
- memory: Vec<u8>,
- pointer: isize,
- }
- impl Computer {
- fn new() -> Self {
- Computer {
- memory: vec![0; 30000],
- pointer: 0,
- }
- }
- fn run(&mut self, procedure: &Procedure) {
- self.run_procedure(procedure);
- }
- fn run_procedure(&mut self, procedure: &Procedure) {
- for instruction in procedure {
- match instruction {
- Instruction::Move(n) => {
- self.pointer += n;
- }
- Instruction::Increment(n) => {
- self.memory[self.pointer as usize] =
- self.memory[self.pointer as usize].wrapping_add(*n);
- }
- Instruction::Decrement(n) => {
- self.memory[self.pointer as usize] =
- self.memory[self.pointer as usize].wrapping_sub(*n);
- }
- Instruction::Output => {
- print!("{}", self.memory[self.pointer as usize] as char);
- }
- Instruction::Loop(proc) => {
- if self.memory[self.pointer as usize] > 0 {
- self.run_procedure(&proc);
- }
- }
- Instruction::EOF => {
- return;
- }
- _ => (),
- }
- }
- if self.memory[self.pointer as usize] != 0 {
- self.run_procedure(procedure);
- }
- }
- }
- fn build_pairs(program: &str) -> HashMap<usize, usize> {
- let mut stack_depth = 0;
- let mut stack: Vec<usize> = vec![];
- let mut stack_map: HashMap<usize, usize> = HashMap::new();
- let mut i = 0;
- while i < program.len() {
- let instruction = program.chars().nth(i).expect("No instructions in program");
- match instruction {
- '[' => {
- stack_depth += 1;
- stack.push(i);
- }
- ']' => {
- let opening_brace = stack.pop().expect("No opening brace");
- stack_map.insert(opening_brace, i);
- }
- _ => (),
- }
- i += 1;
- }
- stack_map
- }
- fn main() {
- let program = std::fs::read_to_string("adv.b").unwrap();
- let procedure = compile_program(&program);
- let mut pc: Computer = Computer::new();
- pc.run(&procedure);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement