Skip to content

Instantly share code, notes, and snippets.

@aisk
Created October 28, 2012 12:50
Show Gist options
  • Save aisk/3968518 to your computer and use it in GitHub Desktop.
Save aisk/3968518 to your computer and use it in GitHub Desktop.
compile simple s-expressions to python bytecode file.
import marshal
import struct
import time
import imp
from opcode import opmap
SEXPR = ('+', 1,
('-', 3,
('+', 1 , 1)))
def f(): return
code = type(f.__code__)
def sexpr2repolish(sexpr):
''' s-expression to reverse polish notation '''
l = []
def unpack(ll):
ll = [ll[0], ll[2], ll[1]]
for i in ll:
if isinstance(i, tuple):
unpack(i)
else:
l.append(i)
unpack(sexpr)
l.reverse()
return l
def gen_bytecode(repolish):
bytecodes = []
consts = []
for op in repolish:
if isinstance(op, int):
bytecodes.append(struct.pack('B', opmap['LOAD_CONST']))
consts.append(op)
bytecodes.append(struct.pack('H', len(consts) - 1))
if op == '+':
bytecodes.append(struct.pack('B', opmap['BINARY_ADD']))
if op == '-':
bytecodes.append(struct.pack('B', opmap['BINARY_SUBTRACT']))
bytecodes.append(struct.pack('B', opmap['PRINT_ITEM']))
bytecodes.append(struct.pack('B', opmap['PRINT_NEWLINE']))
bytecodes.append(struct.pack('B', opmap['LOAD_CONST']))
consts.append(None)
bytecodes.append(struct.pack('H', len(consts) - 1))
bytecodes.append(struct.pack('B', opmap['RETURN_VALUE']))
code_string = ''.join(bytecodes)
consts = tuple(consts)
code_args = (
0, # 'argcount' arguments count of the code object
0, # 'nlocals' ??
20, # 'stack_size' max size of the stack
64, # 'flags' ??
code_string, # 'codestring' the bytecode instructions
consts, # 'constants' constants value for the code object
(), # 'names' used names in this code object
(), # 'varnames' variable names
'test.py', # 'filename' filename
'<module>', # 'name' name of the function/class/module
1, # 'firstlineno' the first line number of this code object
'', # 'lnotab' ??
(), # 'freevars' for closure
(), # 'cellvars': ??
)
return code(*code_args)
def dump_pyc(co, filename):
magic_string = imp.get_magic()
time_string = struct.pack('L', int(time.time()))
f = open(filename, 'wb')
f.write(magic_string)
f.write(time_string)
marshal.dump(co, f)
f.close()
if __name__ == '__main__':
co = gen_bytecode(sexpr2repolish(SEXPR))
dump_pyc(co, 'test.pyc')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment