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.

153 lignes
4.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. _disassemble_func(func, chain)
  12. return chain
  13. def make_function(chain, name, argcount=1):
  14. codes, constants, varnames = _make_codes(chain)
  15. nlocals = len(varnames) + argcount
  16. stacksize = 1024 # High limit?
  17. flags = 0 # Denotes funcs with *args and/or **kwargs; nothing for now
  18. codestring = "".join([chr(code) for code in codes])
  19. names = ()
  20. filename = "<smash>"
  21. firstlineno = 1
  22. lnotab = ""
  23. code = types.CodeType(argcount, nlocals, stacksize, flags, codestring,
  24. constants, names, varnames, filename, name,
  25. firstlineno, lnotab)
  26. func = types.FunctionType(code, globals(), name)
  27. return func
  28. def print_chain(chain):
  29. print "{"
  30. for key in sorted(chain.keys()):
  31. op = _int_to_opname(key)
  32. targets = {}
  33. for op2 in chain[key]:
  34. target = _int_to_opname(op2[0])
  35. if op2[0] >= opcode.HAVE_ARGUMENT:
  36. target = "{0}({1})".format(target, op2[1])
  37. try:
  38. targets[target] += 1
  39. except KeyError:
  40. targets[target] = 1
  41. targs = [t if targets[t] == 1 else "{0}x {1}".format(targets[t], t) for t in targets]
  42. targs.sort()
  43. tstring = ", ".join(targs)
  44. print op.rjust(20), "=> [{0}]".format(tstring)
  45. print "}"
  46. def _disassemble_func(func, chain):
  47. co = func.__code__
  48. code = co.co_code
  49. n = len(code)
  50. i = 0
  51. lastop = MARKOV_START
  52. while i < n:
  53. op = ord(code[i])
  54. i += 1
  55. if op >= opcode.HAVE_ARGUMENT:
  56. oparg = ord(code[i]) + ord(code[i + 1]) * 256
  57. i += 2
  58. if op in opcode.hasconst:
  59. arg = co.co_consts[oparg]
  60. elif op in opcode.haslocal:
  61. arg = co.co_varnames[oparg]
  62. elif op in opcode.hascompare:
  63. arg = opcode.cmp_op[oparg]
  64. else:
  65. raise NotImplementedError(op, opcode.opname[op])
  66. else:
  67. arg = None
  68. _chain_append(chain, lastop, (op, arg))
  69. lastop = op
  70. _chain_append(chain, op, (MARKOV_END, None))
  71. def _chain_append(chain, first, second):
  72. try:
  73. chain[first].append(second)
  74. except KeyError:
  75. chain[first] = [second]
  76. def _make_codes(chain):
  77. codes = []
  78. code = random.choice(chain[MARKOV_START])
  79. constants, varnames = [], []
  80. while 1:
  81. op, arg = code
  82. if op == MARKOV_END:
  83. break
  84. codes.append(op)
  85. if op >= opcode.HAVE_ARGUMENT:
  86. if op in opcode.hasconst:
  87. if arg not in constants:
  88. constants.append(arg)
  89. args = constants
  90. elif op in opcode.haslocal:
  91. if arg not in varnames:
  92. varnames.append(arg)
  93. args = varnames
  94. elif op in opcode.hascompare:
  95. args = opcode.cmp_op
  96. else:
  97. raise NotImplementedError(op, opcode.opname[op])
  98. codes.append(args.index(arg))
  99. codes.append(0)
  100. code = random.choice(chain[op])
  101. return codes, tuple(constants), tuple(varnames)
  102. def _int_to_opname(op):
  103. if op == MARKOV_START:
  104. return "START"
  105. elif op == MARKOV_END:
  106. return "END"
  107. return opcode.opname[op]
  108. ############## FUNCTION CORPUS ################################################
  109. def f1(a):
  110. b = a + 7.0
  111. return b
  112. def f2(a):
  113. b = a - 5.0
  114. return b
  115. def f3(a):
  116. b = a * 3.0
  117. return b
  118. def f4(a):
  119. b = a / 2.0
  120. return b
  121. corpus = [f1, f2, f3, f4]
  122. ############## DEMO ###########################################################
  123. if __name__ == "__main__":
  124. print "USING FUNCTION CORPUS:", [func.__name__ for func in corpus]
  125. chain = make_chain(corpus)
  126. print
  127. func = make_function(chain, "func")
  128. print "SMASHED FUNCTION CODE:", [ord(c) for c in func.__code__.co_code]
  129. print "FUNCTION DISASSEMBLY:"
  130. dis.dis(func)
  131. print
  132. n = 12.0
  133. print "func(%s) =" % n, func(n)