L
Lyndon Samson
More idle coding A simple Compiler/Assembler/VM for a ( very basic
) RPN (dc) style language. I suspect its quite amenable to golfing,
but at a cost to readability.
def compile(pgm)
outs =3D []
lines =3D pgm.split("\n")
lines.each { |line|
tokens =3D line.strip.chomp.split(" ")
pos =3D 0
while true
case tokens[pos]
when '+'
outs << "pop 1"
outs << "pop 2"
outs << "addr 1,2"
outs << "push 1"
when 'p'
outs << "pop 1"
outs << "print 1"
when '',nil
else
outs << "loadr 1,#{tokens[pos]}"
outs << "push 1"
end
pos =3D pos + 1
break if pos > tokens.length
end
}
return outs.join("\n")
end
def assemble(pgm)
mem =3D []
pc =3D 0
lines =3D pgm.split("\n")
lines.each { |line|
tokens =3D line.strip.split(/ |,/)
case tokens[0]
when 'loadr'
mem[pc]=3D1
mem[pc+1]=3Dtokens[1].to_i
mem[pc+2]=3Dtokens[2].to_i
pc =3D pc+3
when 'addr'
mem[pc]=3D2
mem[pc+1]=3Dtokens[1].to_i
mem[pc+2]=3Dtokens[2].to_i
pc =3D pc+3
when 'print'
mem[pc]=3D3
mem[pc+1]=3Dtokens[1].to_i
pc =3D pc+2
when 'push'
mem[pc]=3D4
mem[pc+1]=3Dtokens[1].to_i
pc =3D pc+2
when 'pop'
mem[pc]=3D5
mem[pc+1]=3Dtokens[1].to_i
pc =3D pc+2
end
}
mem.push(0)
return mem
end
def execute(mem)
pc =3D 0
regs=3D[]
stack=3D[]
while true
#puts "> PC:#{pc} CODE:#{mem[pc]} STACK:#{stack.join(',')}"
case mem[pc]
when 0
break
when 1
regs[mem[pc+1]] =3D mem[pc+2]
pc=3Dpc+3
when 2
regs[mem[pc+1]] =3D regs[mem[pc+1]] + regs[mem[pc+2]]
pc=3Dpc+3
when 3
puts "#{regs[mem[pc+1]]}"
pc=3Dpc+2
when 4 #push
stack.push(regs[mem[pc+1]])
pc=3Dpc+2
when 5 #pop
regs[mem[pc+1]] =3D stack.pop()
pc=3Dpc+2
end
end
end
aapgm =3D compile("12 10 + 14 + p")
code =3D assemble(aapgm)
execute(code)
) RPN (dc) style language. I suspect its quite amenable to golfing,
but at a cost to readability.
def compile(pgm)
outs =3D []
lines =3D pgm.split("\n")
lines.each { |line|
tokens =3D line.strip.chomp.split(" ")
pos =3D 0
while true
case tokens[pos]
when '+'
outs << "pop 1"
outs << "pop 2"
outs << "addr 1,2"
outs << "push 1"
when 'p'
outs << "pop 1"
outs << "print 1"
when '',nil
else
outs << "loadr 1,#{tokens[pos]}"
outs << "push 1"
end
pos =3D pos + 1
break if pos > tokens.length
end
}
return outs.join("\n")
end
def assemble(pgm)
mem =3D []
pc =3D 0
lines =3D pgm.split("\n")
lines.each { |line|
tokens =3D line.strip.split(/ |,/)
case tokens[0]
when 'loadr'
mem[pc]=3D1
mem[pc+1]=3Dtokens[1].to_i
mem[pc+2]=3Dtokens[2].to_i
pc =3D pc+3
when 'addr'
mem[pc]=3D2
mem[pc+1]=3Dtokens[1].to_i
mem[pc+2]=3Dtokens[2].to_i
pc =3D pc+3
when 'print'
mem[pc]=3D3
mem[pc+1]=3Dtokens[1].to_i
pc =3D pc+2
when 'push'
mem[pc]=3D4
mem[pc+1]=3Dtokens[1].to_i
pc =3D pc+2
when 'pop'
mem[pc]=3D5
mem[pc+1]=3Dtokens[1].to_i
pc =3D pc+2
end
}
mem.push(0)
return mem
end
def execute(mem)
pc =3D 0
regs=3D[]
stack=3D[]
while true
#puts "> PC:#{pc} CODE:#{mem[pc]} STACK:#{stack.join(',')}"
case mem[pc]
when 0
break
when 1
regs[mem[pc+1]] =3D mem[pc+2]
pc=3Dpc+3
when 2
regs[mem[pc+1]] =3D regs[mem[pc+1]] + regs[mem[pc+2]]
pc=3Dpc+3
when 3
puts "#{regs[mem[pc+1]]}"
pc=3Dpc+2
when 4 #push
stack.push(regs[mem[pc+1]])
pc=3Dpc+2
when 5 #pop
regs[mem[pc+1]] =3D stack.pop()
pc=3Dpc+2
end
end
end
aapgm =3D compile("12 10 + 14 + p")
code =3D assemble(aapgm)
execute(code)