Created
November 22, 2019 04:34
-
-
Save zzl0/bb403efcf68bc6d95b30174df6e88d95 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#!/usr/bin/env python | |
# encoding: utf-8 | |
import struct | |
class Function: | |
def __init__(self, nparams, returns, code): | |
self.nparams = nparams | |
self.returns = returns | |
self.code = code | |
class Machine: | |
def __init__(self, functions, memsize=65536): | |
self.functions = functions | |
self.items = [] | |
self.memory = bytearray(memsize) | |
def load(self, addr): | |
return struct.unpack('<d', self.memory[addr: addr + 8])[0] | |
def store(self, addr, val): | |
self.memory[addr: addr+8] = struct.pack('<d', val) | |
def push(self, item): | |
self.items.append(item) | |
def pop(self): | |
return self.items.pop() | |
def call(self, func, *args): | |
locals = dict(enumerate(args)) | |
self.execute(func.code, locals) | |
if func.returns: | |
return self.pop() | |
def execute(self, instructions, locals): | |
for op, *args in instructions: | |
print(op, args, self.items) | |
if op == 'const': | |
self.push(args[0]) | |
elif op == 'add': | |
right = self.pop() | |
left = self.pop() | |
self.push(left + right) | |
elif op == 'mul': | |
right = self.pop() | |
left = self.pop() | |
self.push(left * right) | |
elif op == 'load': | |
addr = self.pop() | |
self.push(self.load(addr)) | |
elif op == 'store': | |
val = self.pop() | |
addr = self.pop() | |
self.store(addr, val) | |
elif op == 'local_get': | |
self.push(locals[args[0]]) | |
elif op == 'local_set': | |
locals[args[0]] = self.pop() | |
elif op == 'call': | |
func = self.functions[args[0]] | |
fargs = reversed([self.pop() for _ in range(func.nparams)]) | |
result = self.call(func, *fargs) | |
if func.returns: | |
self.push(result) | |
else: | |
raise RuntimeError(f'Bad op {op}') | |
def example(): | |
# def update_position(x, v, dt): | |
# return x + v * dt | |
update_position = Function(nparams=3, returns=True, code=[ | |
('local_get', 0), | |
('local_get', 1), | |
('local_get', 2), | |
('mul',), | |
('add',), | |
]) | |
functions = [update_position] | |
# | |
# x = 2 | |
# v = 3 | |
# x = x + v * 0.1 | |
x_addr = 22 | |
v_addr = 42 | |
code = [ | |
('const', x_addr), | |
('const', x_addr), | |
('load',), | |
('const', v_addr), | |
('load',), | |
('const', 0.1), | |
('call', 0), | |
('store',), | |
] | |
m = Machine(functions) | |
m.store(x_addr, 2.0) | |
m.store(v_addr, 3.0) | |
m.execute(code, None) | |
print(f'Result: {m.load(x_addr)}') | |
if __name__ == '__main__': | |
example() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment