| @@ -3,11 +3,12 @@ import sys | |||
| import func_smash | |||
| OP_HASLOAD = ("LOAD_FAST", "LOAD_CONST", "LOAD_GLOBAL") | |||
| OP_HASLOAD = {"LOAD_CONST": True, "LOAD_FAST": False, "LOAD_GLOBAL": False} | |||
| OP_HASBINARY = {"BINARY_ADD": "+", "BINARY_SUBTRACT": "-", | |||
| "BINARY_MULTIPLY": "*", "BINARY_DIVIDE": "/", | |||
| "BINARY_POWER": "**", "BINARY_MODULO": "%"} | |||
| OP_HASBUILD = ("BUILD_TUPLE", "BUILD_LIST", "BUILD_MAP", "BUILD_SET") | |||
| OP_HASBUILD = {"BUILD_TUPLE": ("(", ")"), "BUILD_LIST": ("[", "]"), | |||
| "BUILD_SET": ("{", "}")} | |||
| def prettify_function(func, indent=0): | |||
| args = _get_func_args(func) | |||
| @@ -38,39 +39,50 @@ def _print_codestring(codes, indent): | |||
| opname = opcode.opname[code] | |||
| _print(indent, opname, arg, "; stack ==", stack, debug=True) | |||
| if opname in OP_HASLOAD: | |||
| stack.append(arg) | |||
| _push(stack, arg, literal=OP_HASLOAD[opname]) | |||
| elif opname in OP_HASBINARY: | |||
| tos, tos1 = str(stack.pop()), str(stack.pop()) | |||
| stack.append(" ".join((tos1, OP_HASBINARY[opname], tos))) | |||
| tos, tos1 = _pop(stack), _pop(stack) | |||
| _push(stack, " ".join((tos1, OP_HASBINARY[opname], tos))) | |||
| elif opname in OP_HASBUILD: | |||
| args = [] | |||
| for i in xrange(arg): | |||
| args.append(str(stack.pop())) | |||
| if opname == "BUILD_TUPLE": | |||
| stack.append("(" + ", ".join(args) + ")") | |||
| args.append(_pop(stack)) | |||
| args.reverse() | |||
| start, end = OP_HASBUILD[opname] | |||
| _push(stack, start + ", ".join(args) + end) | |||
| elif opname == "BUILD_MAP": | |||
| _push(stack, "{}") | |||
| elif opname == "STORE_FAST": | |||
| _print(indent, arg, "=", stack.pop()) | |||
| _print(indent, arg, "=", _pop(stack)) | |||
| elif opname == "STORE_MAP": | |||
| pair = ": ".join((_pop(stack), _pop(stack))) | |||
| oldmap = _pop(stack) | |||
| if oldmap == "{}": | |||
| newmap = "{" + pair + "}" | |||
| else: | |||
| newmap = oldmap[:-1] + ", " + pair + "}" | |||
| _push(stack, newmap) | |||
| elif opname == "POP_TOP": | |||
| _print(indent, stack.pop()) | |||
| _print(indent, _pop(stack)) | |||
| elif opname == "CALL_FUNCTION": | |||
| numargs, numkwargs = arg | |||
| args = [] | |||
| for i in xrange(numkwargs): | |||
| value = str(stack.pop()) | |||
| key = str(stack.pop()) | |||
| value = _pop(stack) | |||
| key = _pop(stack, never_literal=True) | |||
| args.append("=".join((key, value))) | |||
| for i in xrange(numargs): | |||
| args.append(str(stack.pop())) | |||
| args.append(_pop(stack)) | |||
| args.reverse() | |||
| funcname = stack.pop() | |||
| stack.append("{0}({1})".format(funcname, ", ".join(args))) | |||
| funcname = _pop(stack) | |||
| _push(stack, "{0}({1})".format(funcname, ", ".join(args))) | |||
| elif opname == "PRINT_ITEM": | |||
| print_buffer.append(stack.pop()) | |||
| print_buffer.append(_pop(stack)) | |||
| elif opname == "PRINT_NEWLINE": | |||
| _print(indent, "print", ", ".join(print_buffer)) | |||
| print_buffer = [] | |||
| elif opname == "RETURN_VALUE": | |||
| _print(indent, "return", stack.pop()) | |||
| _print(indent, "return", _pop(stack)) | |||
| else: | |||
| raise NotImplementedError(opname, arg, stack) | |||
| @@ -81,22 +93,32 @@ def _get_func_args(func): | |||
| return "" | |||
| return ", ".join([arg for arg in codeobj.co_varnames[:count]]) | |||
| def _push(stack, item, literal=False): | |||
| stack.append((item, literal)) | |||
| def _pop(stack, never_literal=False): | |||
| item, literal = stack.pop() | |||
| return repr(item) if literal and not never_literal else item | |||
| def _print(indentation, *args, **kwargs): | |||
| argstring = " ".join([str(arg) for arg in args if str(arg)]) | |||
| if kwargs.get("debug"): | |||
| # Ignore debug messages without -d flag | |||
| if len(sys.argv) > 1 and sys.argv[1] == "-d": | |||
| print " " * 40 + "#", argstring | |||
| print " " * 50 + "#", argstring | |||
| return | |||
| print " " * indentation + argstring | |||
| if __name__ == "__main__": | |||
| def f1(a): | |||
| b = a + 10 / 7.0 | |||
| d = long_func(a, b+9, c=42, d=43) | |||
| d = long_func(a, b+9, c=42, d="43") | |||
| print b, d | |||
| v, z | |||
| return d % 10 | |||
| ex_tuple = ("Hello", "world!", abcdef) | |||
| ex_list = [1, 2, 3] * 3 + [4, 5, 6] | |||
| ex_set = {99, 98, 97, 96, 95} | |||
| ex_dict = {d: e, f: False, "testing": g} | |||
| return ex_dict | |||
| def f2(): | |||
| pass | |||