I've seen a lot of Brainf**k interpreters in various languages. I decided that actually interpreting Brainf**k is too hard, so instead of that, I wrote a 'compiler' in Ruby that directly transcribes BF to Ruby code. This is Version 1.0, and I'm looking for any tips on how to make it more efficient.
There are a few things that really bug me:
replacements
feels like it's messed up somehow, but I can't put my finger on how.$stdin.readbyte
feels entirely too long, but I can't find an alternative that's shorter.- Should I be using
$stdin
at all?
input_file = $ARGV[0]
output_file = $ARGV[1]
start = <<-END.gsub(/[ \t]*\|/, '')
|# Automatically generated by bf_to_ruby.rb
|# Source available at GitHub
|data = Hash.new(0)
|pointer = 0
END
replacements = [
{ replacing: '+', replacement: 'data[pointer] += 1' },
{ replacing: '-', replacement: 'data[pointer] -= 1' },
{ replacing: '>', replacement: 'pointer += 1' },
{ replacing: '<', replacement: 'pointer -= 1' },
{ replacing: '.', replacement: 'putc data[pointer]' },
{ replacing: ',', replacement: 'data[pointer] = $stdin.readbyte' },
{ replacing: '[', replacement: 'until data[pointer] == 0' },
{ replacing: ']', replacement: 'end' },
]
output = open(output_file, File::CREAT | File::WRONLY)
output.puts(start)
open(input_file, File::RDONLY) do |input|
input.each_char do |char|
replacements.each do |data|
if data[:replacing] == char
output.puts(data[:replacement])
end
end
end
end
Demo
Input:
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
Output:
# Automatically generated by bf_to_ruby.rb # Source available at GitHub data = Hash.new(0) pointer = 0 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 until data[pointer] == 0 pointer += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 until data[pointer] == 0 pointer += 1 data[pointer] += 1 data[pointer] += 1 pointer += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 pointer += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 pointer += 1 data[pointer] += 1 pointer -= 1 pointer -= 1 pointer -= 1 pointer -= 1 data[pointer] -= 1 end pointer += 1 data[pointer] += 1 pointer += 1 data[pointer] += 1 pointer += 1 data[pointer] -= 1 pointer += 1 pointer += 1 data[pointer] += 1 until data[pointer] == 0 pointer -= 1 end pointer -= 1 data[pointer] -= 1 end pointer += 1 pointer += 1 $stdout.putc data[pointer] pointer += 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 $stdout.putc data[pointer] data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 $stdout.putc data[pointer] $stdout.putc data[pointer] data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 $stdout.putc data[pointer] pointer += 1 pointer += 1 $stdout.putc data[pointer] pointer -= 1 data[pointer] -= 1 $stdout.putc data[pointer] pointer -= 1 $stdout.putc data[pointer] data[pointer] += 1 data[pointer] += 1 data[pointer] += 1 $stdout.putc data[pointer] data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 $stdout.putc data[pointer] data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 data[pointer] -= 1 $stdout.putc data[pointer] pointer += 1 pointer += 1 data[pointer] += 1 $stdout.putc data[pointer] pointer += 1 data[pointer] += 1 data[pointer] += 1 $stdout.putc data[pointer]
Both, when run, output:
Hello World!
$$
because I knew I would never make any money with the thing. \$\endgroup\$