From 146f12187abbe8ba18df8f1d417a44cfe557b794 Mon Sep 17 00:00:00 2001 From: Matthew Hall Date: Fri, 2 Sep 2022 22:06:13 +1200 Subject: Able to interpret brainfuck --- src/brainfuck/program.cr | 75 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 2 deletions(-) (limited to 'src/brainfuck/program.cr') diff --git a/src/brainfuck/program.cr b/src/brainfuck/program.cr index cf4a097..5994d40 100644 --- a/src/brainfuck/program.cr +++ b/src/brainfuck/program.cr @@ -1,14 +1,85 @@ require "./parser.cr" class Brainfuck::Program - def initialize(@parser : Brainfuck::Parser) + @mem_size : Int32 + + def initialize(@parser : Parser, mem_size : Int32?) + @mem_size = mem_size || DEFAULT_TAPE_SIZE end def interpret - puts @parser.parse + code = @parser.parse + jumps = find_jumps(code) + code_ptr = 0 + + memory = [0_u8] * @mem_size + mem_ptr = 0 + + while code_ptr < code.size + case code[code_ptr] + when Opcode::PtrRight + mem_ptr += 1 + + when Opcode::PtrLeft + mem_ptr -= 1 + + when Opcode::Inc + begin + memory[mem_ptr] += 1_u8 + rescue OverflowError + memory[mem_ptr] = 0_u8 + end + + when Opcode::Dec + begin + memory[mem_ptr] -= 1_u8 + rescue OverflowError + memory[mem_ptr] = 0_u8 + end + + when Opcode::Out + print memory[mem_ptr].chr + + when Opcode::In + c = STDIN.read_char + memory[mem_ptr] = c.nil? ? 0_u8 : c.ord.to_u8 + + when Opcode::LoopStart + code_ptr = jumps[code_ptr] if memory[mem_ptr] == 0_u8 + + when Opcode::LoopEnd + code_ptr = jumps[code_ptr] unless memory[mem_ptr] == 0_u8 + + end + + raise MemoryError.new("Too far left") if mem_ptr < 0 + raise MemoryError.new("Too far right") if mem_ptr >= memory.size + + code_ptr += 1 + end end def compile + raise NotImplementedError.new + end + + # assumes valid code + private def find_jumps(code : Array(Opcode)) : Hash(Int32, Int32) + jumps = Hash(Int32, Int32).new + stack = [] of Int32 + + code.each_index do |i| + if code[i] == Opcode::LoopStart + stack.push(i) + end + + if code[i] == Opcode::LoopEnd + jumps[i] = stack.pop + jumps[jumps[i]] = i + end + end + + return jumps end end -- cgit v1.2.1