import _ast import struct import sys from types import NoneType def _print_str(s, f): assert len(s) < 2**16 f.write(struct.pack(">H", len(s))) f.write(s) TYPE_MAP = { _ast.alias: 1, _ast.arguments: 2, _ast.Assert: 3, _ast.Assign: 4, _ast.Attribute: 5, _ast.AugAssign: 6, _ast.BinOp: 7, _ast.BoolOp: 8, _ast.Call: 9, _ast.ClassDef: 10, _ast.Compare: 11, _ast.comprehension: 12, _ast.Delete: 13, _ast.Dict: 14, _ast.Exec: 16, _ast.ExceptHandler: 17, _ast.ExtSlice: 18, _ast.Expr: 19, _ast.For: 20, _ast.FunctionDef: 21, _ast.GeneratorExp: 22, _ast.Global: 23, _ast.If: 24, _ast.IfExp: 25, _ast.Import: 26, _ast.ImportFrom: 27, _ast.Index: 28, _ast.keyword: 29, _ast.Lambda: 30, _ast.List: 31, _ast.ListComp: 32, _ast.Module: 33, _ast.Num: 34, _ast.Name: 35, _ast.Pass: 37, _ast.Pow: 38, _ast.Print: 39, _ast.Raise: 40, _ast.Repr: 41, _ast.Return: 42, _ast.Slice: 44, _ast.Str: 45, _ast.Subscript: 46, _ast.TryExcept: 47, _ast.TryFinally: 48, _ast.Tuple: 49, _ast.UnaryOp: 50, _ast.With: 51, _ast.While: 52, _ast.Yield: 53, _ast.Store: 54, _ast.Load: 55, _ast.Param: 56, _ast.Not: 57, _ast.In: 58, _ast.Is: 59, _ast.IsNot: 60, _ast.Or: 61, _ast.And: 62, _ast.Eq: 63, _ast.NotEq: 64, _ast.NotIn: 65, _ast.GtE: 66, _ast.Gt: 67, _ast.Mod: 68, _ast.Add: 69, _ast.Continue: 70, _ast.Lt: 71, _ast.LtE: 72, _ast.Break: 73, _ast.Sub: 74, _ast.Del: 75, _ast.Mult: 76, _ast.Div: 77, _ast.USub: 78, _ast.BitAnd: 79, _ast.BitOr: 80, _ast.BitXor: 81, _ast.RShift: 82, _ast.LShift: 83, _ast.Invert: 84, _ast.UAdd: 85, _ast.FloorDiv: 86, } if sys.version_info >= (2,7): TYPE_MAP[_ast.DictComp] = 15 TYPE_MAP[_ast.Set] = 43 def convert(n, f): assert n is None or isinstance(n, _ast.AST), repr(n) type_idx = TYPE_MAP[type(n)] if n else 0 f.write(struct.pack(">B", type_idx)) if n is None: return if isinstance(n, (_ast.operator, _ast.expr_context, _ast.boolop, _ast.cmpop, _ast.unaryop)): return f.write('\xae') if isinstance(n, _ast.Num): if isinstance(n.n, int): f.write('\x10') elif isinstance(n.n, long): assert (-1L<<60) < n.n < (1L<<60) f.write('\x10') elif isinstance(n.n, float): f.write('\x20') else: raise Exception(type(n.n)) # print >>sys.stderr, n, sorted(n.__dict__.items()) for k, v in sorted(n.__dict__.items()): if k.startswith('_'): continue if k in ("vararg", "kwarg", "asname") and v is None: v = "" # elif k in ('col_offset', 'lineno'): # continue if isinstance(v, list): assert len(v) < 2**16 f.write(struct.pack(">H", len(v))) if isinstance(n, _ast.Global): assert k == "names" for el in v: _print_str(el, f) else: for el in v: convert(el, f) elif isinstance(v, str): _print_str(v, f) elif isinstance(v, unicode): print >>sys.stderr, "Warning, converting unicode string to str!" sys.stderr.flush() _print_str(v.encode("ascii"), f) elif isinstance(v, bool): f.write(struct.pack("B", v)) elif isinstance(v, int): f.write(struct.pack(">q", v)) elif isinstance(v, long): assert (-1L<<60) < v < (1L<<60) print >>sys.stderr, "Warning, converting long to int!" f.write(struct.pack(">q", v)) elif isinstance(v, float): f.write(struct.pack(">d", v)) elif v is None or isinstance(v, _ast.AST): convert(v, f) else: raise Exception((n, k, repr(v))) if __name__ == "__main__": import time start = time.time() fn = sys.argv[1] s = open(fn).read() m = compile(s, fn, "exec", _ast.PyCF_ONLY_AST) convert(m, sys.stdout)