Skip to content

Instantly share code, notes, and snippets.

@fowlmouth
Last active May 12, 2016 16:06
Show Gist options
  • Save fowlmouth/1edf02cde1952b4866ea4ab252221329 to your computer and use it in GitHub Desktop.
Save fowlmouth/1edf02cde1952b4866ea4ab252221329 to your computer and use it in GitHub Desktop.
# run some assembly code like
code = <<-eof
# stack
push 1 # [1]
push 2 # [1, 2]
add # [3]
print # []
push 2 # [2]
cond:
dup
push 3
equals?
if-true-jump ret
push 3
goto cond
ret:
print
eof
class AsmParser
attr_accessor :instr
def initialize
@instr = []
end
def parse str
labels = {}
unresolved_labels = {}
get_label = proc do|l|
labels[l] || ((unresolved_labels[l] ||= []) << instr.size; nil)
end
iter = str.each_line
loop do
l = iter.next
case l
when /push (\d+)/i
instr << :push
instr << $1.to_i
when /add/i
instr << :add
when /print/i
instr << :print
when /equals\?/i
instr << :equals?
when /pop/i
instr << :pop
when /dup/i
instr << :dup
when /if-true-jump (\S+)/i
instr << :iftrue
instr << get_label[$1]
when /if-false-jump (\S+)/i
instr << :iffalse
instr << get_label[$1]
when /(\S+):/i
labels[$1] = instr.size
when /goto (\S+)/i, /jump (\S+)/i
instr << :jump
instr << get_label[$1]
else
puts "unrecognized line: #{l}"
end
end
unresolved_labels.each do |k,v|
loc = labels[k]
v.each do |idx|
instr[idx] = loc
end
end
instr
end
end
class VM
attr_accessor :instr
def load instrs
@instr = instrs
self
end
def run
ip = 0
stack = []
while ip < @instr.size
op = @instr[ip]
ip += 1
case op
when :push
stack << instr[ip]
ip += 1
when :dup
stack << stack.last
when :add
stack << (stack.pop + stack.pop)
when :print
puts stack.pop
when :jump
ip = instr[ip]
when :equals?
stack << (stack.pop == stack.pop)
when :pop
stack.pop
when :iftrue
jumpto = instr[ip]
if stack.pop
ip = jumpto
else
ip += 1
end
when :iffalse
jumpto = instr[ip]
if stack.pop
ip += 1
else
ip = jumpto
end
when :nop
else
puts "error: not understand this much"
return
end
end
end
end
VM.new
.load(AsmParser.new.parse(code))
.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment