scanner27.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. # Copyright (c) 2015-2018, 2021-2022 by Rocky Bernstein
  2. """
  3. Python 2.7 bytecode ingester.
  4. This massages tokenized 2.7 bytecode to make it more amenable for
  5. grammar parsing.
  6. """
  7. from uncompyle6.scanners.scanner2 import Scanner2
  8. from xdis.version_info import version_tuple_to_str
  9. import sys
  10. intern = sys.intern
  11. # bytecode verification, verify(), uses JUMP_OPs from here
  12. from xdis.opcodes import opcode_27
  13. JUMP_OPS = opcode_27.JUMP_OPs
  14. class Scanner27(Scanner2):
  15. def __init__(self, show_asm=False, is_pypy=False):
  16. super(Scanner27, self).__init__((2, 7), show_asm, is_pypy)
  17. # opcodes that start statements
  18. self.statement_opcodes = frozenset(
  19. self.statement_opcodes
  20. | set(
  21. [
  22. # New in 2.7
  23. self.opc.SETUP_WITH,
  24. self.opc.STORE_SLICE_0,
  25. self.opc.STORE_SLICE_1,
  26. self.opc.STORE_SLICE_2,
  27. self.opc.STORE_SLICE_3,
  28. self.opc.DELETE_SLICE_0,
  29. self.opc.DELETE_SLICE_1,
  30. self.opc.DELETE_SLICE_2,
  31. self.opc.DELETE_SLICE_3,
  32. ]
  33. )
  34. )
  35. # opcodes which expect a variable number pushed values and whose
  36. # count is in the opcode. For parsing we generally change the
  37. # opcode name to include that number.
  38. varargs_ops = set(
  39. [
  40. self.opc.BUILD_LIST,
  41. self.opc.BUILD_TUPLE,
  42. self.opc.BUILD_SLICE,
  43. self.opc.UNPACK_SEQUENCE,
  44. self.opc.MAKE_FUNCTION,
  45. self.opc.CALL_FUNCTION,
  46. self.opc.MAKE_CLOSURE,
  47. self.opc.CALL_FUNCTION_VAR,
  48. self.opc.CALL_FUNCTION_KW,
  49. self.opc.CALL_FUNCTION_VAR_KW,
  50. self.opc.DUP_TOPX,
  51. self.opc.RAISE_VARARGS,
  52. # New in Python 2.7
  53. self.opc.BUILD_SET,
  54. self.opc.BUILD_MAP,
  55. ]
  56. )
  57. if is_pypy:
  58. varargs_ops.add(self.opc.CALL_METHOD)
  59. self.varargs_ops = frozenset(varargs_ops)
  60. # "setup" opcodes
  61. self.setup_ops = frozenset(
  62. [
  63. self.opc.SETUP_EXCEPT,
  64. self.opc.SETUP_FINALLY,
  65. # New in 2.7
  66. self.opc.SETUP_WITH,
  67. ]
  68. )
  69. # opcodes that store values into a variable
  70. self.designator_ops = frozenset(
  71. [
  72. self.opc.STORE_FAST,
  73. self.opc.STORE_NAME,
  74. self.opc.STORE_GLOBAL,
  75. self.opc.STORE_DEREF,
  76. self.opc.STORE_ATTR,
  77. self.opc.STORE_SLICE_0,
  78. self.opc.STORE_SLICE_1,
  79. self.opc.STORE_SLICE_2,
  80. self.opc.STORE_SLICE_3,
  81. self.opc.STORE_SUBSCR,
  82. self.opc.UNPACK_SEQUENCE,
  83. self.opc.JUMP_ABSOLUTE,
  84. ]
  85. )
  86. self.pop_jump_if_or_pop = frozenset(
  87. [self.opc.JUMP_IF_FALSE_OR_POP, self.opc.JUMP_IF_TRUE_OR_POP]
  88. )
  89. return
  90. pass
  91. if __name__ == "__main__":
  92. from xdis.version_info import PYTHON_VERSION_TRIPLE
  93. if PYTHON_VERSION_TRIPLE[:2] == (2, 7):
  94. import inspect
  95. co = inspect.currentframe().f_code # type: ignore
  96. tokens, customize = Scanner27().ingest(co)
  97. for t in tokens:
  98. print(t.format())
  99. pass
  100. else:
  101. print("Need to be Python 2.7 to demo; I am version %s" % version_tuple_to_str())