Created
October 28, 2012 12:50
-
-
Save aisk/3968518 to your computer and use it in GitHub Desktop.
compile simple s-expressions to python bytecode file.
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
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