def decompile(decompiler): PY36 = sys.version_info >= (3, 6) code = decompiler.code co_code = code.co_code free = code.co_cellvars + code.co_freevars try: extended_arg = 0 while decompiler.pos < decompiler.end: i = decompiler.pos if i in decompiler.targets: decompiler.process_target(i) op = ord(code.co_code[i]) if PY36: if op >= HAVE_ARGUMENT: oparg = ord(co_code[i + 1]) | extended_arg extended_arg = ((extended_arg << 8) if op == EXTENDED_ARG else 0) i += 2 else: i += 1 if op >= HAVE_ARGUMENT: oparg = ord(co_code[i]) + ord(co_code[i + 1]) * 256 i += 2 if op == EXTENDED_ARG: op = ord(code.co_code[i]) i += 1 oparg = (ord(co_code[i]) + ord(co_code[i + 1]) * 256 + oparg * 65536) i += 2 if op >= HAVE_ARGUMENT: if op in hasconst: arg = [code.co_consts[oparg]] elif op in hasname: arg = [code.co_names[oparg]] elif op in hasjrel: arg = [i + oparg] elif op in haslocal: arg = [code.co_varnames[oparg]] elif op in hascompare: arg = [cmp_op[oparg]] elif op in hasfree: arg = [free[oparg]] else: arg = [oparg] else: arg = [] opname = opnames[op].replace('+', '_') # print(opname, arg, decompiler.stack) method = getattr(decompiler, opname, None) if method is None: throw(NotImplementedError, 'Unsupported operation: %s' % opname) # noqa decompiler.pos = i x = method(*arg) if x is not None: decompiler.stack.append(x) except AstGenerated: pass
def STORE_FAST(decompiler, varname): if varname.startswith('_['): throw( InvalidQuery, 'Use generator expression (... for ... in ...) ' 'instead of list comprehension [... for ... in ...] inside query' ) # noqa decompiler.assnames.add(varname) decompiler.store(ast.AssName(varname, 'OP_ASSIGN'))
def CALL_FUNCTION_EX(decompiler, argc): star2 = None if argc: if argc != 1: throw(NotImplementedError) star2 = decompiler.stack.pop() star = decompiler.stack.pop() return decompiler._call_function([], star, star2)
def process_target(decompiler, pos, partial=False): if pos is None: limit = None elif partial: limit = decompiler.targets.get(pos, None) else: limit = decompiler.targets.pop(pos, None) top = decompiler.stack.pop() while True: top = simplify(top) if top is limit: break if isinstance(top, ast.GenExprFor): break top2 = decompiler.stack[-1] if isinstance(top2, ast.GenExprFor): break if partial and hasattr(top2, 'endpos') and top2.endpos == pos: break if isinstance(top2, (ast.And, ast.Or)): if top2.__class__ == top.__class__: top2.nodes.extend(top.nodes) else: top2.nodes.append(top) elif isinstance(top2, ast.IfExp): # Python 2.5 top2.else_ = top if hasattr(top, 'endpos'): top2.endpos = top.endpos if decompiler.targets.get(top.endpos) is top: decompiler.targets[top.endpos] = top2 else: throw( NotImplementedError, 'Expression is too complex to decompile, try to pass query as string, e.g. select("x for x in Something")' ) # noqa top2.endpos = max(top2.endpos, getattr(top, 'endpos', 0)) top = decompiler.stack.pop() decompiler.stack.append(top)
def decompile(x): cells = {} if isinstance(x, types.CodeType): codeobject = x elif isinstance(x, types.GeneratorType): codeobject = x.gi_frame.f_code elif isinstance(x, types.FunctionType): codeobject = x.func_code if PY2 else x.__code__ if PY2: if x.func_closure: cells = dict(izip(codeobject.co_freevars, x.func_closure)) else: if x.__closure__: cells = dict(izip(codeobject.co_freevars, x.__closure__)) else: throw(TypeError) key = get_codeobject_id(codeobject) result = ast_cache.get(key) if result is None: decompiler = Decompiler(codeobject) result = decompiler.ast, decompiler.external_names ast_cache.set(key, result) return result + (cells, )
def MAKE_FUNCTION(decompiler, argc): if sys.version_info >= (3, 6): if argc: if argc != 0x08: throw(NotImplementedError, argc) decompiler.stack.pop() tos = decompiler.stack.pop() if (argc & 0x08): decompiler.stack.pop() else: if argc: throw(NotImplementedError) tos = decompiler.stack.pop() if not PY2: tos = decompiler.stack.pop() codeobject = tos.value func_decompiler = Decompiler(codeobject) # decompiler.names.update(decompiler.names) ??? if codeobject.co_varnames[:1] == ('.0', ): return func_decompiler.ast # generator argnames = codeobject.co_varnames[:codeobject.co_argcount] defaults = [] # todo flags = 0 # todo return ast.Lambda(argnames, defaults, flags, func_decompiler.ast)
def RETURN_VALUE(decompiler): if decompiler.pos != decompiler.end: throw(NotImplementedError) expr = decompiler.stack.pop() decompiler.stack.append(simplify(expr)) raise AstGenerated()
def LIST_APPEND(decompiler, offset=None): throw(InvalidQuery, 'Use generator expression (... for ... in ...) ' 'instead of list comprehension [... for ... in ...] inside query' ) # noqa
def default_post(translator, node): throw(NotImplementedError, node)
def default_post(self, node): throw(NotImplementedError, node)