customize38.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. # Copyright (c) 2019-2020, 2022, 2024 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 3.8 version-specific semantic actions here.
  16. """
  17. ########################
  18. # Python 3.8+ changes
  19. #######################
  20. from uncompyle6.semantics.consts import PRECEDENCE, TABLE_DIRECT
  21. from uncompyle6.semantics.customize37 import FSTRING_CONVERSION_MAP
  22. from uncompyle6.semantics.helper import escape_string, strip_quotes
  23. def customize_for_version38(self, version: tuple):
  24. # FIXME: pytest doesn't add proper keys in testing. Reinstate after we have fixed pytest.
  25. # for lhs in 'for forelsestmt forelselaststmt '
  26. # 'forelselaststmtc tryfinally38'.split():
  27. # del TABLE_DIRECT[lhs]
  28. self.TABLE_DIRECT.update(
  29. {
  30. "async_for_stmt38": (
  31. "%|async for %c in %c:\n%+%c%-%-\n\n",
  32. (2, "store"),
  33. (0, "expr"),
  34. (3, ("for_block", "pass")),
  35. ),
  36. "async_forelse_stmt38": (
  37. "%|async for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
  38. (7, "store"),
  39. (0, "expr"),
  40. (8, "for_block"),
  41. (-1, "else_suite"),
  42. ),
  43. "async_with_stmt38": (
  44. "%|async with %c:\n%+%c%-\n",
  45. (0, "expr"),
  46. (7, ("l_stmts_opt", "l_stmts", "pass")),
  47. ),
  48. "async_with_as_stmt38": (
  49. "%|async with %c as %c:\n%+%|%c%-",
  50. (0, "expr"),
  51. (6, "store"),
  52. (7, "suite_stmts"),
  53. ),
  54. "c_forelsestmt38": (
  55. "%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
  56. (2, "store"),
  57. (0, "expr"),
  58. (3, "for_block"),
  59. -1,
  60. ),
  61. "c_tryfinallystmt38": (
  62. "%|try:\n%+%c%-%|finally:\n%+%c%-\n\n",
  63. (1, "c_suite_stmts_opt"),
  64. (-2, "c_suite_stmts_opt"),
  65. ),
  66. # Python 3.8 reverses the order of keys and items
  67. # from all prior versions of Python.
  68. "dict_comp_body": (
  69. "%c: %c",
  70. (0, "expr"),
  71. (1, "expr"),
  72. ),
  73. "except_cond1a": (
  74. "%|except %c:\n",
  75. (1, "expr"),
  76. ),
  77. "except_cond_as": (
  78. "%|except %c as %c:\n",
  79. (1, "expr"),
  80. (-2, "STORE_FAST"),
  81. ),
  82. "except_handler38": ("%c", (2, "except_stmts")),
  83. "except_handler38a": ("%c", (-2, "stmts")),
  84. "except_handler38c": (
  85. "%c%+%c%-",
  86. (1, "except_cond1a"),
  87. (2, "except_stmts"),
  88. ),
  89. "except_handler_as": (
  90. "%c%+\n%+%c%-",
  91. (1, "except_cond_as"),
  92. (2, "tryfinallystmt"),
  93. ),
  94. "except_ret38a": ("return %c", (4, "expr")),
  95. # Note: there is a suite_stmts_opt which seems
  96. # to be bookkeeping which is not expressed in source code
  97. "except_ret38": ("%|return %c\n", (1, "expr")),
  98. "for38": (
  99. "%|for %c in %c:\n%+%c%-\n\n",
  100. (2, "store"),
  101. (0, "expr"),
  102. (3, "for_block"),
  103. ),
  104. "forelsestmt38": (
  105. "%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
  106. (2, "store"),
  107. (0, "expr"),
  108. (3, "for_block"),
  109. -1,
  110. ),
  111. "forelselaststmt38": (
  112. "%|for %c in %c:\n%+%c%-%|else:\n%+%c%-",
  113. (2, "store"),
  114. (0, "expr"),
  115. (3, "for_block"),
  116. -2,
  117. ),
  118. "forelselaststmtc38": (
  119. "%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n",
  120. (2, "store"),
  121. (0, "expr"),
  122. (3, "for_block"),
  123. -2,
  124. ),
  125. "ifpoplaststmtc": ("%|if %c:\n%+%c%-", (0, "testexpr"), (2, "l_stmts")),
  126. "named_expr": ( # AKA "walrus operator"
  127. "%c := %p",
  128. (2, "store"),
  129. (0, "expr", PRECEDENCE["named_expr"] - 1),
  130. ),
  131. "pop_return": ("%|return %c\n", (1, "return_expr")),
  132. "popb_return": ("%|return %c\n", (0, "return_expr")),
  133. "pop_ex_return": ("%|return %c\n", (0, "return_expr")),
  134. "set_for": (
  135. " for %c in %c",
  136. (2, "store"),
  137. (0, "expr_or_arg"),
  138. ),
  139. "whilestmt38": (
  140. "%|while %c:\n%+%c%-\n\n",
  141. (1, ("bool_op", "testexpr", "testexprc")),
  142. (2, ("_stmts", "l_stmts", "l_stmts_opt", "pass")),
  143. ),
  144. "whileTruestmt38": (
  145. "%|while True:\n%+%c%-\n\n",
  146. (1, ("l_stmts", "pass")),
  147. ),
  148. "try_elsestmtl38": (
  149. "%|try:\n%+%c%-%c%|else:\n%+%c%-",
  150. (1, "suite_stmts_opt"),
  151. (3, "except_handler38"),
  152. (5, "else_suitel"),
  153. ),
  154. "try_except38": (
  155. "%|try:\n%+%c\n%-%|except:\n%+%c%-\n\n",
  156. (2, ("suite_stmts_opt", "suite_stmts")),
  157. (3, ("except_handler38a", "except_handler38b", "except_handler38c")),
  158. ),
  159. "try_except38r": (
  160. "%|try:\n%+%c\n%-%|except:\n%+%c%-\n\n",
  161. (1, "return_except"),
  162. (2, "except_handler38b"),
  163. ),
  164. "try_except38r2": (
  165. "%|try:\n%+%c\n%-%|except:\n%+%c%c%-\n\n",
  166. (1, "suite_stmts_opt"),
  167. (8, "cond_except_stmts_opt"),
  168. (10, "return"),
  169. ),
  170. "try_except38r4": (
  171. "%|try:\n%+%c\n%-%|except:\n%+%c%c%-\n\n",
  172. (1, "returns_in_except"),
  173. (3, "except_cond1"),
  174. (4, "return"),
  175. ),
  176. "try_except_as": (
  177. "%|try:\n%+%c%-\n%|%-%c\n\n",
  178. (
  179. -4,
  180. ("suite_stmts", "_stmts"),
  181. ), # Go from the end because of POP_BLOCK variation
  182. (-3, "except_handler_as"),
  183. ),
  184. "try_except_ret38": (
  185. "%|try:\n%+%c%-\n%|except:\n%+%|%c%-\n\n",
  186. (1, "returns"),
  187. (2, "except_ret38a"),
  188. ),
  189. "try_except_ret38a": (
  190. "%|try:\n%+%c%-%c\n\n",
  191. (1, "returns"),
  192. (2, "except_handler38c"),
  193. ),
  194. "tryfinally38rstmt": (
  195. "%|try:\n%+%c%-%|finally:\n%+%c%-\n\n",
  196. (0, "sf_pb_call_returns"),
  197. (-1, ("ss_end_finally", "suite_stmts", "_stmts")),
  198. ),
  199. "tryfinally38rstmt2": (
  200. "%|try:\n%+%c%-%|finally:\n%+%c%-\n\n",
  201. (4, "returns"),
  202. -2,
  203. "ss_end_finally",
  204. ),
  205. "tryfinally38rstmt3": (
  206. "%|try:\n%+%|return %c%-\n%|finally:\n%+%c%-\n\n",
  207. (1, "expr"),
  208. (-1, "ss_end_finally"),
  209. ),
  210. "tryfinally38rstmt4": (
  211. "%|try:\n%+%c%-\n%|finally:\n%+%c%-\n\n",
  212. (1, "suite_stmts_opt"),
  213. (5, "suite_stmts_return"),
  214. ),
  215. "tryfinally38stmt": (
  216. "%|try:\n%+%c%-%|finally:\n%+%c%-\n\n",
  217. (1, "suite_stmts_opt"),
  218. (6, "suite_stmts_opt"),
  219. ),
  220. "tryfinally38astmt": (
  221. "%|try:\n%+%c%-%|finally:\n%+%c%-\n\n",
  222. (2, "suite_stmts_opt"),
  223. (8, "suite_stmts_opt"),
  224. ),
  225. "with_as_pass": (
  226. "%|with %c as %c:\n%+%c%-",
  227. (0, "expr"),
  228. (2, "store"),
  229. (3, "pass"),
  230. ),
  231. }
  232. )
  233. def except_return_value(node):
  234. if node[0] == "POP_BLOCK":
  235. self.default(node[1])
  236. else:
  237. self.template_engine(("%|return %c\n", (0, "expr")), node)
  238. self.prune()
  239. self.n_except_return_value = except_return_value
  240. # FIXME: now that we've split out cond_except_stmt,
  241. # we should be able to get this working as a pure transformation rule,
  242. # so no procedure is needed here.
  243. def try_except38r3(node):
  244. self.template_engine(("%|try:\n%+%c\n%-", (1, "suite_stmts_opt")), node)
  245. cond_except_stmts_opt = node[5]
  246. assert cond_except_stmts_opt == "cond_except_stmts_opt"
  247. for child in cond_except_stmts_opt:
  248. if child == "cond_except_stmt":
  249. if child[0] == "except_cond1":
  250. self.template_engine(
  251. ("%c\n", (0, "except_cond1"), (1, "expr")), child
  252. )
  253. self.template_engine(("%+%c%-\n", (1, "except_stmts")), child)
  254. pass
  255. pass
  256. self.template_engine(("%+%c%-\n", (7, "return")), node)
  257. self.prune()
  258. self.n_try_except38r3 = try_except38r3
  259. def n_list_afor(node):
  260. if len(node) == 2:
  261. # list_afor ::= get_iter list_afor
  262. self.comprehension_walk_newer(node, 0)
  263. else:
  264. list_iter_index = 2 if node[2] == "list_iter" else 3
  265. self.template_engine(
  266. (
  267. " async for %[1]{%c} in %c%[1]{%c}",
  268. (1, "store"),
  269. (0, "get_aiter"),
  270. (list_iter_index, "list_iter"),
  271. ),
  272. node,
  273. )
  274. self.prune()
  275. self.n_list_afor = n_list_afor
  276. def n_set_afor(node):
  277. if len(node) == 2:
  278. self.template_engine(
  279. (" async for %[1]{%c} in %c", (1, "store"), (0, "get_aiter")), node
  280. )
  281. else:
  282. self.template_engine(
  283. " async for %[1]{%c} in %c%c",
  284. (1, "store"),
  285. (0, "get_aiter"),
  286. (2, "set_iter"),
  287. )
  288. self.prune()
  289. self.n_set_afor = n_set_afor
  290. def n_formatted_value_debug(node):
  291. p = self.prec
  292. self.prec = 100
  293. formatted_value = node[1]
  294. value_equal = node[0].attr
  295. assert formatted_value.kind.startswith("formatted_value")
  296. old_in_format_string = self.in_format_string
  297. self.in_format_string = formatted_value.kind
  298. format_value_attr = node[-1]
  299. post_str = ""
  300. if node[-1] == "BUILD_STRING_3":
  301. post_load_str = node[-2]
  302. post_str = self.traverse(post_load_str, indent="")
  303. post_str = strip_quotes(post_str)
  304. if format_value_attr == "FORMAT_VALUE_ATTR":
  305. attr = format_value_attr.attr
  306. if attr & 4:
  307. fmt = strip_quotes(self.traverse(node[3], indent=""))
  308. attr_flags = attr & 3
  309. if attr_flags:
  310. conversion = "%s:%s" % (
  311. FSTRING_CONVERSION_MAP.get(attr_flags, ""),
  312. fmt,
  313. )
  314. else:
  315. conversion = ":%s" % fmt
  316. else:
  317. conversion = FSTRING_CONVERSION_MAP.get(attr, "")
  318. f_str = "f%s" % escape_string(
  319. "{%s%s}%s" % (value_equal, conversion, post_str)
  320. )
  321. else:
  322. f_conversion = self.traverse(formatted_value, indent="")
  323. # Remove leaving "f" and quotes
  324. conversion = strip_quotes(f_conversion[1:])
  325. f_str = "f%s" % escape_string(f"{value_equal}{conversion}" + post_str)
  326. self.write(f_str)
  327. self.in_format_string = old_in_format_string
  328. self.prec = p
  329. self.prune()
  330. self.n_formatted_value_debug = n_formatted_value_debug
  331. def n_suite_stmts_return(node):
  332. if len(node) > 1:
  333. assert len(node) == 2
  334. self.template_engine(
  335. ("%c\n%|return %c", (0, ("_stmts", "suite_stmts")), (1, "expr")), node
  336. )
  337. else:
  338. self.template_engine(("%|return %c", (0, "expr")), node)
  339. self.prune()
  340. self.n_suite_stmts_return = n_suite_stmts_return