Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
101 lines (91 sloc) 2.08 KB
GC.disable
Tape = ObjectSpace
class Cell
attr_accessor :symbol
def initialize(s)
@symbol = s
end
end
class BF
def initialize
@max_id = 0
end
def run(src)
state = {pc: 0, head: 0, op: src[0]}
inc = last = 0
clocked = false
_, jump = src.chars.each_with_object([[], {}]).with_index do |(c, (s, b)), i|
case c
when "["
s << i
when "]"
b[s.pop] = i
end
[s, b]
end
# initialize tape
put_cell(0)
put_cell(state.dup)
# run
Tape.each_object(Cell) do |cell|
next if cell.symbol.nil?
if sentinel?(cell)
last = inc-1
inc = 0
clocked = false
state[:pc] += 1
break if state[:pc] >= src.size
state[:op] = src[state[:pc]]
put_cell(state.dup.merge(last: last))
next
end
cell = put_cell(cell.symbol)
if inc == state[:head] && !clocked
case state[:op]
when ?> then state[:head]+=1; put_cell(0) if state[:head] > last
when ?< then state[:head]-=1
when ?+ then (cell.symbol > 255) ? cell.symbol=0 : cell.symbol+=1
when ?- then (cell.symbol <= 0) ? cell.symbol=255 : cell.symbol-=1
when ?. then print cell.symbol.chr
when ?, then cell.symbol = getc
when ?[ then state[:pc] = jump[state[:pc]] if cell.symbol.zero?
when ?] then state[:pc] = jump.invert[state[:pc]] - 1
else raise "no order"
end
clocked = true
end
inc += 1
end
end
def history
puts "TAPE HISTORY"
Tape.each_object(Cell) do |cell|
next if cell.symbol.nil?
if sentinel?(cell)
puts "..."
puts cell.symbol
puts "-" * 20
next
end
print cell.symbol.to_s + "|"
end
end
private
def sentinel?(cell)
cell.symbol.is_a?(Hash)
end
def put_cell(s)
begin
c = Cell.new(nil)
end while @max_id > c.object_id
@max_id = c.object_id
c.symbol = s
return c
end
end
bf = BF.new
begin
bf.run(File.read(ARGV.last).gsub("\n", ""))
ensure
bf.history if ARGV[0] == "--history"
end
You can’t perform that action at this time.