1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
use std::io::{Read, Write}; use state::State; use common::BfResult; use traits::Interpretable; use super::*; impl Interpretable for Program { fn interpret_state<R: Read, W: Write>( &self, mut state: State, mut input: R, mut output: W) -> BfResult<()> { interpret(self, &mut state, &mut input, &mut output) } } fn interpret<R, W>(instructions: &Program, state: &mut State, input: &mut R, output: &mut W) -> BfResult<()> where R: Read, W: Write { use common::Instruction::*; let mut pc = 0; while pc < instructions.len() { match instructions[pc] { Left(count) => state.left(count)?, Right(count) => state.right(count)?, Add(count) => state.up(count), In => state.read(input), Out => state.write(output), JumpZero(address) => { if state.load() == 0 { pc = address as usize; } } JumpNotZero(address) => { if state.load() != 0 { pc = address as usize; } } SetZero => state.store(0), OffsetAddRight(offset) => { if state.load() != 0 { let value = state.load(); state.store(0); state.up_pos_offset(offset, value)?; } } OffsetAddLeft(offset) => { if state.load() != 0 { let value = state.load(); state.store(0); state.up_neg_offset(offset, value)?; } } FindZeroRight(offset) => { while state.load() != 0 { state.right(offset)?; } } FindZeroLeft(offset) => { while state.load() != 0 { state.left(offset)?; } } } pc += 1; } Ok(()) } #[cfg(test)] mod tests { use test_helpers::*; #[test] fn hello_world() { assert_parse_interpret(HELLO_WORLD_SRC, "", "Hello, World!"); } #[test] fn factoring() { assert_parse_interpret(FACTOR_SRC, "2\n", "2: 2\n"); assert_parse_interpret(FACTOR_SRC, "3\n", "3: 3\n"); assert_parse_interpret(FACTOR_SRC, "6\n", "6: 2 3\n"); assert_parse_interpret(FACTOR_SRC, "100\n", "100: 2 2 5 5\n"); } fn assert_parse_interpret(program: &[u8], input: &str, output: &str) { let program = ::ast::parse_program(program).unwrap(); let program = ::rle::compile(&program); let program = ::peephole::compile(&program); let program = ::bytecode::compile(&program); assert_interpret(&*program, input.as_bytes(), output.as_bytes()); } }