4
\$\begingroup\$

Previous iteration.

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
code = IO.read(input_file).delete('^+-<>.,[]')
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
asked Jun 24, 2015 at 22:41
\$\endgroup\$
1
  • 1
    \$\begingroup\$ BTW: this is a compiler, not an interpreter. \$\endgroup\$ Commented Jul 31, 2015 at 11:19

1 Answer 1

5
\$\begingroup\$

I'm not 100% sure this works in Ruby, but can you use constants with string interpolation? This string is repeated a lot. I doubt it will ever change, but if it does, it would be nice to only have to change it once.

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

Could be #{' ' * indent_level}#{DATA}.

answered Jun 24, 2015 at 23:18
\$\endgroup\$
7
  • \$\begingroup\$ I'm not quite sure what you mean by "can you use constants with string interpolation?" \$\endgroup\$ Commented Jun 24, 2015 at 23:19
  • \$\begingroup\$ Can you inject a constant string value into another string using interpolation? I'm sure you can. I'm just not sure you can. \$\endgroup\$ Commented Jun 24, 2015 at 23:21
  • \$\begingroup\$ Oh, like "#{'test'} test"? Yes, that's possible. I don't see why you'd do it though. \$\endgroup\$ Commented Jun 24, 2015 at 23:22
  • 2
    \$\begingroup\$ 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. \$\endgroup\$ Commented Jun 24, 2015 at 23:23
  • \$\begingroup\$ And when would I ever need to change it? \$\endgroup\$ Commented Jun 25, 2015 at 1:13

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.