69 lines
1.9 KiB
Python
69 lines
1.9 KiB
Python
|
from tpers import *
|
||
|
from scripting import Fail, Synt
|
||
|
|
||
|
class Vars(TPrs):
|
||
|
def InitPersistent(self):
|
||
|
self.rgmpsynt_sobj = [{}] # [0] is for globals?
|
||
|
|
||
|
def Get(self, synt):
|
||
|
for mpsynt_sobj in reversed(self.rgmpsynt_sobj):
|
||
|
try:
|
||
|
return mpsynt_sobj[synt]
|
||
|
except:
|
||
|
pass
|
||
|
return Fail("Variable " + synt.name.St() + " not defined")
|
||
|
|
||
|
def Define(self, synt, sobj):
|
||
|
self.rgmpsynt_sobj[-1][synt] = sobj
|
||
|
|
||
|
def Set(self, synt, sobj):
|
||
|
for mpsynt_sobj in reversed(self.rgmpsynt_sobj):
|
||
|
if synt in mpsynt_sobj:
|
||
|
mpsynt_sobj[synt] = sobj
|
||
|
return
|
||
|
return Fail("Variable " + synt.name.St() + " not defined")
|
||
|
|
||
|
def Push(self):
|
||
|
self.rgmpsynt_sobj.append({})
|
||
|
|
||
|
def Pop(self):
|
||
|
self.rgmpsynt_sobj.pop()
|
||
|
|
||
|
class Vm(TPrs):
|
||
|
def InitPersistent(self):
|
||
|
self.vstack = []
|
||
|
self.rstack = []
|
||
|
self.vars = Vars()
|
||
|
|
||
|
def Push(self, sobj):
|
||
|
self.vstack.append(sobj)
|
||
|
def Pop(self):
|
||
|
return self.vstack.pop()
|
||
|
|
||
|
def CallI(self, synt, r, ip):
|
||
|
if ip < len(r): # tail call optimization
|
||
|
self.rstack.append(r, ip)
|
||
|
return (synt.Compile(), 0)
|
||
|
|
||
|
def RunSynt(self, synt):
|
||
|
r = synt.Compile()
|
||
|
ip = 0
|
||
|
while True:
|
||
|
if ip < len(r):
|
||
|
instr = r[ip]
|
||
|
ip += 1
|
||
|
if isinstance(instr, Synt):
|
||
|
(r, ip) = self.CallI(instr, r, ip)
|
||
|
elif callable(instr):
|
||
|
synt = instr(self)
|
||
|
if synt != None:
|
||
|
(r, ip) = self.CallI(instr, r, ip)
|
||
|
else:
|
||
|
assert False, "invalid opcode"
|
||
|
else:
|
||
|
if len(rstack) == 0:
|
||
|
break
|
||
|
(r, ip) = self.rstack.pop()
|
||
|
|
||
|
|
||
|
|