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.

119 lignes
3.2 KiB

  1. import dis
  2. import opcode
  3. import random
  4. import types
  5. ############## CODE ###########################################################
  6. MARKOV_START = -1
  7. MARKOV_END = -2
  8. def make_chain(funcs):
  9. chain = {}
  10. for func in funcs:
  11. co = func.__code__
  12. code = co.co_code
  13. n = len(code)
  14. i = 0
  15. lastop = MARKOV_START
  16. while i < n:
  17. op = ord(code[i])
  18. i += 1
  19. if op >= opcode.HAVE_ARGUMENT:
  20. oparg = ord(code[i]) + ord(code[i + 1]) * 256
  21. i += 2
  22. if op in opcode.hasconst:
  23. arg = co.co_consts[oparg]
  24. elif op in opcode.haslocal:
  25. arg = co.co_varnames[oparg]
  26. else:
  27. raise NotImplementedError(op, opcode.opname[op])
  28. else:
  29. arg = None
  30. _chain_append(chain, lastop, (op, arg))
  31. lastop = op
  32. _chain_append(chain, op, MARKOV_END)
  33. return chain
  34. def make_function(chain, name, argcount=1):
  35. codes, constants, varnames = _make_codes(chain)
  36. nlocals = len(varnames) + argcount
  37. stacksize = 1024 # High limit?
  38. flags = 0 # Denotes funcs with *args and/or **kwargs; nothing for now
  39. codestring = "".join([chr(code) for code in codes])
  40. names = ()
  41. filename = "<smash>"
  42. firstlineno = 1
  43. lnotab = ""
  44. code = types.CodeType(argcount, nlocals, stacksize, flags, codestring,
  45. constants, names, varnames, filename, name,
  46. firstlineno, lnotab)
  47. func = types.FunctionType(code, globals(), name)
  48. return func
  49. def _chain_append(chain, first, second):
  50. try:
  51. chain[first].append(second)
  52. except KeyError:
  53. chain[first] = [second]
  54. def _make_codes(chain):
  55. codes = []
  56. code = random.choice(chain[MARKOV_START])
  57. constants, varnames = [], []
  58. while 1:
  59. if code == MARKOV_END:
  60. break
  61. op, arg = code
  62. codes.append(op)
  63. if op >= opcode.HAVE_ARGUMENT:
  64. if op in opcode.hasconst:
  65. args = constants
  66. elif op in opcode.haslocal:
  67. args = varnames
  68. else:
  69. raise NotImplementedError(op, opcode.opname[op])
  70. if arg not in args:
  71. args.append(arg)
  72. codes.append(args.index(arg))
  73. codes.append(0)
  74. code = random.choice(chain[op])
  75. return codes, tuple(constants), tuple(varnames)
  76. ############## FUNCTION CORPUS ################################################
  77. def f1(a):
  78. b = a + 7.0
  79. return b
  80. def f2(a):
  81. b = a - 5.0
  82. return b
  83. def f3(a):
  84. b = a * 3.0
  85. return b
  86. def f4(a):
  87. b = a / 2.0
  88. return b
  89. corpus = [f1, f2, f3, f4]
  90. ############## DEMO ###########################################################
  91. if __name__ == "__main__":
  92. print "USING FUNCTION CORPUS:", [func.__name__ for func in corpus]
  93. chain = make_chain(corpus)
  94. print "OPCODE MARKOV CHAIN:", chain
  95. print
  96. func = make_function(chain, "func")
  97. print "SMASHED FUNCTION CODE:", [ord(c) for c in func.__code__.co_code]
  98. print "FUNCTION DISASSEMBLY:"
  99. dis.dis(func)
  100. print
  101. n = 12.0
  102. print "func(%s) =" % n, func(n)