Execute Brain****/Brat

From Rosetta Code
Execute Brain****/Brat is an implementation of Brainf***. Other implementations of Brainf***.
Execute Brain****/Brat is part of RCBF. You may find other members of RCBF at Category:RCBF.

An implementation of a Brainf*** interpreter in Brat.

Does not handle EOF when getting input. Tape is "infinite" in the positive direction. Each cell holds an integer.

#BF machine
bf = object.new
 
#Initialize with array of instructions
bf.init = { instructions |
my.instructions = instructions
my.program_counter = 0
my.pointer = 0
my.tape = []
calculate_jumps
 
#Override my.tape[] to return 0 instead of null
my.tape.original_get = my.tape->get
my.tape.get = { index |
val = my.original_get index
null? val
{ 0 }
{ val }
}
}
 
#Run instructions
bf.prototype.run = {
current_instruction = null
 
while { current_instruction = instructions[my.program_counter] }
{
action = my.interpreter[current_instruction]
action
 
my.program_counter = my.program_counter + 1
}
}
 
#Holds all operations
bf.interpreter = [:]
 
bf.interpreter[:>] = {
my.pointer = my.pointer + 1
}
 
bf.interpreter[:<] = {
my.pointer = my.pointer - 1
}
 
bf.interpreter[:+] = {
my.tape[my.pointer] = my.tape[my.pointer] + 1
}
 
bf.interpreter[:-] = {
my.tape[my.pointer] = my.tape[my.pointer] - 1
}
 
bf.interpreter["."] = {
print my.tape[my.pointer].to_char
}
 
bf.interpreter[","] = {
my.tape[my.pointer] = g.to_byte
}
 
bf.interpreter["["] = {
true? my.tape[my.pointer] == 0
{ my.program_counter = my.jumps[my.program_counter] }
}
 
bf.interpreter["]"] = {
false? my.tape[my.pointer] == 0
{ my.program_counter = my.jumps[my.program_counter] }
}
 
#Precalcuate '[' and ']' jump locations
bf.prototype.calculate_jumps = {
forwards = []
jumps = [:]
 
my.instructions.each_with_index { ins, index |
when { ins == "[" } { forwards << index }
{ ins == "]" } {
match = forwards.pop
jumps[match] = index
jumps[index] = match
}
}
 
my.jumps = jumps
}
 
#Get file name from user and run it
include :file
 
bf.new(file.read(ask "BF file: ").dice).run