HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Self-modifying esoteric language interpreter in Ruby

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
interpreterrubylanguageesotericmodifyingself

Problem

I recently created Copy, an esoteric language, and wrote an implementation in Ruby.

The language has only 7 instructions:

  • copy Copy the code block from a to b at c



  • remove Remove the code block from a to b



  • skip Skip the next instruction if value is not 0



  • add Add value to var



  • negate Negate var



  • print Print value as an ASCII character



  • getch Read a character and store it character code in var



All addresses are relative and values can be variables or signed integers,

require "io/console"

class Copy
    def initialize(code)
        @code = code.lines.map &:chomp
        @len = @code.length*2
        @i = 0
        @vars = {}
    end

    def value(s)
        if s =~ /-?\d+/
            s.to_i
        else
            @vars[s] or 0
        end
    end

    def step
        while @code.length > @len do
            @code.shift
            @i -= 1
        end
        line = @code[@i].split " "
        case line[0]
        when "copy"
            @code.insert(
                @i + value(line[3]),
                *@code.slice((@i + value(line[1]))..(@i + value(line[2])))
                )
        when "remove"
            @code.slice!((@i + value(line[1]))..(@i + value(line[2])))
        when "skip"
            if value(line[1]) != 0
                @i += 1
            end
        when "add"
            @vars[line[1]] = (@vars[line[1]] or 0) + value(line[2])
        when "negate"
            @vars[line[1]] *= -1
        when "print"
            STDOUT.write value(line[1]).chr
        when "getch"
            @vars[line[1]] = STDIN.getch.ord
        end
        @i += 1
    end

    def run
        while @i "
    end

    c = Copy.new File.read(ARGV[0])
    c.run
end


Truth machine (If the input is 0, print 0 and exit, if the input is 1, print 1 in an infinite loop):

getch a
add b a
add b -48
print a
skip b
skip 1
copy -4 0 1


I am not really good at Ruby, can someone review this?

Solution

I would suggest refactoring the switch. This would make scaling easier

def remove_callback
     @code.slice!((@i + value(line[1]))..(@i + value(line[2])))
   end

   ...

   line = @code[@i].split " "
   self.send("#{line[0]}_callback")

Code Snippets

def remove_callback
     @code.slice!((@i + value(line[1]))..(@i + value(line[2])))
   end

   ...

   line = @code[@i].split " "
   self.send("#{line[0]}_callback")

Context

StackExchange Code Review Q#142407, answer score: 3

Revisions (0)

No revisions yet.