|
#!/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* |
|
') |
|
|
|
MRISC.new.run(' |
|
*==========[ stack test ]===========* |
|
*construct for a subroutine call* |
|
let,n,7; |
|
let,@rj,_pc; |
|
add,@rj,2; |
|
jmp,@fac; |
|
out,n; *print result* |
|
end; *end here* |
|
*=========[ subroutines ]=========* |
|
@fac; *calculates faculty of n, uses t, uses the stack, result in n* |
|
pus,n; |
|
sub,n,1; |
|
jig,n,1,@fac; |
|
@facloop; |
|
pop,t; |
|
mul,n,t; |
|
jig,_ss,0,@facloop; |
|
jmp,@rj; |
|
*===================================* |
|
') |