Bit of fun II

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)
 
X

Xeno Campanoli

Lyndon said:
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 = []

lines = pgm.split("\n")
Why not save a step and just do:

pgm.each_line { |line|...?
lines.each { |line|
tokens = line.strip.chomp.split(" ")
pos = 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 = pos + 1
break if pos > tokens.length
end
}

return outs.join("\n")
end

def assemble(pgm)
mem = []
pc = 0

lines = pgm.split("\n")
# Same comment as above...?
lines.each { |line|
tokens = line.strip.split(/ |,/)
case tokens[0]
when 'loadr'
mem[pc]=1
mem[pc+1]=tokens[1].to_i
mem[pc+2]=tokens[2].to_i
pc = pc+3
when 'addr'
mem[pc]=2
mem[pc+1]=tokens[1].to_i
mem[pc+2]=tokens[2].to_i
pc = pc+3
when 'print'
mem[pc]=3
mem[pc+1]=tokens[1].to_i
pc = pc+2
when 'push'
mem[pc]=4
mem[pc+1]=tokens[1].to_i
pc = pc+2
when 'pop'
mem[pc]=5
mem[pc+1]=tokens[1].to_i
pc = pc+2
end

}

mem.push(0)

return mem
end

def execute(mem)
pc = 0
regs=[]
stack=[]

while true
#puts "> PC:#{pc} CODE:#{mem[pc]} STACK:#{stack.join(',')}"

case mem[pc]
when 0
break
when 1
regs[mem[pc+1]] = mem[pc+2]
pc=pc+3
when 2
regs[mem[pc+1]] = regs[mem[pc+1]] + regs[mem[pc+2]]
pc=pc+3
when 3
puts "#{regs[mem[pc+1]]}"
pc=pc+2
when 4 #push
stack.push(regs[mem[pc+1]])
pc=pc+2
when 5 #pop
regs[mem[pc+1]] = stack.pop()
pc=pc+2
end
end

end

aapgm = compile("12 10 + 14 + p")
code = assemble(aapgm)

execute(code)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,785
Messages
2,569,624
Members
45,318
Latest member
LuisWestma

Latest Threads

Top