customize.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. # Copyright (c) 2018-2022 by Rocky Bernstein
  2. #
  3. # This program is free software: you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation, either version 3 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. """Isolate Python version-specific semantic actions here.
  16. """
  17. from decompyle3.semantics.consts import (
  18. INDENT_PER_LEVEL,
  19. NO_PARENTHESIS_EVER,
  20. PRECEDENCE,
  21. TABLE_DIRECT,
  22. )
  23. from decompyle3.semantics.helper import flatten_list
  24. def customize_for_version(self, is_pypy, version):
  25. if is_pypy:
  26. ########################
  27. # PyPy changes
  28. #######################
  29. # fmt: off
  30. TABLE_DIRECT.update(
  31. {
  32. "assert": ("%|assert %c\n", 0),
  33. # This can happen as a result of an if transformation
  34. "assert2": ("%|assert %c, %c\n", 0, 3),
  35. "assert_pypy": ("%|assert %c\n", (1, "assert_expr")),
  36. "assert2_pypy": ("%|assert %c, %c\n", 1, 4),
  37. # This is as a result of an if transformation
  38. "assert0_pypy": ("%|assert %c\n", (0, "assert_expr")),
  39. "assert_not_pypy": ("%|assert not %c\n", (1, "assert_exp")),
  40. "assert2_not_pypy": (
  41. "%|assert not %c, %c\n",
  42. (1, "assert_exp"),
  43. (4, "expr"),
  44. ),
  45. "try_except_pypy": ("%|try:\n%+%c%-%c\n\n", 1, 2),
  46. "tryfinallystmt_pypy": ("%|try:\n%+%c%-%|finally:\n%+%c%-\n\n", 1, 3),
  47. "assign3_pypy": ("%|%c, %c, %c = %c, %c, %c\n", 5, 4, 3, 0, 1, 2),
  48. "assign2_pypy": ("%|%c, %c = %c, %c\n", 3, 2, 0, 1),
  49. }
  50. )
  51. # fmt: on
  52. # At one time PyPy did this but now follows CPython?
  53. if version[:2] >= (3, 7):
  54. def n_call_kw_pypy37(node):
  55. self.template_engine(("%p(", (0, NO_PARENTHESIS_EVER)), node)
  56. assert node[-1] == "CALL_METHOD_KW"
  57. arg_count = node[-1].attr
  58. kw_names = node[-2]
  59. assert kw_names == "pypy_kw_keys"
  60. kwargs_names = kw_names[0].attr
  61. kwarg_count = len(kwargs_names)
  62. pos_argc = arg_count - kwarg_count
  63. flat_elems = flatten_list(node[1:-2])
  64. n = len(flat_elems)
  65. assert n == arg_count, f"n: {n}, arg_count: {arg_count}\n{node}"
  66. sep = ""
  67. for i in range(pos_argc):
  68. elem = flat_elems[i]
  69. line_number = self.line_number
  70. value = self.traverse(elem)
  71. if line_number != self.line_number:
  72. sep += "\n" + self.indent + INDENT_PER_LEVEL[:-1]
  73. pass
  74. self.write(f"{sep}{value}")
  75. sep = ", "
  76. assert n >= len(kwargs_names)
  77. j = pos_argc
  78. for i in range(kwarg_count):
  79. elem = flat_elems[j]
  80. j += 1
  81. assert elem == "expr"
  82. line_number = self.line_number
  83. value = self.traverse(elem)
  84. if line_number != self.line_number:
  85. sep += "\n" + self.indent + INDENT_PER_LEVEL[:-1]
  86. pass
  87. self.write(f"{sep}{kwargs_names[i]}={value}")
  88. sep = ", "
  89. pass
  90. self.write(")")
  91. self.prune()
  92. self.n_call_kw_pypy37 = n_call_kw_pypy37
  93. else:
  94. ########################
  95. # Without PyPy
  96. #######################
  97. TABLE_DIRECT.update(
  98. {
  99. # "assert" and "assert_expr" are added via transform rules.
  100. "assert": ("%|assert %c\n", 0),
  101. "assert2": ("%|assert %c, %c\n", 0, 3),
  102. # Created only via transformation
  103. "assertnot": ("%|assert not %p\n", (0, PRECEDENCE["unary_not"])),
  104. "assert2not": (
  105. "%|assert not %p, %c\n",
  106. (0, PRECEDENCE["unary_not"]),
  107. 3,
  108. ),
  109. "assign2": ("%|%c, %c = %c, %c\n", 3, 4, 0, 1),
  110. "assign3": ("%|%c, %c, %c = %c, %c, %c\n", 5, 6, 7, 0, 1, 2),
  111. "try_except": ("%|try:\n%+%c%-%c\n\n", 1, 3),
  112. }
  113. )
  114. if version >= (3, 2):
  115. TABLE_DIRECT.update(
  116. {
  117. "del_deref_stmt": ("%|del %c\n", 0),
  118. "DELETE_DEREF": ("%{pattr}", 0),
  119. }
  120. )
  121. from decompyle3.semantics.customize3 import customize_for_version3
  122. customize_for_version3(self, version)
  123. return