Created
July 20, 2015 04:07
-
-
Save 5thWall/94f7a1c19dc10ff07186 to your computer and use it in GitHub Desktop.
Implementation of a BrainF*** interpreter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'memory' | |
require 'tape' | |
class BrainLuckMachine | |
attr_accessor :tape, :input, :output, :memory | |
def initialize(code, input) | |
@tape = Tape.new(code) | |
@input = input.codepoints | |
@output = '' | |
@memory = Memory.new | |
end | |
def run | |
loop do | |
cmd = tape.incr_tape | |
return output if cmd == :EOF | |
send(cmd) | |
end | |
end | |
private | |
def incr_data_ptr | |
memory.incr_ptr | |
end | |
def decr_data_ptr | |
memory.decr_ptr | |
end | |
def incr_data | |
memory.incr | |
end | |
def decr_data | |
memory.decr | |
end | |
def put_output | |
output << memory.current.chr | |
end | |
def save_input | |
memory.save(input.first) | |
self.input = input.drop(1) | |
end | |
def jump_forward | |
tape.jump_forward if memory.zero? | |
end | |
def jump_back | |
tape.jump_back unless memory.zero? | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Memory | |
attr_reader :memory, :ptr | |
def initialize | |
@memory = [] | |
@ptr = 0 | |
end | |
def incr_ptr | |
@ptr += 1 | |
memory[ptr] ||= 0 | |
end | |
def decr_ptr | |
if ptr < 0 | |
@ptr = 0 | |
memory.insert(0, 0) | |
else | |
@ptr -= 1 | |
end | |
end | |
def incr | |
memory[ptr] += 1 | |
memory[ptr] = 0 if current > 255 | |
end | |
def decr | |
memory[ptr] -= 1 | |
memory[ptr] = 255 if current < 0 | |
end | |
def save(input) | |
memory[ptr] = input | |
end | |
def current | |
memory[ptr] | |
end | |
def zero? | |
current.zero? | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Tape | |
COMMANDS = { | |
'>' => :incr_data_ptr, | |
'<' => :decr_data_ptr, | |
'+' => :incr_data, | |
'-' => :decr_data, | |
'.' => :put_output, | |
',' => :save_input, | |
'[' => :jump_forward, | |
']' => :jump_back | |
} | |
attr_reader :code, :ptr | |
def initialize(code) | |
@code = code.chars.each_with_index.map do |char, i| | |
COMMANDS.fetch(char) do |_| | |
fail "Syntax Error at #{i}: Could not parse '#{char}'" | |
end | |
end | |
@ptr = -1 | |
end | |
def cur_cmd | |
return :EOF if ptr < 0 | |
code[ptr] || :EOF | |
end | |
def incr_tape | |
@ptr += 1 | |
cur_cmd | |
end | |
def decr_tape | |
@ptr -= 1 | |
cur_cmd | |
end | |
def jump_forward(count = 0) | |
cmd = incr_tape | |
fail "EOF Reached Unexpectedly" if cmd == :EOF | |
return cmd if count == 0 && cmd == :jump_back | |
count += 1 if cmd == :jump_forward | |
count -= 1 if cmd == :jump_back | |
jump_forward(count) | |
end | |
def jump_back(count = 0) | |
cmd = decr_tape | |
fail "BOF Reached Unexpectedly" if cmd == :EOF | |
return cmd if count == 0 && cmd == :jump_forward | |
count -= 1 if cmd == :jump_forward | |
count += 1 if cmd == :jump_back | |
jump_back(count) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment