# Brainf**k to Ruby interpreter — v3

I think this is about as good as it's gonna get, but just for kicks, let's do one more round of iterations.

As before, it's a very simple substitution from Brainfuck to Ruby, with fancy things like joining duplicate lines into one and indentation.

Some things that bug me:

• The regex (/\++|-+|<+|>+|[.,]/) feels like it can be simplified, but I can't figure out how.
• I feel like the map can be simplified, but I can't figure out how.
• The constant repetition of #{' ' * indent_level} bugs me, but I can't see how to get rid of it.
• indent_level being declared outside of the scope of each feels like an anti-pattern, but AFAICT there's no better way to do it.
input_file, output_file = ARGV

open(output_file, File::CREAT | File::WRONLY) do |output|
output.puts <<-END.gsub(/^[ \t]*\||\s*#@.*$/, '') |#!/usr/bin/env ruby |class Mem < Hash #@ Hash because it's more memory-efficient and allows negative values. | def initialize; super(0); end | def []=(i, val); super(i, val & 255); end |end |data = Mem.new |pointer = 0 END indent_level = 0 code.scan(/\++|-+|<+|>+|[.,]/) .map do |string| case string[0] when '+' #String of "+" next "#{' ' * indent_level}data[pointer] += #{string.length}" when '-' #String of "-" next "#{' ' * indent_level}data[pointer] -= #{string.length}" when '<' #String of "<" next "#{' ' * indent_level}pointer -= #{string.length}" when '>' #String of ">" next "#{' ' * indent_level}pointer += #{string.length}" when '[' #Single "[" ret = "#{' ' * indent_level}until data[pointer] == 0" indent_level += 1 next ret #Split it so that it's clear that indent is increased *after* the line when ']' #Single "]" indent_level -= 1 next "#{' ' * indent_level}end" when ',' #Single "," next "#{' ' * indent_level}data[pointer] =$stdin.readbyte"
when '.' #Single "."
next "#{'  ' * indent_level}putc data[pointer]"
end
end.each { |line| output.puts(line) }
end

• BTW: this is a compiler, not an interpreter. – Jörg W Mittag Jul 31 '15 at 11:19

"#{'  ' * indent_level}data[pointer]"

Could be #{' ' * indent_level}#{DATA}.
• Oh, like "#{'test'} test"? Yes, that's possible. I don't see why you'd do it though. – Fund Monica's Lawsuit Jun 24 '15 at 23:22
• Because this string (data[pointer]) is repeated several times. If you would ever have a reason to change it. You'd only have to change it once. – RubberDuck Jun 24 '15 at 23:23