I recently created Copy, an esoteric language, and wrote an implementation in Ruby.
The language has only 7 instructions:
copy <a> <b> <c>
Copy the code block froma
tob
atc
remove <a> <b>
Remove the code block froma
tob
skip <value>
Skip the next instruction ifvalue
is not 0add <var> <value>
Addvalue
tovar
negate <var>
Negatevar
print <value>
Printvalue
as an ASCII charactergetch <var>
Read 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 < @code.length
step
end
end
end
if __FILE__ == $0
unless ARGV[0]
puts "Copy interpreter in Ruby"
puts "Usage: #{$0} <file>"
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?
step
toself.step
to increase readability. \$\endgroup\$ – Conor O'Brien Sep 25 '16 at 16:36