patternrubyMinor
Self-modifying esoteric language interpreter in Ruby
Viewed 0 times
interpreterrubylanguageesotericmodifyingself
Problem
I recently created Copy, an esoteric language, and wrote an implementation in Ruby.
The language has only 7 instructions:
All addresses are relative and values can be variables or signed integers,
Truth machine (If the input is 0, print 0 and exit, if the input is 1, print 1 in an infinite loop):
I am not really good at Ruby, can someone review this?
The language has only 7 instructions:
copyCopy the code block fromatobatc
removeRemove the code block fromatob
skipSkip the next instruction ifvalueis not 0
addAddvaluetovar
negateNegatevar
printPrintvalueas an ASCII character
getchRead a character and store it character code invar
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
endTruth 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 1I 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.