Generates random Python functions using Markov chains
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

187 lignes
5.9 KiB

  1. import opcode
  2. import sys
  3. import func_smash
  4. OP_HASLOAD = {"LOAD_CONST": True, "LOAD_FAST": False, "LOAD_GLOBAL": False}
  5. OP_HASBINARY = {"BINARY_ADD": "+", "BINARY_SUBTRACT": "-",
  6. "BINARY_MULTIPLY": "*", "BINARY_DIVIDE": "/",
  7. "BINARY_POWER": "**", "BINARY_MODULO": "%"}
  8. OP_HASBUILD = {"BUILD_TUPLE": ("(", ")"), "BUILD_LIST": ("[", "]"),
  9. "BUILD_SET": ("{", "}")}
  10. def prettify_function(func, indent=0):
  11. args = _get_func_args(func)
  12. _print(indent, "def {0}({1}):".format(func.func_name, args))
  13. prettify_code(func.__code__, indent=indent+4)
  14. def prettify_code(codeobj, indent=0):
  15. codes = []
  16. codestring = codeobj.co_code
  17. length = len(codestring)
  18. i = 0
  19. while i < length:
  20. code = ord(codestring[i])
  21. i += 1
  22. if code >= opcode.HAVE_ARGUMENT:
  23. arg = func_smash._get_argument(codeobj, codestring, i, code)
  24. i += 2
  25. codes.append((code, arg))
  26. else:
  27. codes.append((code, None))
  28. _print_codestring(codes, indent)
  29. def _print_codestring(codes, indent):
  30. stack = []
  31. print_buffer = []
  32. block_dedent_at = []
  33. block_else_at = []
  34. i = 0
  35. for instruction in codes:
  36. code, arg = instruction
  37. opname = opcode.opname[code]
  38. if code >= opcode.HAVE_ARGUMENT:
  39. i += 3
  40. else:
  41. i += 1
  42. for x in block_dedent_at:
  43. if i >= x:
  44. indent -= 4
  45. block_dedent_at.remove(x)
  46. for x in block_else_at:
  47. if i >= x:
  48. _print(indent, "else:")
  49. indent += 4
  50. _print(indent, "pass")
  51. block_else_at.remove(x)
  52. _print(indent, i, opname, arg, debug=True)
  53. if opname in OP_HASLOAD:
  54. _push(stack, arg, literal=OP_HASLOAD[opname])
  55. elif opname in OP_HASBINARY:
  56. tos, tos1 = _pop(stack), _pop(stack)
  57. _push(stack, " ".join((tos1, OP_HASBINARY[opname], tos)))
  58. elif opname in OP_HASBUILD:
  59. args = []
  60. for i in xrange(arg):
  61. args.append(_pop(stack))
  62. args.reverse()
  63. start, end = OP_HASBUILD[opname]
  64. _push(stack, start + ", ".join(args) + end)
  65. elif opname == "BUILD_MAP":
  66. _push(stack, "{}")
  67. elif opname == "STORE_FAST":
  68. _print(indent, arg, "=", _pop(stack))
  69. elif opname == "STORE_MAP":
  70. key, value = _pop(stack), _pop(stack)
  71. pair = ": ".join((key, value))
  72. oldmap = _pop(stack)
  73. if oldmap == "{}":
  74. newmap = "{" + pair + "}"
  75. else:
  76. newmap = oldmap[:-1] + ", " + pair + "}"
  77. _push(stack, newmap)
  78. elif opname == "LOAD_ATTR":
  79. tos = _pop(stack)
  80. new_tos = tos + "." + arg
  81. _push(stack, new_tos)
  82. elif opname == "POP_TOP":
  83. _print(indent, _pop(stack))
  84. elif opname == "CALL_FUNCTION":
  85. numargs, numkwargs = arg
  86. args = []
  87. for i in xrange(numkwargs):
  88. value = _pop(stack)
  89. key = _pop(stack, never_literal=True)
  90. args.append("=".join((key, value)))
  91. for i in xrange(numargs):
  92. args.append(_pop(stack))
  93. args.reverse()
  94. funcname = _pop(stack)
  95. _push(stack, "{0}({1})".format(funcname, ", ".join(args)))
  96. elif opname == "PRINT_ITEM":
  97. print_buffer.append(_pop(stack))
  98. elif opname == "PRINT_NEWLINE":
  99. _print(indent, "print", ", ".join(print_buffer))
  100. print_buffer = []
  101. elif opname == "RETURN_VALUE":
  102. _print(indent, "return", _pop(stack))
  103. elif opname == "COMPARE_OP":
  104. tos, tos1 = _pop(stack), _pop(stack)
  105. compare = " ".join((tos1, arg, tos))
  106. _push(stack, compare)
  107. elif opname == "POP_JUMP_IF_FALSE":
  108. test = _pop(stack)
  109. _print(indent, "if {0}:".format(test))
  110. block_dedent_at.append(arg)
  111. block_else_at.append(arg)
  112. indent += 4
  113. elif opname == "JUMP_ABSOLUTE":
  114. block_dedent_at.append(i)
  115. elif opname == "JUMP_FORWARD":
  116. block_dedent_at.append(i + arg)
  117. else:
  118. raise NotImplementedError(opname, arg, stack)
  119. def _get_func_args(func):
  120. codeobj = func.__code__
  121. count = codeobj.co_argcount
  122. if count == 0:
  123. return ""
  124. return ", ".join([arg for arg in codeobj.co_varnames[:count]])
  125. def _push(stack, item, literal=False):
  126. stack.append((item, literal))
  127. def _pop(stack, never_literal=False):
  128. item, literal = stack.pop()
  129. return repr(item) if literal and not never_literal else item
  130. def _print(indentation, *args, **kwargs):
  131. argstring = " ".join([str(arg) for arg in args if str(arg)])
  132. if kwargs.get("debug"):
  133. # Ignore debug messages without -d flag
  134. if len(sys.argv) > 1 and sys.argv[1] == "-d":
  135. print " " * 50 + "#", argstring
  136. return
  137. print " " * indentation + argstring
  138. if __name__ == "__main__":
  139. def f1(a):
  140. b = a + 10 / 7.0
  141. d = long_func(a, b+9, c=42, d="43")
  142. print b, d
  143. ex_tuple = ("Hello", "world!", abcdef)
  144. ex_list = [1, 2, 3] * 3 + [4, 5, 6]
  145. ex_set = {99, 98, 97, 96, 95}
  146. ex_dict = {d: e, f: False, "testing": g}
  147. return ex_dict
  148. def f2(a, b, c):
  149. if cmp1:
  150. line1
  151. if cmp2:
  152. line2
  153. elif cmp3:
  154. line3
  155. elif cmp4:
  156. line4
  157. else:
  158. line5
  159. line6
  160. else:
  161. line7
  162. line8
  163. if cmp4:
  164. line9
  165. if cmp5:
  166. if cmp6:
  167. if cmp7:
  168. if cmp8:
  169. if cmp9:
  170. line10
  171. return line11
  172. prettify_function(f1)
  173. print
  174. prettify_function(f2)