import time from builtins import builtin_map from language_types import coerce, uncoerce class VirtualMachine(object): def __init__(self, db): self.db = db self.active_task_id = None self.sleepytime = None self.stack = [] self.contexts = [] self.tasks = {} self.task_sequence = [] self.ticks_used = 0 def pop(self, count=1): return [uncoerce(self.stack.pop()) for x in range(count)] def push(self, value): self.stack.append(coerce(value)) def setvar(self, varname, val): self.contexts[-1][varname] = val def getvar(self, varname): return self.contexts[-1][varname] def push_context(self): self.contexts.append({}) def pop_context(self): self.contexts.pop() def suspend_start_next(self, delay): now = time.time() newtask = heapq.heappushpop(self.task_sequence, (now+max(0.0,delay), self.stack, self.contexts, self.ticks_used)) return activate_task(newtask) def finished_start_next(self): now = time.time() newtask = heapq.heappop(self.task_sequence) return activate_task(newtask) def activate_task(self, task): if now < task[0]: "task isn't ready to execute yet" self.sleepytime = task[0] - now heapq.heappush(self.task_sequence, task[0]) return False self.active_task_id = task[0] self.stack = task[1] self.contexts = task[2] self.ticks_used = task[3] def get_next_task(self): heapq.heappop(self.task_sequence) def run_active_task def run(self): self.sleepytime = None if self.active_task_id == None: finished_start_next() if self.active_task_id == None: return class CodeOp(object): def __init__(self): pass class GetProperty(CodeOp): def execute(self, vm): prop, obj = vm.pop(2) vm.stack.append(vm.db.get_property(obj, prop)) class SetProperty(CodeOp): def execute(self, vm): val, prop, obj = vm.pop(3) vm.db.set_property(obj, prop, val) class GetFile(CodeOp): def execute(self, vm): prop, obj = vm.pop(2) vm.stack.append(vm.db.get_file(obj, prop)) class SetFile(CodeOp): def execute(self, vm): val, prop, obj = vm.pop(3) vm.db.set_file(obj, prop, val) class SetVariable(CodeOp): def execute(self, vm): val, varname = vm.pop(2) vm.setvar(varname, val) class GetVariable(CodeOp): def execute(self, vm): varname, = vm.pop(1) vm.push(vm.getvar(varname)) class CallBuiltin(CodeOp): def __init__(self): pass def execute(self, vm): funcname, = vm.pop(1) builtin_map[funcname](vm) class StartContext(CodeOp): def execute(self, vm): vm.push_context() class EndContext(CodeOp): def execute(self, vm): vm.pop_context()