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
|