84 lines
1.7 KiB
Ruby
84 lines
1.7 KiB
Ruby
require_relative "backend.rb"
|
|
class Interpreter < Backend
|
|
def initialize(code)
|
|
@vartable={}
|
|
@paramtable=[]
|
|
@functable={}
|
|
@retstack=[]
|
|
@envstack=[]
|
|
@noinc=["call","return"]
|
|
@infunc=false
|
|
super(code)
|
|
end
|
|
def execute(op)
|
|
if @infunc
|
|
if op[1]=="funcend"
|
|
@infunc=false
|
|
end
|
|
return true
|
|
end
|
|
puts "Running #{op}"
|
|
case op[1]
|
|
when "="
|
|
@vartable[op[0]]=toval(op[2])
|
|
when "+","-","*","/"
|
|
op[2]=toval(op[2])
|
|
op[3]=toval(op[3])
|
|
@vartable[op[0]]=op[2].send(op[1],op[3])
|
|
when "param"
|
|
@paramtable.push toval(op[2])
|
|
when "call"
|
|
result=nil
|
|
case op[2]
|
|
when "puts"
|
|
puts @paramtable.shift
|
|
result=1
|
|
@pc+=1
|
|
when "gets"
|
|
print "Enter number:"
|
|
result=gets.chomp!.to_i
|
|
@pc+=1
|
|
else
|
|
if @functable.has_key? op[2]
|
|
@retstack.push([@pc+1,op[0]])
|
|
@pc=@functable[op[2]]
|
|
@envstack.push @vartable
|
|
@vartable={}
|
|
end
|
|
end
|
|
if result and op[0]
|
|
@vartable[op[0]]=result
|
|
end
|
|
when "func"
|
|
@functable[op[2]]=@pc+1
|
|
@infunc=true
|
|
when "return"
|
|
info=@retstack.pop()
|
|
@pc=info[0]
|
|
if op[2]
|
|
rval=toval(op[2])
|
|
else
|
|
rval=nil
|
|
end
|
|
@vartable=@envstack.pop()
|
|
@vartable[info[1]]=rval
|
|
end
|
|
puts "Vars:#{@vartable}"
|
|
puts "Params:#{@paramtable}"
|
|
puts "Funcs:#{@functable}"
|
|
return !(@noinc.include? op[1])
|
|
end
|
|
private
|
|
def toval(obj)
|
|
if obj.is_a? Integer
|
|
return obj
|
|
elsif /^\d+/.match obj
|
|
return obj.to_i
|
|
elsif /^"([^"]+)"/.match obj
|
|
return $1
|
|
else
|
|
return @vartable[obj]
|
|
end
|
|
end
|
|
end
|