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
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 { for instruction in instructions { interpret_instruction(instruction, state, input, output)?; } Ok(()) } #[inline] fn interpret_instruction<R, W>(instruction: &Statement, state: &mut State, input: &mut R, output: &mut W) -> BfResult<()> where R: Read, W: Write { use self::Statement::*; use common::Command::*; match *instruction { Cmd(Left, count) => state.left(count)?, Cmd(Right, count) => state.right(count)?, Cmd(Up, count) => state.up(count as u8), Cmd(Down, count) => state.down(count as u8), Cmd(In, count) => { for _ in 0 .. count { state.read(input); } } Cmd(Out, count) => { for _ in 0 .. count { state.write(output); } } Cmd(Begin, _) | Cmd(End, _) => panic!("Invalid opcode"), Loop(ref program) => { while state.load() != 0 { interpret(program, state, input, output)?; } } } 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); assert_interpret(&*program, input.as_bytes(), output.as_bytes()); } }