| @@ -3,11 +3,12 @@ import sys | |||||
| import func_smash | 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": "-", | OP_HASBINARY = {"BINARY_ADD": "+", "BINARY_SUBTRACT": "-", | ||||
| "BINARY_MULTIPLY": "*", "BINARY_DIVIDE": "/", | "BINARY_MULTIPLY": "*", "BINARY_DIVIDE": "/", | ||||
| "BINARY_POWER": "**", "BINARY_MODULO": "%"} | "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): | def prettify_function(func, indent=0): | ||||
| args = _get_func_args(func) | args = _get_func_args(func) | ||||
| @@ -38,39 +39,50 @@ def _print_codestring(codes, indent): | |||||
| opname = opcode.opname[code] | opname = opcode.opname[code] | ||||
| _print(indent, opname, arg, "; stack ==", stack, debug=True) | _print(indent, opname, arg, "; stack ==", stack, debug=True) | ||||
| if opname in OP_HASLOAD: | if opname in OP_HASLOAD: | ||||
| stack.append(arg) | |||||
| _push(stack, arg, literal=OP_HASLOAD[opname]) | |||||
| elif opname in OP_HASBINARY: | 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: | elif opname in OP_HASBUILD: | ||||
| args = [] | args = [] | ||||
| for i in xrange(arg): | 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": | 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": | elif opname == "POP_TOP": | ||||
| _print(indent, stack.pop()) | |||||
| _print(indent, _pop(stack)) | |||||
| elif opname == "CALL_FUNCTION": | elif opname == "CALL_FUNCTION": | ||||
| numargs, numkwargs = arg | numargs, numkwargs = arg | ||||
| args = [] | args = [] | ||||
| for i in xrange(numkwargs): | 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))) | args.append("=".join((key, value))) | ||||
| for i in xrange(numargs): | for i in xrange(numargs): | ||||
| args.append(str(stack.pop())) | |||||
| args.append(_pop(stack)) | |||||
| args.reverse() | 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": | elif opname == "PRINT_ITEM": | ||||
| print_buffer.append(stack.pop()) | |||||
| print_buffer.append(_pop(stack)) | |||||
| elif opname == "PRINT_NEWLINE": | elif opname == "PRINT_NEWLINE": | ||||
| _print(indent, "print", ", ".join(print_buffer)) | _print(indent, "print", ", ".join(print_buffer)) | ||||
| print_buffer = [] | print_buffer = [] | ||||
| elif opname == "RETURN_VALUE": | elif opname == "RETURN_VALUE": | ||||
| _print(indent, "return", stack.pop()) | |||||
| _print(indent, "return", _pop(stack)) | |||||
| else: | else: | ||||
| raise NotImplementedError(opname, arg, stack) | raise NotImplementedError(opname, arg, stack) | ||||
| @@ -81,22 +93,32 @@ def _get_func_args(func): | |||||
| return "" | return "" | ||||
| return ", ".join([arg for arg in codeobj.co_varnames[:count]]) | 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): | def _print(indentation, *args, **kwargs): | ||||
| argstring = " ".join([str(arg) for arg in args if str(arg)]) | argstring = " ".join([str(arg) for arg in args if str(arg)]) | ||||
| if kwargs.get("debug"): | if kwargs.get("debug"): | ||||
| # Ignore debug messages without -d flag | # Ignore debug messages without -d flag | ||||
| if len(sys.argv) > 1 and sys.argv[1] == "-d": | if len(sys.argv) > 1 and sys.argv[1] == "-d": | ||||
| print " " * 40 + "#", argstring | |||||
| print " " * 50 + "#", argstring | |||||
| return | return | ||||
| print " " * indentation + argstring | print " " * indentation + argstring | ||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||
| def f1(a): | def f1(a): | ||||
| b = a + 10 / 7.0 | 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 | 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(): | def f2(): | ||||
| pass | pass | ||||