Created
November 14, 2015 02:36
-
-
Save Butjok/2a63ee679573c1178c3f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def pairs(l): | |
return zip(l[::2], l[1::2]) | |
def vm(ops, env={}): | |
class closure: | |
def __init__(self, pc, env): self.pc, self.env = pc, env | |
def popn(n): | |
if len(stack) < n: print 'not enough elements for pop: %d needed, %d left' % (n, len(stack)) | |
top = stack[-n:] | |
stack[-n:] = [] | |
return top | |
pc, stack, fstack = 0, [], [] | |
labels = {op[1]: index for index, op in enumerate(ops) if op[0] == 'label'} | |
while pc < len(ops): | |
op, args, pc = ops[pc][0], ops[pc][1:], pc + 1 | |
arg = args[0] if args else None | |
if op == 'label': | |
pass | |
elif op == 'val': | |
stack.append(arg) | |
elif op == 'fn': | |
stack.append(closure(labels[arg], env)) | |
elif op == 'set' or op == 'get': | |
e = env | |
while e is not None and arg not in e: | |
e = e[''] if '' in e else None | |
if op == 'set': (env if e is None else e)[arg] = stack.pop() | |
elif op == 'get': | |
if e: stack.append(e[arg]) | |
else: print('undefined variable %s' % arg) | |
elif op == 'arr': | |
stack.append(popn(arg)) | |
elif op == 'map': | |
stack.append(dict(pairs(popn(arg * 2)))) | |
elif op == 'call' or op == 'tcall': | |
fn = stack.pop() | |
if args and arg: | |
stack.append(popn(arg)) | |
if isinstance(fn, closure): | |
if op == 'call': | |
fstack.append((pc, env)) | |
pc, env = fn.pc, {'': fn.env} | |
elif hasattr(fn, '__call__'): | |
stack.append(fn(stack.pop())) | |
elif op == 'args': | |
vals = stack.pop() | |
if len(args) != len(vals): print 'warning: wrong arguments count: %d expected, %d given' % (len(args), len(vals)) | |
env.update(dict(zip(args, vals))) | |
elif op == 'ret': | |
if not fstack: break | |
pc, env = fstack.pop() | |
elif op == 'jmp': | |
pc = labels[arg] | |
elif op == 'jmpf': | |
if not stack.pop(): pc = labels[arg] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment