Skip to content

Instantly share code, notes, and snippets.

@eterps
Forked from pachacamac/mrisc.rb
Created Jul 8, 2011
Embed
What would you like to do?
A Simple Assembler Language and VM
#!/usr/bin/env ruby
class MRISC
def run(code)
tokens = code.gsub(/(\*.*?\*)|[^a-z0-9,-;@\._]/,'').split(';')
@vars,stack,i = {:_pc=>-1,:_oc=>0},[],0
tokens.map!{|t| t.chars.first=='@' ? (@vars[t.to_sym]=i-1;nil) : (i+=1;t.split(',').map{|e|numeric?(e) ? e.to_i : e.to_sym})}.compact!
while @vars[:_pc] < tokens.size-1
@vars[:_pc] += 1
@vars[:_oc] += 1
@vars[:_ss] = stack.size
raise 'too many operations!' if @vars[:_oc] > 9999
cmd,a,b,c = tokens[@vars[:_pc]]
case cmd
when :let; set(a,b)
when :out; puts get(a)
when :dbg; puts a
when :add; set(a,get(a)+get(b))
when :sub; set(a,get(a)-get(b))
when :mul; set(a,get(a)*get(b))
when :mod; set(a,get(a)%get(b))
when :div; set(a,get(a)/get(b))
when :jmp; @vars[:_pc]=get(a)
when :jis; @vars[:_pc]=get(c) if get(a)<get(b)
when :jig; @vars[:_pc]=get(c) if get(a)>get(b)
when :jie; @vars[:_pc]=get(c) if get(a)==get(b)
when :jiu; @vars[:_pc]=get(c) if get(a)!=get(b)
when :end; @vars[:_pc]=tokens.size
when :pus; stack.push(get(a))
when :pop; set(a,stack.pop)
else raise "unknown command '#{cmd}' at #{tokens[@vars[:_pc]].join(',')}"
end
end
@vars
end
private
def get(s); (@vars.key?(s) ? @vars[s] : numeric?(s) ? s : 0).to_i; end
def set(s,v); @vars[s] = get(v); end
def numeric?(n); true if Float(n) rescue false; end
end
MRISC.new.run('
*=== Main ===*
let,a,3; *arg 1 and result*
let,b,5; *arg 2*
let,@rj,_pc; *return address*
add,@rj,2;
jmp,@power; *subroutine call*
out,a; *print result*
end;
*=== Subroutines ===*
@power; *calculates pow(a,b) result in a. uses tmp*
let,tmp,a;
@power1;
mul,a,tmp;
sub,b,1;
jig,b,1,@power1;
jmp,@rj; *return from subroutine*
')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment