superacli 1.1.6 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1268) hide show
  1. package/CONTRIBUTING.md +270 -0
  2. package/README.md +141 -54
  3. package/__tests__/adapter-schema.test.js +251 -86
  4. package/__tests__/azd-plugin.test.js +109 -0
  5. package/__tests__/config.test.js +4 -3
  6. package/__tests__/discover.test.js +59 -0
  7. package/__tests__/goose-plugin.test.js +149 -0
  8. package/__tests__/help-json.test.js +2 -0
  9. package/__tests__/openhands-plugin.test.js +106 -0
  10. package/__tests__/plugin-cocoindex-code-uninstall.test.js +19 -0
  11. package/__tests__/plugin-cocoindex-code.test.js +37 -0
  12. package/__tests__/plugin-install-guidance.test.js +81 -0
  13. package/__tests__/plugins-registry.test.js +44 -0
  14. package/__tests__/plugins-store.test.js +40 -5
  15. package/__tests__/process-adapter.test.js +50 -1
  16. package/__tests__/resend-plugin.test.js +109 -82
  17. package/__tests__/server-app.test.js +1 -0
  18. package/__tests__/server-routes-commands.test.js +20 -2
  19. package/__tests__/server-routes-plugins.test.js +130 -0
  20. package/__tests__/skills.test.js +26 -0
  21. package/__tests__/squirrelscan-plugin.test.js +129 -0
  22. package/__tests__/uipath-plugin.test.js +104 -0
  23. package/__tests__/uipathcli-plugin.test.js +95 -0
  24. package/cli/adapters/mcp.js +2 -0
  25. package/cli/adapters/process.js +50 -7
  26. package/cli/config.js +240 -3
  27. package/cli/discover.js +157 -0
  28. package/cli/help-json.js +16 -1
  29. package/cli/plugin-install-guidance.js +92 -37
  30. package/cli/plugins-manager.js +4 -3
  31. package/cli/plugins-registry.js +74 -8
  32. package/cli/plugins-store.js +78 -17
  33. package/cli/skills-mcp.js +1 -1
  34. package/cli/skills.js +39 -2
  35. package/cli/supercli.js +255 -63
  36. package/docs/feature-gaps.md +8 -8
  37. package/docs/features/azd-uipath-plugins.md +43 -0
  38. package/docs/features/server-plugins.md +62 -0
  39. package/docs/features/skills.md +9 -5
  40. package/docs/index.html +183 -123
  41. package/docs/{supported-harnesses.md → plugins-available.md} +4 -3
  42. package/docs/{plugin-harness-guide.md → plugins-how-to.md} +1 -1
  43. package/docs/plugins.md +26 -20
  44. package/docs/server-plugins-usage-guide.md +182 -0
  45. package/docs/skills-catalog.md +12 -10
  46. package/index.html +384 -0
  47. package/package.json +2 -2
  48. package/plugins/agent-browser/README.md +69 -0
  49. package/plugins/agent-browser/plugin.json +111 -0
  50. package/plugins/agent-browser/skills/quickstart/SKILL.md +66 -0
  51. package/plugins/aider/README.md +53 -0
  52. package/plugins/aider/plugin.json +105 -0
  53. package/plugins/aider/scripts/aider-wrapper.js +243 -0
  54. package/plugins/aider/scripts/setup-aider.js +37 -0
  55. package/plugins/aider/skills/dry-run-review.md +24 -0
  56. package/plugins/aider/skills/model-and-provider.md +24 -0
  57. package/plugins/aider/skills/one-shot-edits.md +30 -0
  58. package/plugins/aider/skills/quickstart/SKILL.md +51 -0
  59. package/plugins/azd/README.md +28 -0
  60. package/plugins/azd/plugin.json +87 -0
  61. package/plugins/azd/skills/quickstart/SKILL.md +41 -0
  62. package/plugins/blogwatcher/README.md +3 -3
  63. package/plugins/boxlite/Dockerfile +9 -0
  64. package/plugins/boxlite/README.md +62 -0
  65. package/plugins/boxlite/plugin.json +201 -0
  66. package/plugins/boxlite/scripts/run-boxlite.js +106 -0
  67. package/plugins/boxlite/skills/quickstart/SKILL.md +40 -0
  68. package/plugins/cass/plugin.json +150 -0
  69. package/plugins/cass/scripts/setup-cass.js +47 -0
  70. package/plugins/cass/skills/quickstart/SKILL.md +46 -0
  71. package/plugins/clever/README.md +46 -0
  72. package/plugins/clever/plugin.json +119 -0
  73. package/plugins/clever/scripts/setup-clever.js +28 -0
  74. package/plugins/clever/skills/auth-and-profile.md +29 -0
  75. package/plugins/clever/skills/passthrough-safety.md +21 -0
  76. package/plugins/clever/skills/quickstart/SKILL.md +45 -0
  77. package/plugins/clever/skills/resource-inventory.md +24 -0
  78. package/plugins/clix/README.md +4 -4
  79. package/plugins/cocoindex-code/README.md +64 -0
  80. package/plugins/cocoindex-code/plugin.json +81 -0
  81. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-310.pyc +0 -0
  82. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-311.pyc +0 -0
  83. package/plugins/cocoindex-code/scripts/post-install.js +61 -0
  84. package/plugins/cocoindex-code/scripts/post-uninstall.js +25 -0
  85. package/plugins/cocoindex-code/scripts/query.py +88 -0
  86. package/plugins/cocoindex-code/scripts/run-query.js +50 -0
  87. package/plugins/cocoindex-code/skills/quickstart/SKILL.md +73 -0
  88. package/plugins/copilot/README.md +24 -0
  89. package/plugins/copilot/plugin.json +80 -0
  90. package/plugins/copilot/skills/quickstart/SKILL.md +44 -0
  91. package/plugins/gemini/README.md +24 -0
  92. package/plugins/gemini/plugin.json +98 -0
  93. package/plugins/gemini/skills/quickstart/SKILL.md +44 -0
  94. package/plugins/gifcap/plugin.json +119 -0
  95. package/plugins/gifcap/scripts/setup-gifcap.js +44 -0
  96. package/plugins/gifcap/skills/quickstart/SKILL.md +34 -0
  97. package/plugins/gifcap/test-record-quiet.gif +0 -0
  98. package/plugins/gifcap/test-record.gif +0 -0
  99. package/plugins/goose/README.md +36 -0
  100. package/plugins/goose/plugin.json +183 -0
  101. package/plugins/goose/skills/quickstart/SKILL.md +44 -0
  102. package/plugins/json-server/README.md +58 -0
  103. package/plugins/json-server/plugin.json +113 -0
  104. package/plugins/json-server/skills/quickstart/SKILL.md +57 -0
  105. package/plugins/lightpanda/README.md +145 -0
  106. package/plugins/lightpanda/package-lock.json +1375 -0
  107. package/plugins/lightpanda/package.json +12 -0
  108. package/plugins/lightpanda/plugin.json +116 -0
  109. package/plugins/lightpanda/scripts/lightpanda-contacts.js +494 -0
  110. package/plugins/lightpanda/scripts/lightpanda-generic-extract.js +403 -0
  111. package/plugins/lightpanda/scripts/lightpanda-wrapper.js +480 -0
  112. package/plugins/lightpanda/scripts/setup-lightpanda.js +39 -0
  113. package/plugins/lightpanda/skills/contact-discovery.md +51 -0
  114. package/plugins/lightpanda/skills/generic-extraction.md +66 -0
  115. package/plugins/lightpanda/skills/quickstart/SKILL.md +103 -0
  116. package/plugins/lightpanda/skills/resilient-navigation.md +42 -0
  117. package/plugins/monty/README.md +2 -2
  118. package/plugins/nullclaw/README.md +3 -3
  119. package/plugins/offline-ai/README.md +23 -0
  120. package/plugins/offline-ai/plugin.json +82 -0
  121. package/plugins/offline-ai/skills/quickstart/SKILL.md +43 -0
  122. package/plugins/openhands/README.md +25 -0
  123. package/plugins/openhands/plugin.json +116 -0
  124. package/plugins/openhands/skills/quickstart/SKILL.md +26 -0
  125. package/plugins/plandex/README.md +25 -0
  126. package/plugins/plandex/plugin.json +130 -0
  127. package/plugins/plandex/skills/quickstart/SKILL.md +50 -0
  128. package/plugins/plugins.json +199 -0
  129. package/plugins/squirrelscan/Dockerfile +5 -0
  130. package/plugins/squirrelscan/README.md +47 -0
  131. package/plugins/squirrelscan/plugin.json +493 -0
  132. package/plugins/squirrelscan/scripts/post-install.js +33 -0
  133. package/plugins/squirrelscan/scripts/post-uninstall.js +25 -0
  134. package/plugins/squirrelscan/scripts/run-squirrel.js +73 -0
  135. package/plugins/squirrelscan/skills/audit-workflow/SKILL.md +33 -0
  136. package/plugins/squirrelscan/skills/publish-report/SKILL.md +33 -0
  137. package/plugins/squirrelscan/skills/quickstart/SKILL.md +41 -0
  138. package/plugins/uipath/README.md +27 -0
  139. package/plugins/uipath/plugin.json +86 -0
  140. package/plugins/uipath/skills/quickstart/SKILL.md +47 -0
  141. package/plugins/uipathcli/README.md +28 -0
  142. package/plugins/uipathcli/plugin.json +120 -0
  143. package/plugins/uipathcli/scripts/run-uipath-cli.js +49 -0
  144. package/plugins/uipathcli/skills/quickstart/SKILL.md +22 -0
  145. package/plugins/xurl/README.md +4 -4
  146. package/server/app.js +5 -2
  147. package/server/public/app.js +3 -0
  148. package/server/routes/commands.js +95 -12
  149. package/server/routes/plugins.js +262 -0
  150. package/server/services/pluginsService.js +303 -0
  151. package/server/views/command-edit.ejs +196 -14
  152. package/server/views/partials/head.ejs +1 -0
  153. package/server/views/plugins.ejs +264 -0
  154. package/tests/test-plugins-registry.js +30 -0
  155. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl +0 -20
  156. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl.meta.json +0 -1
  157. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl +0 -21
  158. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl.meta.json +0 -1
  159. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl +0 -22
  160. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl.meta.json +0 -1
  161. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl +0 -23
  162. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl.meta.json +0 -1
  163. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl +0 -24
  164. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl.meta.json +0 -1
  165. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl +0 -24
  166. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl.meta.json +0 -1
  167. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl +0 -24
  168. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl.meta.json +0 -1
  169. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl +0 -24
  170. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl.meta.json +0 -1
  171. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl +0 -24
  172. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl.meta.json +0 -1
  173. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl +0 -24
  174. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl.meta.json +0 -1
  175. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl +0 -24
  176. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl.meta.json +0 -1
  177. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl +0 -24
  178. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl.meta.json +0 -1
  179. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl +0 -24
  180. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl.meta.json +0 -1
  181. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl +0 -25
  182. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl.meta.json +0 -1
  183. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl +0 -25
  184. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl.meta.json +0 -1
  185. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl +0 -25
  186. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl.meta.json +0 -1
  187. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl +0 -26
  188. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl.meta.json +0 -1
  189. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl +0 -27
  190. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl.meta.json +0 -1
  191. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl +0 -28
  192. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl.meta.json +0 -1
  193. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl +0 -29
  194. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl.meta.json +0 -1
  195. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl +0 -30
  196. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl.meta.json +0 -1
  197. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl +0 -31
  198. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl.meta.json +0 -1
  199. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl +0 -32
  200. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl.meta.json +0 -1
  201. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl +0 -32
  202. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl.meta.json +0 -1
  203. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl +0 -32
  204. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl.meta.json +0 -1
  205. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl +0 -32
  206. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl.meta.json +0 -1
  207. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl +0 -32
  208. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl.meta.json +0 -1
  209. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl +0 -32
  210. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl.meta.json +0 -1
  211. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl +0 -32
  212. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl.meta.json +0 -1
  213. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl +0 -32
  214. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl.meta.json +0 -1
  215. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl +0 -32
  216. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl.meta.json +0 -1
  217. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl +0 -32
  218. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl.meta.json +0 -1
  219. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl +0 -32
  220. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl.meta.json +0 -1
  221. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl +0 -32
  222. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl.meta.json +0 -1
  223. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl +0 -32
  224. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl.meta.json +0 -1
  225. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl +0 -32
  226. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl.meta.json +0 -1
  227. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl +0 -33
  228. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl.meta.json +0 -1
  229. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl +0 -33
  230. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl.meta.json +0 -1
  231. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl +0 -34
  232. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl.meta.json +0 -1
  233. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl +0 -34
  234. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl.meta.json +0 -1
  235. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl +0 -35
  236. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl.meta.json +0 -1
  237. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl +0 -36
  238. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl.meta.json +0 -1
  239. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl +0 -37
  240. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl.meta.json +0 -1
  241. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl +0 -38
  242. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl.meta.json +0 -1
  243. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl +0 -39
  244. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl.meta.json +0 -1
  245. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl +0 -40
  246. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl.meta.json +0 -1
  247. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl +0 -41
  248. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl.meta.json +0 -1
  249. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl +0 -42
  250. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl.meta.json +0 -1
  251. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl +0 -43
  252. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl.meta.json +0 -1
  253. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl +0 -44
  254. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl.meta.json +0 -1
  255. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl +0 -45
  256. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl.meta.json +0 -1
  257. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl +0 -46
  258. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl.meta.json +0 -1
  259. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl +0 -47
  260. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl.meta.json +0 -1
  261. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl +0 -48
  262. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl.meta.json +0 -1
  263. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl +0 -49
  264. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl.meta.json +0 -1
  265. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl +0 -50
  266. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl.meta.json +0 -1
  267. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl +0 -51
  268. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl.meta.json +0 -1
  269. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl +0 -52
  270. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl.meta.json +0 -1
  271. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl +0 -53
  272. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl.meta.json +0 -1
  273. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl +0 -54
  274. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl.meta.json +0 -1
  275. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl +0 -55
  276. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl.meta.json +0 -1
  277. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl +0 -56
  278. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl.meta.json +0 -1
  279. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl +0 -57
  280. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl.meta.json +0 -1
  281. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl +0 -57
  282. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl.meta.json +0 -1
  283. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl +0 -57
  284. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl.meta.json +0 -1
  285. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl +0 -57
  286. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl.meta.json +0 -1
  287. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl +0 -57
  288. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl.meta.json +0 -1
  289. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl +0 -57
  290. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl.meta.json +0 -1
  291. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl +0 -57
  292. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl.meta.json +0 -1
  293. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl +0 -57
  294. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl.meta.json +0 -1
  295. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl +0 -57
  296. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl.meta.json +0 -1
  297. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl +0 -57
  298. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl.meta.json +0 -1
  299. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl +0 -57
  300. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl.meta.json +0 -1
  301. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl +0 -57
  302. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl.meta.json +0 -1
  303. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl +0 -57
  304. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl.meta.json +0 -1
  305. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl +0 -57
  306. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl.meta.json +0 -1
  307. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl +0 -57
  308. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl.meta.json +0 -1
  309. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl +0 -57
  310. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl.meta.json +0 -1
  311. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl +0 -57
  312. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl.meta.json +0 -1
  313. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl +0 -57
  314. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl.meta.json +0 -1
  315. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl +0 -57
  316. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl.meta.json +0 -1
  317. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl +0 -57
  318. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl.meta.json +0 -1
  319. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl +0 -57
  320. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl.meta.json +0 -1
  321. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl +0 -57
  322. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl.meta.json +0 -1
  323. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl +0 -57
  324. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl.meta.json +0 -1
  325. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl +0 -57
  326. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl.meta.json +0 -1
  327. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl +0 -57
  328. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl.meta.json +0 -1
  329. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl +0 -57
  330. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl.meta.json +0 -1
  331. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl +0 -57
  332. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl.meta.json +0 -1
  333. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl +0 -57
  334. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl.meta.json +0 -1
  335. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl +0 -57
  336. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl.meta.json +0 -1
  337. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl +0 -57
  338. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl.meta.json +0 -1
  339. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl +0 -58
  340. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl.meta.json +0 -1
  341. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl +0 -59
  342. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl.meta.json +0 -1
  343. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl +0 -60
  344. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl.meta.json +0 -1
  345. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl +0 -60
  346. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl.meta.json +0 -1
  347. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl +0 -60
  348. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl.meta.json +0 -1
  349. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl +0 -60
  350. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl.meta.json +0 -1
  351. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl +0 -60
  352. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl.meta.json +0 -1
  353. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl +0 -60
  354. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl.meta.json +0 -1
  355. package/.beads/config.yaml +0 -4
  356. package/.beads/issues.jsonl +0 -60
  357. package/.beads/metadata.json +0 -4
  358. package/docs/docs.html +0 -224
  359. package/docs/mcp-cheatsheet.md +0 -324
  360. package/docs/visual-overview.md +0 -21
  361. package/ref-monty/.cargo/config.toml +0 -3
  362. package/ref-monty/.claude/settings.json +0 -60
  363. package/ref-monty/.claude/skills/fastmod/SKILL.md +0 -22
  364. package/ref-monty/.claude/skills/python-playground/SKILL.md +0 -47
  365. package/ref-monty/.codecov.yml +0 -12
  366. package/ref-monty/.github/actions/build-pgo-wheel/action.yml +0 -72
  367. package/ref-monty/.github/workflows/ci.yml +0 -776
  368. package/ref-monty/.github/workflows/codspeed.yml +0 -45
  369. package/ref-monty/.github/workflows/init-npm-packages.yml +0 -82
  370. package/ref-monty/.pre-commit-config.yaml +0 -47
  371. package/ref-monty/.python-version +0 -1
  372. package/ref-monty/.rustfmt.toml +0 -4
  373. package/ref-monty/.zed/settings.json +0 -11
  374. package/ref-monty/CLAUDE.md +0 -535
  375. package/ref-monty/Cargo.lock +0 -3798
  376. package/ref-monty/Cargo.toml +0 -87
  377. package/ref-monty/LICENSE +0 -21
  378. package/ref-monty/Makefile +0 -216
  379. package/ref-monty/README.md +0 -430
  380. package/ref-monty/RELEASING.md +0 -47
  381. package/ref-monty/crates/fuzz/Cargo.toml +0 -30
  382. package/ref-monty/crates/fuzz/fuzz_targets/string_input_panic.rs +0 -37
  383. package/ref-monty/crates/fuzz/fuzz_targets/tokens_input_panic.rs +0 -552
  384. package/ref-monty/crates/monty/Cargo.toml +0 -68
  385. package/ref-monty/crates/monty/benches/main.rs +0 -247
  386. package/ref-monty/crates/monty/build.rs +0 -10
  387. package/ref-monty/crates/monty/src/args.rs +0 -733
  388. package/ref-monty/crates/monty/src/asyncio.rs +0 -179
  389. package/ref-monty/crates/monty/src/builtins/abs.rs +0 -55
  390. package/ref-monty/crates/monty/src/builtins/all.rs +0 -30
  391. package/ref-monty/crates/monty/src/builtins/any.rs +0 -30
  392. package/ref-monty/crates/monty/src/builtins/bin.rs +0 -59
  393. package/ref-monty/crates/monty/src/builtins/chr.rs +0 -46
  394. package/ref-monty/crates/monty/src/builtins/divmod.rs +0 -164
  395. package/ref-monty/crates/monty/src/builtins/enumerate.rs +0 -52
  396. package/ref-monty/crates/monty/src/builtins/filter.rs +0 -67
  397. package/ref-monty/crates/monty/src/builtins/getattr.rs +0 -65
  398. package/ref-monty/crates/monty/src/builtins/hash.rs +0 -28
  399. package/ref-monty/crates/monty/src/builtins/hex.rs +0 -58
  400. package/ref-monty/crates/monty/src/builtins/id.rs +0 -24
  401. package/ref-monty/crates/monty/src/builtins/isinstance.rs +0 -68
  402. package/ref-monty/crates/monty/src/builtins/len.rs +0 -25
  403. package/ref-monty/crates/monty/src/builtins/map.rs +0 -98
  404. package/ref-monty/crates/monty/src/builtins/min_max.rs +0 -113
  405. package/ref-monty/crates/monty/src/builtins/mod.rs +0 -246
  406. package/ref-monty/crates/monty/src/builtins/next.rs +0 -21
  407. package/ref-monty/crates/monty/src/builtins/oct.rs +0 -59
  408. package/ref-monty/crates/monty/src/builtins/ord.rs +0 -67
  409. package/ref-monty/crates/monty/src/builtins/pow.rs +0 -365
  410. package/ref-monty/crates/monty/src/builtins/print.rs +0 -141
  411. package/ref-monty/crates/monty/src/builtins/repr.rs +0 -16
  412. package/ref-monty/crates/monty/src/builtins/reversed.rs +0 -28
  413. package/ref-monty/crates/monty/src/builtins/round.rs +0 -174
  414. package/ref-monty/crates/monty/src/builtins/sorted.rs +0 -151
  415. package/ref-monty/crates/monty/src/builtins/sum.rs +0 -66
  416. package/ref-monty/crates/monty/src/builtins/type_.rs +0 -16
  417. package/ref-monty/crates/monty/src/builtins/zip.rs +0 -77
  418. package/ref-monty/crates/monty/src/bytecode/builder.rs +0 -699
  419. package/ref-monty/crates/monty/src/bytecode/code.rs +0 -310
  420. package/ref-monty/crates/monty/src/bytecode/compiler.rs +0 -3206
  421. package/ref-monty/crates/monty/src/bytecode/mod.rs +0 -24
  422. package/ref-monty/crates/monty/src/bytecode/op.rs +0 -617
  423. package/ref-monty/crates/monty/src/bytecode/vm/async_exec.rs +0 -1058
  424. package/ref-monty/crates/monty/src/bytecode/vm/attr.rs +0 -63
  425. package/ref-monty/crates/monty/src/bytecode/vm/binary.rs +0 -487
  426. package/ref-monty/crates/monty/src/bytecode/vm/call.rs +0 -767
  427. package/ref-monty/crates/monty/src/bytecode/vm/collections.rs +0 -741
  428. package/ref-monty/crates/monty/src/bytecode/vm/compare.rs +0 -147
  429. package/ref-monty/crates/monty/src/bytecode/vm/exceptions.rs +0 -297
  430. package/ref-monty/crates/monty/src/bytecode/vm/format.rs +0 -132
  431. package/ref-monty/crates/monty/src/bytecode/vm/mod.rs +0 -1958
  432. package/ref-monty/crates/monty/src/bytecode/vm/scheduler.rs +0 -620
  433. package/ref-monty/crates/monty/src/exception_private.rs +0 -1513
  434. package/ref-monty/crates/monty/src/exception_public.rs +0 -346
  435. package/ref-monty/crates/monty/src/expressions.rs +0 -694
  436. package/ref-monty/crates/monty/src/fstring.rs +0 -854
  437. package/ref-monty/crates/monty/src/function.rs +0 -119
  438. package/ref-monty/crates/monty/src/heap.rs +0 -1073
  439. package/ref-monty/crates/monty/src/heap_data.rs +0 -985
  440. package/ref-monty/crates/monty/src/heap_traits.rs +0 -312
  441. package/ref-monty/crates/monty/src/intern.rs +0 -837
  442. package/ref-monty/crates/monty/src/io.rs +0 -106
  443. package/ref-monty/crates/monty/src/lib.rs +0 -52
  444. package/ref-monty/crates/monty/src/modules/asyncio.rs +0 -144
  445. package/ref-monty/crates/monty/src/modules/math.rs +0 -1453
  446. package/ref-monty/crates/monty/src/modules/mod.rs +0 -120
  447. package/ref-monty/crates/monty/src/modules/os.rs +0 -116
  448. package/ref-monty/crates/monty/src/modules/pathlib.rs +0 -33
  449. package/ref-monty/crates/monty/src/modules/re.rs +0 -606
  450. package/ref-monty/crates/monty/src/modules/sys.rs +0 -60
  451. package/ref-monty/crates/monty/src/modules/typing.rs +0 -70
  452. package/ref-monty/crates/monty/src/namespace.rs +0 -21
  453. package/ref-monty/crates/monty/src/object.rs +0 -1040
  454. package/ref-monty/crates/monty/src/os.rs +0 -215
  455. package/ref-monty/crates/monty/src/parse.rs +0 -1730
  456. package/ref-monty/crates/monty/src/prepare.rs +0 -3015
  457. package/ref-monty/crates/monty/src/repl.rs +0 -1109
  458. package/ref-monty/crates/monty/src/resource.rs +0 -559
  459. package/ref-monty/crates/monty/src/run.rs +0 -457
  460. package/ref-monty/crates/monty/src/run_progress.rs +0 -821
  461. package/ref-monty/crates/monty/src/signature.rs +0 -651
  462. package/ref-monty/crates/monty/src/sorting.rs +0 -100
  463. package/ref-monty/crates/monty/src/types/bytes.rs +0 -2356
  464. package/ref-monty/crates/monty/src/types/dataclass.rs +0 -345
  465. package/ref-monty/crates/monty/src/types/dict.rs +0 -879
  466. package/ref-monty/crates/monty/src/types/dict_view.rs +0 -619
  467. package/ref-monty/crates/monty/src/types/iter.rs +0 -799
  468. package/ref-monty/crates/monty/src/types/list.rs +0 -929
  469. package/ref-monty/crates/monty/src/types/long_int.rs +0 -211
  470. package/ref-monty/crates/monty/src/types/mod.rs +0 -48
  471. package/ref-monty/crates/monty/src/types/module.rs +0 -146
  472. package/ref-monty/crates/monty/src/types/namedtuple.rs +0 -261
  473. package/ref-monty/crates/monty/src/types/path.rs +0 -596
  474. package/ref-monty/crates/monty/src/types/property.rs +0 -35
  475. package/ref-monty/crates/monty/src/types/py_trait.rs +0 -322
  476. package/ref-monty/crates/monty/src/types/range.rs +0 -285
  477. package/ref-monty/crates/monty/src/types/re_match.rs +0 -522
  478. package/ref-monty/crates/monty/src/types/re_pattern.rs +0 -726
  479. package/ref-monty/crates/monty/src/types/set.rs +0 -1373
  480. package/ref-monty/crates/monty/src/types/slice.rs +0 -257
  481. package/ref-monty/crates/monty/src/types/str.rs +0 -2051
  482. package/ref-monty/crates/monty/src/types/tuple.rs +0 -376
  483. package/ref-monty/crates/monty/src/types/type.rs +0 -407
  484. package/ref-monty/crates/monty/src/value.rs +0 -2558
  485. package/ref-monty/crates/monty/test_cases/args__dict_get_no_args.py +0 -3
  486. package/ref-monty/crates/monty/test_cases/args__dict_get_too_many.py +0 -3
  487. package/ref-monty/crates/monty/test_cases/args__dict_items_with_args.py +0 -3
  488. package/ref-monty/crates/monty/test_cases/args__dict_keys_with_args.py +0 -3
  489. package/ref-monty/crates/monty/test_cases/args__dict_pop_no_args.py +0 -3
  490. package/ref-monty/crates/monty/test_cases/args__dict_pop_too_many.py +0 -3
  491. package/ref-monty/crates/monty/test_cases/args__dict_values_with_args.py +0 -3
  492. package/ref-monty/crates/monty/test_cases/args__id_too_many.py +0 -2
  493. package/ref-monty/crates/monty/test_cases/args__len_no_args.py +0 -2
  494. package/ref-monty/crates/monty/test_cases/args__len_too_many.py +0 -2
  495. package/ref-monty/crates/monty/test_cases/args__len_type_error_int.py +0 -9
  496. package/ref-monty/crates/monty/test_cases/args__len_type_error_none.py +0 -9
  497. package/ref-monty/crates/monty/test_cases/args__list_append_no_args.py +0 -3
  498. package/ref-monty/crates/monty/test_cases/args__list_append_too_many.py +0 -3
  499. package/ref-monty/crates/monty/test_cases/args__list_insert_too_few.py +0 -3
  500. package/ref-monty/crates/monty/test_cases/args__list_insert_too_many.py +0 -3
  501. package/ref-monty/crates/monty/test_cases/args__repr_no_args.py +0 -2
  502. package/ref-monty/crates/monty/test_cases/arith__div_zero_float.py +0 -2
  503. package/ref-monty/crates/monty/test_cases/arith__div_zero_int.py +0 -2
  504. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_float.py +0 -2
  505. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_int.py +0 -2
  506. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg.py +0 -2
  507. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg_builtin.py +0 -9
  508. package/ref-monty/crates/monty/test_cases/assert__expr_fail.py +0 -2
  509. package/ref-monty/crates/monty/test_cases/assert__fail.py +0 -2
  510. package/ref-monty/crates/monty/test_cases/assert__fail_msg.py +0 -2
  511. package/ref-monty/crates/monty/test_cases/assert__fn_fail.py +0 -3
  512. package/ref-monty/crates/monty/test_cases/assert__ops.py +0 -11
  513. package/ref-monty/crates/monty/test_cases/async__asyncio_run.py +0 -47
  514. package/ref-monty/crates/monty/test_cases/async__basic.py +0 -10
  515. package/ref-monty/crates/monty/test_cases/async__closure.py +0 -14
  516. package/ref-monty/crates/monty/test_cases/async__double_await_coroutine.py +0 -16
  517. package/ref-monty/crates/monty/test_cases/async__exception.py +0 -10
  518. package/ref-monty/crates/monty/test_cases/async__ext_call.py +0 -73
  519. package/ref-monty/crates/monty/test_cases/async__gather_all.py +0 -85
  520. package/ref-monty/crates/monty/test_cases/async__nested_await.py +0 -15
  521. package/ref-monty/crates/monty/test_cases/async__nested_gather_ext.py +0 -37
  522. package/ref-monty/crates/monty/test_cases/async__not_awaitable.py +0 -10
  523. package/ref-monty/crates/monty/test_cases/async__not_imported.py +0 -14
  524. package/ref-monty/crates/monty/test_cases/async__recursion_depth_isolation.py +0 -27
  525. package/ref-monty/crates/monty/test_cases/async__return_types.py +0 -31
  526. package/ref-monty/crates/monty/test_cases/async__sequential.py +0 -16
  527. package/ref-monty/crates/monty/test_cases/async__traceback.py +0 -19
  528. package/ref-monty/crates/monty/test_cases/async__with_args.py +0 -14
  529. package/ref-monty/crates/monty/test_cases/attr__get_int_error.py +0 -9
  530. package/ref-monty/crates/monty/test_cases/attr__get_list_error.py +0 -9
  531. package/ref-monty/crates/monty/test_cases/attr__set_frozen_nonfield.py +0 -12
  532. package/ref-monty/crates/monty/test_cases/attr__set_int_error.py +0 -10
  533. package/ref-monty/crates/monty/test_cases/attr__set_list_error.py +0 -10
  534. package/ref-monty/crates/monty/test_cases/bench__kitchen_sink.py +0 -68
  535. package/ref-monty/crates/monty/test_cases/bool__ops.py +0 -20
  536. package/ref-monty/crates/monty/test_cases/builtin__add_type_error.py +0 -2
  537. package/ref-monty/crates/monty/test_cases/builtin__filter.py +0 -62
  538. package/ref-monty/crates/monty/test_cases/builtin__filter_not_iterable.py +0 -11
  539. package/ref-monty/crates/monty/test_cases/builtin__getattr.py +0 -84
  540. package/ref-monty/crates/monty/test_cases/builtin__iter_funcs.py +0 -42
  541. package/ref-monty/crates/monty/test_cases/builtin__iter_next.py +0 -66
  542. package/ref-monty/crates/monty/test_cases/builtin__map.py +0 -74
  543. package/ref-monty/crates/monty/test_cases/builtin__map_not_iterable.py +0 -11
  544. package/ref-monty/crates/monty/test_cases/builtin__math_funcs.py +0 -154
  545. package/ref-monty/crates/monty/test_cases/builtin__more_iter_funcs.py +0 -148
  546. package/ref-monty/crates/monty/test_cases/builtin__next_stop_iteration.py +0 -10
  547. package/ref-monty/crates/monty/test_cases/builtin__print_invalid_kwarg.py +0 -9
  548. package/ref-monty/crates/monty/test_cases/builtin__print_kwargs.py +0 -12
  549. package/ref-monty/crates/monty/test_cases/builtin__repr.py +0 -3
  550. package/ref-monty/crates/monty/test_cases/builtin__string_funcs.py +0 -73
  551. package/ref-monty/crates/monty/test_cases/bytes__decode_invalid_utf8.py +0 -18
  552. package/ref-monty/crates/monty/test_cases/bytes__endswith_str_error.py +0 -10
  553. package/ref-monty/crates/monty/test_cases/bytes__getitem_index_error.py +0 -10
  554. package/ref-monty/crates/monty/test_cases/bytes__index_start_gt_end.py +0 -10
  555. package/ref-monty/crates/monty/test_cases/bytes__methods.py +0 -394
  556. package/ref-monty/crates/monty/test_cases/bytes__negative_count.py +0 -9
  557. package/ref-monty/crates/monty/test_cases/bytes__ops.py +0 -90
  558. package/ref-monty/crates/monty/test_cases/bytes__startswith_str_error.py +0 -10
  559. package/ref-monty/crates/monty/test_cases/call_object.py +0 -3
  560. package/ref-monty/crates/monty/test_cases/chain_comparison__all.py +0 -79
  561. package/ref-monty/crates/monty/test_cases/closure__param_shadows_outer.py +0 -81
  562. package/ref-monty/crates/monty/test_cases/closure__pep448.py +0 -203
  563. package/ref-monty/crates/monty/test_cases/closure__undefined_nonlocal.py +0 -13
  564. package/ref-monty/crates/monty/test_cases/compare__mixed_types.py +0 -120
  565. package/ref-monty/crates/monty/test_cases/comprehension__all.py +0 -208
  566. package/ref-monty/crates/monty/test_cases/comprehension__scope.py +0 -7
  567. package/ref-monty/crates/monty/test_cases/comprehension__unbound_local.py +0 -14
  568. package/ref-monty/crates/monty/test_cases/dataclass__basic.py +0 -238
  569. package/ref-monty/crates/monty/test_cases/dataclass__call_field_error.py +0 -12
  570. package/ref-monty/crates/monty/test_cases/dataclass__frozen_set_error.py +0 -12
  571. package/ref-monty/crates/monty/test_cases/dataclass__get_missing_attr_error.py +0 -11
  572. package/ref-monty/crates/monty/test_cases/dict__get_unhashable_key.py +0 -3
  573. package/ref-monty/crates/monty/test_cases/dict__literal_unhashable_key.py +0 -2
  574. package/ref-monty/crates/monty/test_cases/dict__method_pop_missing_error.py +0 -3
  575. package/ref-monty/crates/monty/test_cases/dict__methods.py +0 -151
  576. package/ref-monty/crates/monty/test_cases/dict__ops.py +0 -133
  577. package/ref-monty/crates/monty/test_cases/dict__pop_unhashable_key.py +0 -4
  578. package/ref-monty/crates/monty/test_cases/dict__popitem_empty.py +0 -9
  579. package/ref-monty/crates/monty/test_cases/dict__subscript_missing_key.py +0 -3
  580. package/ref-monty/crates/monty/test_cases/dict__unhashable_dict_key.py +0 -2
  581. package/ref-monty/crates/monty/test_cases/dict__unhashable_list_key.py +0 -2
  582. package/ref-monty/crates/monty/test_cases/dict__unpack_type_error.py +0 -2
  583. package/ref-monty/crates/monty/test_cases/dict__views.py +0 -165
  584. package/ref-monty/crates/monty/test_cases/edge__all.py +0 -26
  585. package/ref-monty/crates/monty/test_cases/edge__float_int_mod.py +0 -2
  586. package/ref-monty/crates/monty/test_cases/edge__int_float_mod.py +0 -2
  587. package/ref-monty/crates/monty/test_cases/exc__args.py +0 -16
  588. package/ref-monty/crates/monty/test_cases/exc__str.py +0 -15
  589. package/ref-monty/crates/monty/test_cases/execute_ok__all.py +0 -54
  590. package/ref-monty/crates/monty/test_cases/execute_raise__error_instance_str.py +0 -2
  591. package/ref-monty/crates/monty/test_cases/execute_raise__error_no_args.py +0 -2
  592. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg.py +0 -2
  593. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg_quotes.py +0 -2
  594. package/ref-monty/crates/monty/test_cases/execute_raise__error_type.py +0 -2
  595. package/ref-monty/crates/monty/test_cases/execute_raise__raise_instance_via_var.py +0 -4
  596. package/ref-monty/crates/monty/test_cases/execute_raise__raise_list.py +0 -2
  597. package/ref-monty/crates/monty/test_cases/execute_raise__raise_number.py +0 -2
  598. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_call_via_var.py +0 -4
  599. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_direct.py +0 -3
  600. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_via_var.py +0 -4
  601. package/ref-monty/crates/monty/test_cases/ext_call__arg_side_effect_bug.py +0 -22
  602. package/ref-monty/crates/monty/test_cases/ext_call__augmented.py +0 -17
  603. package/ref-monty/crates/monty/test_cases/ext_call__augmented_refcount_bug.py +0 -7
  604. package/ref-monty/crates/monty/test_cases/ext_call__bare_raise_after_resume.py +0 -34
  605. package/ref-monty/crates/monty/test_cases/ext_call__basic.py +0 -99
  606. package/ref-monty/crates/monty/test_cases/ext_call__boolean.py +0 -37
  607. package/ref-monty/crates/monty/test_cases/ext_call__boolean_side_effect_hang.py +0 -17
  608. package/ref-monty/crates/monty/test_cases/ext_call__closure_bug.py +0 -16
  609. package/ref-monty/crates/monty/test_cases/ext_call__comparison.py +0 -26
  610. package/ref-monty/crates/monty/test_cases/ext_call__deep_call_stack.py +0 -18
  611. package/ref-monty/crates/monty/test_cases/ext_call__elif.py +0 -171
  612. package/ref-monty/crates/monty/test_cases/ext_call__exc.py +0 -4
  613. package/ref-monty/crates/monty/test_cases/ext_call__exc_deep_stack.py +0 -39
  614. package/ref-monty/crates/monty/test_cases/ext_call__exc_in_function.py +0 -17
  615. package/ref-monty/crates/monty/test_cases/ext_call__exc_nested_functions.py +0 -31
  616. package/ref-monty/crates/monty/test_cases/ext_call__ext_exc.py +0 -171
  617. package/ref-monty/crates/monty/test_cases/ext_call__for.py +0 -114
  618. package/ref-monty/crates/monty/test_cases/ext_call__fstring.py +0 -12
  619. package/ref-monty/crates/monty/test_cases/ext_call__if.py +0 -135
  620. package/ref-monty/crates/monty/test_cases/ext_call__if_condition.py +0 -37
  621. package/ref-monty/crates/monty/test_cases/ext_call__in_closure.py +0 -14
  622. package/ref-monty/crates/monty/test_cases/ext_call__in_function.py +0 -40
  623. package/ref-monty/crates/monty/test_cases/ext_call__in_function_simple.py +0 -7
  624. package/ref-monty/crates/monty/test_cases/ext_call__literals.py +0 -17
  625. package/ref-monty/crates/monty/test_cases/ext_call__multi_in_func.py +0 -32
  626. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup.py +0 -69
  627. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup_undefined.py +0 -4
  628. package/ref-monty/crates/monty/test_cases/ext_call__nested_calls.py +0 -14
  629. package/ref-monty/crates/monty/test_cases/ext_call__recursion_bug.py +0 -19
  630. package/ref-monty/crates/monty/test_cases/ext_call__return.py +0 -28
  631. package/ref-monty/crates/monty/test_cases/ext_call__side_effects.py +0 -25
  632. package/ref-monty/crates/monty/test_cases/ext_call__subscript.py +0 -7
  633. package/ref-monty/crates/monty/test_cases/ext_call__ternary.py +0 -28
  634. package/ref-monty/crates/monty/test_cases/ext_call__try.py +0 -280
  635. package/ref-monty/crates/monty/test_cases/ext_call__try_simple.py +0 -10
  636. package/ref-monty/crates/monty/test_cases/ext_call__unary.py +0 -13
  637. package/ref-monty/crates/monty/test_cases/frozenset__ops.py +0 -178
  638. package/ref-monty/crates/monty/test_cases/fstring__all.py +0 -236
  639. package/ref-monty/crates/monty/test_cases/fstring__error_eq_align_on_str.py +0 -3
  640. package/ref-monty/crates/monty/test_cases/fstring__error_float_f_on_str.py +0 -3
  641. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_float.py +0 -3
  642. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_str.py +0 -3
  643. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec.py +0 -4
  644. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_dynamic.py +0 -4
  645. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_str.py +0 -4
  646. package/ref-monty/crates/monty/test_cases/fstring__error_str_s_on_int.py +0 -3
  647. package/ref-monty/crates/monty/test_cases/function__call_duplicate_kwargs.py +0 -6
  648. package/ref-monty/crates/monty/test_cases/function__call_unpack.py +0 -42
  649. package/ref-monty/crates/monty/test_cases/function__defaults.py +0 -117
  650. package/ref-monty/crates/monty/test_cases/function__err_duplicate_arg.py +0 -7
  651. package/ref-monty/crates/monty/test_cases/function__err_duplicate_first_arg.py +0 -7
  652. package/ref-monty/crates/monty/test_cases/function__err_duplicate_kwarg_cleanup.py +0 -9
  653. package/ref-monty/crates/monty/test_cases/function__err_kwonly_as_positional.py +0 -7
  654. package/ref-monty/crates/monty/test_cases/function__err_missing_all_posonly.py +0 -7
  655. package/ref-monty/crates/monty/test_cases/function__err_missing_heap_cleanup.py +0 -9
  656. package/ref-monty/crates/monty/test_cases/function__err_missing_kwonly.py +0 -7
  657. package/ref-monty/crates/monty/test_cases/function__err_missing_posonly_with_kwarg.py +0 -7
  658. package/ref-monty/crates/monty/test_cases/function__err_missing_with_posonly.py +0 -7
  659. package/ref-monty/crates/monty/test_cases/function__err_posonly_as_kwarg.py +0 -7
  660. package/ref-monty/crates/monty/test_cases/function__err_posonly_first_as_kwarg.py +0 -7
  661. package/ref-monty/crates/monty/test_cases/function__err_too_many_posonly.py +0 -7
  662. package/ref-monty/crates/monty/test_cases/function__err_too_many_with_kwonly.py +0 -7
  663. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg.py +0 -7
  664. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_cleanup.py +0 -9
  665. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_quote.py +0 -13
  666. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_simple.py +0 -7
  667. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_arg.py +0 -6
  668. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_heap.py +0 -8
  669. package/ref-monty/crates/monty/test_cases/function__err_unpack_int.py +0 -6
  670. package/ref-monty/crates/monty/test_cases/function__err_unpack_nonstring_key.py +0 -6
  671. package/ref-monty/crates/monty/test_cases/function__err_unpack_not_mapping.py +0 -6
  672. package/ref-monty/crates/monty/test_cases/function__kwargs_unpacking.py +0 -173
  673. package/ref-monty/crates/monty/test_cases/function__ops.py +0 -294
  674. package/ref-monty/crates/monty/test_cases/function__return_none.py +0 -42
  675. package/ref-monty/crates/monty/test_cases/function__signatures.py +0 -47
  676. package/ref-monty/crates/monty/test_cases/function__too_few_args_all.py +0 -6
  677. package/ref-monty/crates/monty/test_cases/function__too_few_args_one.py +0 -6
  678. package/ref-monty/crates/monty/test_cases/function__too_few_args_two.py +0 -6
  679. package/ref-monty/crates/monty/test_cases/function__too_many_args_one.py +0 -6
  680. package/ref-monty/crates/monty/test_cases/function__too_many_args_two.py +0 -6
  681. package/ref-monty/crates/monty/test_cases/function__too_many_args_zero.py +0 -6
  682. package/ref-monty/crates/monty/test_cases/global__error_assigned_before.py +0 -7
  683. package/ref-monty/crates/monty/test_cases/global__ops.py +0 -163
  684. package/ref-monty/crates/monty/test_cases/hash__dict_unhashable.py +0 -2
  685. package/ref-monty/crates/monty/test_cases/hash__list_unhashable.py +0 -2
  686. package/ref-monty/crates/monty/test_cases/hash__ops.py +0 -153
  687. package/ref-monty/crates/monty/test_cases/id__bytes_literals_distinct.py +0 -3
  688. package/ref-monty/crates/monty/test_cases/id__int_copy_distinct.py +0 -5
  689. package/ref-monty/crates/monty/test_cases/id__is_number_is_number.py +0 -3
  690. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_distinct_types.py +0 -10
  691. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_same_types.py +0 -6
  692. package/ref-monty/crates/monty/test_cases/id__ops.py +0 -97
  693. package/ref-monty/crates/monty/test_cases/id__str_literals_same.py +0 -3
  694. package/ref-monty/crates/monty/test_cases/if__elif_else.py +0 -207
  695. package/ref-monty/crates/monty/test_cases/if__raise_elif.py +0 -11
  696. package/ref-monty/crates/monty/test_cases/if__raise_else.py +0 -13
  697. package/ref-monty/crates/monty/test_cases/if__raise_if.py +0 -9
  698. package/ref-monty/crates/monty/test_cases/if__raise_in_elif_condition.py +0 -18
  699. package/ref-monty/crates/monty/test_cases/if__raise_in_if_condition.py +0 -16
  700. package/ref-monty/crates/monty/test_cases/if_else_expr__all.py +0 -55
  701. package/ref-monty/crates/monty/test_cases/import__error_cannot_import.py +0 -9
  702. package/ref-monty/crates/monty/test_cases/import__error_module_not_found.py +0 -9
  703. package/ref-monty/crates/monty/test_cases/import__local_scope.py +0 -68
  704. package/ref-monty/crates/monty/test_cases/import__os.py +0 -25
  705. package/ref-monty/crates/monty/test_cases/import__relative_error.py +0 -9
  706. package/ref-monty/crates/monty/test_cases/import__relative_no_module_error.py +0 -9
  707. package/ref-monty/crates/monty/test_cases/import__runtime_error_when_executed.py +0 -14
  708. package/ref-monty/crates/monty/test_cases/import__star_error.py +0 -11
  709. package/ref-monty/crates/monty/test_cases/import__sys.py +0 -47
  710. package/ref-monty/crates/monty/test_cases/import__sys_monty.py +0 -28
  711. package/ref-monty/crates/monty/test_cases/import__type_checking_guard.py +0 -37
  712. package/ref-monty/crates/monty/test_cases/import__typing.py +0 -25
  713. package/ref-monty/crates/monty/test_cases/import__typing_type_ignore.py +0 -4
  714. package/ref-monty/crates/monty/test_cases/int__bigint.py +0 -467
  715. package/ref-monty/crates/monty/test_cases/int__bigint_errors.py +0 -260
  716. package/ref-monty/crates/monty/test_cases/int__ops.py +0 -219
  717. package/ref-monty/crates/monty/test_cases/int__overflow_division.py +0 -84
  718. package/ref-monty/crates/monty/test_cases/is_variant__all.py +0 -36
  719. package/ref-monty/crates/monty/test_cases/isinstance__arg2_list_error.py +0 -2
  720. package/ref-monty/crates/monty/test_cases/isinstance__arg2_type_error.py +0 -2
  721. package/ref-monty/crates/monty/test_cases/iter__dict_mutation.py +0 -4
  722. package/ref-monty/crates/monty/test_cases/iter__for.py +0 -243
  723. package/ref-monty/crates/monty/test_cases/iter__for_loop_unpacking.py +0 -66
  724. package/ref-monty/crates/monty/test_cases/iter__generator_expr.py +0 -20
  725. package/ref-monty/crates/monty/test_cases/iter__generator_expr_type.py +0 -7
  726. package/ref-monty/crates/monty/test_cases/iter__not_iterable.py +0 -3
  727. package/ref-monty/crates/monty/test_cases/lambda__all.py +0 -145
  728. package/ref-monty/crates/monty/test_cases/list__extend_not_iterable.py +0 -7
  729. package/ref-monty/crates/monty/test_cases/list__getitem_out_of_bounds.py +0 -3
  730. package/ref-monty/crates/monty/test_cases/list__index_not_found.py +0 -9
  731. package/ref-monty/crates/monty/test_cases/list__index_start_gt_end.py +0 -10
  732. package/ref-monty/crates/monty/test_cases/list__ops.py +0 -473
  733. package/ref-monty/crates/monty/test_cases/list__pop_empty.py +0 -9
  734. package/ref-monty/crates/monty/test_cases/list__pop_out_of_range.py +0 -9
  735. package/ref-monty/crates/monty/test_cases/list__pop_type_error.py +0 -9
  736. package/ref-monty/crates/monty/test_cases/list__remove_not_found.py +0 -9
  737. package/ref-monty/crates/monty/test_cases/list__setitem_dict_index.py +0 -13
  738. package/ref-monty/crates/monty/test_cases/list__setitem_huge_int_index.py +0 -13
  739. package/ref-monty/crates/monty/test_cases/list__setitem_index_error.py +0 -10
  740. package/ref-monty/crates/monty/test_cases/list__setitem_type_error.py +0 -10
  741. package/ref-monty/crates/monty/test_cases/list__unpack_type_error.py +0 -2
  742. package/ref-monty/crates/monty/test_cases/longint__index_error.py +0 -3
  743. package/ref-monty/crates/monty/test_cases/longint__repeat_error.py +0 -3
  744. package/ref-monty/crates/monty/test_cases/loop__break_continue.py +0 -113
  745. package/ref-monty/crates/monty/test_cases/loop__break_finally.py +0 -69
  746. package/ref-monty/crates/monty/test_cases/loop__break_in_function_error.py +0 -13
  747. package/ref-monty/crates/monty/test_cases/loop__break_in_if_error.py +0 -11
  748. package/ref-monty/crates/monty/test_cases/loop__break_nested_except_clears.py +0 -55
  749. package/ref-monty/crates/monty/test_cases/loop__break_outside_error.py +0 -9
  750. package/ref-monty/crates/monty/test_cases/loop__continue_finally.py +0 -81
  751. package/ref-monty/crates/monty/test_cases/loop__continue_in_function_error.py +0 -13
  752. package/ref-monty/crates/monty/test_cases/loop__continue_in_if_error.py +0 -11
  753. package/ref-monty/crates/monty/test_cases/loop__continue_nested_except_clears.py +0 -60
  754. package/ref-monty/crates/monty/test_cases/loop__continue_outside_error.py +0 -9
  755. package/ref-monty/crates/monty/test_cases/math__acos_domain_error.py +0 -11
  756. package/ref-monty/crates/monty/test_cases/math__acosh_domain_error.py +0 -11
  757. package/ref-monty/crates/monty/test_cases/math__asin_domain_error.py +0 -11
  758. package/ref-monty/crates/monty/test_cases/math__atanh_domain_error.py +0 -11
  759. package/ref-monty/crates/monty/test_cases/math__cos_inf_error.py +0 -11
  760. package/ref-monty/crates/monty/test_cases/math__cosh_overflow_error.py +0 -11
  761. package/ref-monty/crates/monty/test_cases/math__exp_overflow_error.py +0 -11
  762. package/ref-monty/crates/monty/test_cases/math__factorial_float_error.py +0 -11
  763. package/ref-monty/crates/monty/test_cases/math__factorial_negative_error.py +0 -11
  764. package/ref-monty/crates/monty/test_cases/math__floor_inf_error.py +0 -11
  765. package/ref-monty/crates/monty/test_cases/math__floor_nan_error.py +0 -11
  766. package/ref-monty/crates/monty/test_cases/math__floor_str_error.py +0 -11
  767. package/ref-monty/crates/monty/test_cases/math__fmod_inf_error.py +0 -11
  768. package/ref-monty/crates/monty/test_cases/math__gamma_neg_int_error.py +0 -11
  769. package/ref-monty/crates/monty/test_cases/math__gcd_float_error.py +0 -11
  770. package/ref-monty/crates/monty/test_cases/math__isqrt_negative_error.py +0 -11
  771. package/ref-monty/crates/monty/test_cases/math__ldexp_overflow_error.py +0 -11
  772. package/ref-monty/crates/monty/test_cases/math__log1p_domain_error.py +0 -11
  773. package/ref-monty/crates/monty/test_cases/math__log_base1_error.py +0 -11
  774. package/ref-monty/crates/monty/test_cases/math__log_zero_error.py +0 -11
  775. package/ref-monty/crates/monty/test_cases/math__module.py +0 -1432
  776. package/ref-monty/crates/monty/test_cases/math__pow_domain_error.py +0 -11
  777. package/ref-monty/crates/monty/test_cases/math__sin_inf_error.py +0 -11
  778. package/ref-monty/crates/monty/test_cases/math__sqrt_negative_error.py +0 -11
  779. package/ref-monty/crates/monty/test_cases/math__tan_inf_error.py +0 -11
  780. package/ref-monty/crates/monty/test_cases/math__trunc_str_error.py +0 -11
  781. package/ref-monty/crates/monty/test_cases/method__args_kwargs_unpacking.py +0 -259
  782. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_func.py +0 -19
  783. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_module.py +0 -12
  784. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_chained.py +0 -9
  785. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_expr.py +0 -9
  786. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_function.py +0 -16
  787. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_with_args.py +0 -9
  788. package/ref-monty/crates/monty/test_cases/name_error__undefined_global.py +0 -10
  789. package/ref-monty/crates/monty/test_cases/namedtuple__missing_attr.py +0 -11
  790. package/ref-monty/crates/monty/test_cases/namedtuple__ops.py +0 -34
  791. package/ref-monty/crates/monty/test_cases/nonlocal__error_module_level.py +0 -3
  792. package/ref-monty/crates/monty/test_cases/nonlocal__ops.py +0 -353
  793. package/ref-monty/crates/monty/test_cases/os__environ.py +0 -40
  794. package/ref-monty/crates/monty/test_cases/os__getenv_key_list_error.py +0 -5
  795. package/ref-monty/crates/monty/test_cases/os__getenv_key_type_error.py +0 -5
  796. package/ref-monty/crates/monty/test_cases/parse_error__complex.py +0 -3
  797. package/ref-monty/crates/monty/test_cases/pathlib__import.py +0 -11
  798. package/ref-monty/crates/monty/test_cases/pathlib__os.py +0 -136
  799. package/ref-monty/crates/monty/test_cases/pathlib__os_read_error.py +0 -12
  800. package/ref-monty/crates/monty/test_cases/pathlib__pure.py +0 -81
  801. package/ref-monty/crates/monty/test_cases/pyobject__cycle_dict_self.py +0 -5
  802. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_dict.py +0 -6
  803. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_self.py +0 -5
  804. package/ref-monty/crates/monty/test_cases/pyobject__cycle_multiple_refs.py +0 -6
  805. package/ref-monty/crates/monty/test_cases/range__error_no_args.py +0 -2
  806. package/ref-monty/crates/monty/test_cases/range__error_step_zero.py +0 -2
  807. package/ref-monty/crates/monty/test_cases/range__error_too_many_args.py +0 -2
  808. package/ref-monty/crates/monty/test_cases/range__getitem_index_error.py +0 -10
  809. package/ref-monty/crates/monty/test_cases/range__ops.py +0 -236
  810. package/ref-monty/crates/monty/test_cases/re__basic.py +0 -756
  811. package/ref-monty/crates/monty/test_cases/re__grouping.py +0 -241
  812. package/ref-monty/crates/monty/test_cases/re__match.py +0 -148
  813. package/ref-monty/crates/monty/test_cases/recursion__deep_drop.py +0 -26
  814. package/ref-monty/crates/monty/test_cases/recursion__deep_eq.py +0 -23
  815. package/ref-monty/crates/monty/test_cases/recursion__deep_hash.py +0 -46
  816. package/ref-monty/crates/monty/test_cases/recursion__deep_repr.py +0 -12
  817. package/ref-monty/crates/monty/test_cases/recursion__function_depth.py +0 -13
  818. package/ref-monty/crates/monty/test_cases/refcount__cycle_mutual_reference.py +0 -18
  819. package/ref-monty/crates/monty/test_cases/refcount__cycle_self_reference.py +0 -12
  820. package/ref-monty/crates/monty/test_cases/refcount__dict_basic.py +0 -5
  821. package/ref-monty/crates/monty/test_cases/refcount__dict_get.py +0 -5
  822. package/ref-monty/crates/monty/test_cases/refcount__dict_keys_and.py +0 -14
  823. package/ref-monty/crates/monty/test_cases/refcount__dict_overwrite.py +0 -6
  824. package/ref-monty/crates/monty/test_cases/refcount__gather_cleanup.py +0 -16
  825. package/ref-monty/crates/monty/test_cases/refcount__gather_exception.py +0 -18
  826. package/ref-monty/crates/monty/test_cases/refcount__gather_nested_cancel.py +0 -25
  827. package/ref-monty/crates/monty/test_cases/refcount__immediate_skipped.py +0 -4
  828. package/ref-monty/crates/monty/test_cases/refcount__kwargs_unpacking.py +0 -27
  829. package/ref-monty/crates/monty/test_cases/refcount__list_append_multiple.py +0 -6
  830. package/ref-monty/crates/monty/test_cases/refcount__list_append_ref.py +0 -5
  831. package/ref-monty/crates/monty/test_cases/refcount__list_concat.py +0 -5
  832. package/ref-monty/crates/monty/test_cases/refcount__list_getitem.py +0 -5
  833. package/ref-monty/crates/monty/test_cases/refcount__list_iadd.py +0 -5
  834. package/ref-monty/crates/monty/test_cases/refcount__nested_list.py +0 -4
  835. package/ref-monty/crates/monty/test_cases/refcount__re_pattern_sub_error_paths.py +0 -37
  836. package/ref-monty/crates/monty/test_cases/refcount__re_search_match.py +0 -34
  837. package/ref-monty/crates/monty/test_cases/refcount__re_sub_error_paths.py +0 -31
  838. package/ref-monty/crates/monty/test_cases/refcount__shared_reference.py +0 -4
  839. package/ref-monty/crates/monty/test_cases/refcount__single_list.py +0 -3
  840. package/ref-monty/crates/monty/test_cases/repr__cycle_detection.py +0 -24
  841. package/ref-monty/crates/monty/test_cases/set__ops.py +0 -191
  842. package/ref-monty/crates/monty/test_cases/set__review_bugs.py +0 -35
  843. package/ref-monty/crates/monty/test_cases/set__unpack_type_error.py +0 -2
  844. package/ref-monty/crates/monty/test_cases/slice__invalid_indices.py +0 -2
  845. package/ref-monty/crates/monty/test_cases/slice__kwargs.py +0 -9
  846. package/ref-monty/crates/monty/test_cases/slice__no_args.py +0 -9
  847. package/ref-monty/crates/monty/test_cases/slice__ops.py +0 -149
  848. package/ref-monty/crates/monty/test_cases/slice__step_zero.py +0 -9
  849. package/ref-monty/crates/monty/test_cases/slice__step_zero_bytes.py +0 -9
  850. package/ref-monty/crates/monty/test_cases/slice__step_zero_range.py +0 -9
  851. package/ref-monty/crates/monty/test_cases/slice__step_zero_str.py +0 -9
  852. package/ref-monty/crates/monty/test_cases/slice__step_zero_tuple.py +0 -9
  853. package/ref-monty/crates/monty/test_cases/slice__too_many_args.py +0 -9
  854. package/ref-monty/crates/monty/test_cases/str__getitem_index_error.py +0 -10
  855. package/ref-monty/crates/monty/test_cases/str__index_not_found.py +0 -9
  856. package/ref-monty/crates/monty/test_cases/str__join_no_args.py +0 -9
  857. package/ref-monty/crates/monty/test_cases/str__join_non_string.py +0 -9
  858. package/ref-monty/crates/monty/test_cases/str__join_not_iterable.py +0 -9
  859. package/ref-monty/crates/monty/test_cases/str__join_too_many_args.py +0 -9
  860. package/ref-monty/crates/monty/test_cases/str__methods.py +0 -327
  861. package/ref-monty/crates/monty/test_cases/str__ops.py +0 -162
  862. package/ref-monty/crates/monty/test_cases/str__partition_empty.py +0 -9
  863. package/ref-monty/crates/monty/test_cases/str__rsplit_empty_sep.py +0 -9
  864. package/ref-monty/crates/monty/test_cases/str__split_empty_sep.py +0 -9
  865. package/ref-monty/crates/monty/test_cases/sys__types.py +0 -7
  866. package/ref-monty/crates/monty/test_cases/traceback__division_error.py +0 -30
  867. package/ref-monty/crates/monty/test_cases/traceback__index_error.py +0 -17
  868. package/ref-monty/crates/monty/test_cases/traceback__insert_as_int.py +0 -10
  869. package/ref-monty/crates/monty/test_cases/traceback__nested_call.py +0 -29
  870. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_module_scope.py +0 -10
  871. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_unbound.py +0 -24
  872. package/ref-monty/crates/monty/test_cases/traceback__range_as_int.py +0 -9
  873. package/ref-monty/crates/monty/test_cases/traceback__recursion_error.py +0 -23
  874. package/ref-monty/crates/monty/test_cases/traceback__set_mutation.py +0 -11
  875. package/ref-monty/crates/monty/test_cases/traceback__undefined_attr_call.py +0 -16
  876. package/ref-monty/crates/monty/test_cases/traceback__undefined_call.py +0 -16
  877. package/ref-monty/crates/monty/test_cases/traceback__undefined_raise.py +0 -16
  878. package/ref-monty/crates/monty/test_cases/try_except__all.py +0 -472
  879. package/ref-monty/crates/monty/test_cases/try_except__bare_raise_no_context.py +0 -2
  880. package/ref-monty/crates/monty/test_cases/try_except__invalid_type.py +0 -5
  881. package/ref-monty/crates/monty/test_cases/tuple__getitem_out_of_bounds.py +0 -3
  882. package/ref-monty/crates/monty/test_cases/tuple__index_not_found.py +0 -9
  883. package/ref-monty/crates/monty/test_cases/tuple__index_start_gt_end.py +0 -10
  884. package/ref-monty/crates/monty/test_cases/tuple__methods.py +0 -19
  885. package/ref-monty/crates/monty/test_cases/tuple__ops.py +0 -133
  886. package/ref-monty/crates/monty/test_cases/tuple__unpack_type_error.py +0 -2
  887. package/ref-monty/crates/monty/test_cases/type__builtin_attr_error.py +0 -9
  888. package/ref-monty/crates/monty/test_cases/type__bytes_negative.py +0 -2
  889. package/ref-monty/crates/monty/test_cases/type__cell_not_builtin.py +0 -9
  890. package/ref-monty/crates/monty/test_cases/type__exception_attr_error.py +0 -11
  891. package/ref-monty/crates/monty/test_cases/type__float_conversion_error.py +0 -2
  892. package/ref-monty/crates/monty/test_cases/type__float_repr_both_quotes.py +0 -9
  893. package/ref-monty/crates/monty/test_cases/type__float_repr_newline.py +0 -9
  894. package/ref-monty/crates/monty/test_cases/type__float_repr_single_quote.py +0 -9
  895. package/ref-monty/crates/monty/test_cases/type__int_conversion_error.py +0 -2
  896. package/ref-monty/crates/monty/test_cases/type__list_not_iterable.py +0 -2
  897. package/ref-monty/crates/monty/test_cases/type__non_builtin_name_error.py +0 -9
  898. package/ref-monty/crates/monty/test_cases/type__ops.py +0 -200
  899. package/ref-monty/crates/monty/test_cases/type__shadow_exc.py +0 -3
  900. package/ref-monty/crates/monty/test_cases/type__shadow_int.py +0 -9
  901. package/ref-monty/crates/monty/test_cases/type__shadow_len.py +0 -3
  902. package/ref-monty/crates/monty/test_cases/type__tuple_not_iterable.py +0 -2
  903. package/ref-monty/crates/monty/test_cases/type_error__int_add_list.py +0 -2
  904. package/ref-monty/crates/monty/test_cases/type_error__int_div_str.py +0 -2
  905. package/ref-monty/crates/monty/test_cases/type_error__int_floordiv_str.py +0 -2
  906. package/ref-monty/crates/monty/test_cases/type_error__int_iadd_str.py +0 -3
  907. package/ref-monty/crates/monty/test_cases/type_error__int_mod_str.py +0 -2
  908. package/ref-monty/crates/monty/test_cases/type_error__int_pow_str.py +0 -2
  909. package/ref-monty/crates/monty/test_cases/type_error__int_sub_str.py +0 -2
  910. package/ref-monty/crates/monty/test_cases/type_error__list_add_int.py +0 -2
  911. package/ref-monty/crates/monty/test_cases/type_error__list_add_str.py +0 -2
  912. package/ref-monty/crates/monty/test_cases/type_error__list_iadd_int.py +0 -6
  913. package/ref-monty/crates/monty/test_cases/type_error__str_add_int.py +0 -2
  914. package/ref-monty/crates/monty/test_cases/type_error__str_iadd_int.py +0 -3
  915. package/ref-monty/crates/monty/test_cases/type_error__unary_invert_str.py +0 -3
  916. package/ref-monty/crates/monty/test_cases/type_error__unary_minus_str.py +0 -4
  917. package/ref-monty/crates/monty/test_cases/type_error__unary_neg_str.py +0 -3
  918. package/ref-monty/crates/monty/test_cases/type_error__unary_plus_str.py +0 -4
  919. package/ref-monty/crates/monty/test_cases/typing__types.py +0 -24
  920. package/ref-monty/crates/monty/test_cases/unpack__nested.py +0 -48
  921. package/ref-monty/crates/monty/test_cases/unpack__non_sequence.py +0 -9
  922. package/ref-monty/crates/monty/test_cases/unpack__not_enough.py +0 -9
  923. package/ref-monty/crates/monty/test_cases/unpack__ops.py +0 -153
  924. package/ref-monty/crates/monty/test_cases/unpack__star_not_enough.py +0 -9
  925. package/ref-monty/crates/monty/test_cases/unpack__too_many.py +0 -9
  926. package/ref-monty/crates/monty/test_cases/version__cpython.py +0 -4
  927. package/ref-monty/crates/monty/test_cases/walrus__all.py +0 -178
  928. package/ref-monty/crates/monty/test_cases/while__all.py +0 -206
  929. package/ref-monty/crates/monty/tests/asyncio.rs +0 -764
  930. package/ref-monty/crates/monty/tests/binary_serde.rs +0 -185
  931. package/ref-monty/crates/monty/tests/bytecode_limits.rs +0 -248
  932. package/ref-monty/crates/monty/tests/datatest_runner.rs +0 -2029
  933. package/ref-monty/crates/monty/tests/inputs.rs +0 -420
  934. package/ref-monty/crates/monty/tests/json_serde.rs +0 -250
  935. package/ref-monty/crates/monty/tests/main.rs +0 -71
  936. package/ref-monty/crates/monty/tests/math_module.rs +0 -114
  937. package/ref-monty/crates/monty/tests/name_lookup.rs +0 -482
  938. package/ref-monty/crates/monty/tests/os_tests.rs +0 -459
  939. package/ref-monty/crates/monty/tests/parse_errors.rs +0 -441
  940. package/ref-monty/crates/monty/tests/print_writer.rs +0 -238
  941. package/ref-monty/crates/monty/tests/py_object.rs +0 -121
  942. package/ref-monty/crates/monty/tests/regex.rs +0 -90
  943. package/ref-monty/crates/monty/tests/repl.rs +0 -344
  944. package/ref-monty/crates/monty/tests/resource_limits.rs +0 -1826
  945. package/ref-monty/crates/monty/tests/try_from.rs +0 -167
  946. package/ref-monty/crates/monty-cli/Cargo.toml +0 -25
  947. package/ref-monty/crates/monty-cli/src/main.rs +0 -541
  948. package/ref-monty/crates/monty-js/.cargo/config.toml +0 -2
  949. package/ref-monty/crates/monty-js/.prettierignore +0 -8
  950. package/ref-monty/crates/monty-js/Cargo.toml +0 -32
  951. package/ref-monty/crates/monty-js/README.md +0 -207
  952. package/ref-monty/crates/monty-js/__test__/async.spec.ts +0 -350
  953. package/ref-monty/crates/monty-js/__test__/basic.spec.ts +0 -114
  954. package/ref-monty/crates/monty-js/__test__/exceptions.spec.ts +0 -427
  955. package/ref-monty/crates/monty-js/__test__/external.spec.ts +0 -354
  956. package/ref-monty/crates/monty-js/__test__/inputs.spec.ts +0 -143
  957. package/ref-monty/crates/monty-js/__test__/limits.spec.ts +0 -162
  958. package/ref-monty/crates/monty-js/__test__/package.json +0 -3
  959. package/ref-monty/crates/monty-js/__test__/print.spec.ts +0 -229
  960. package/ref-monty/crates/monty-js/__test__/repl.spec.ts +0 -34
  961. package/ref-monty/crates/monty-js/__test__/serialize.spec.ts +0 -205
  962. package/ref-monty/crates/monty-js/__test__/start.spec.ts +0 -443
  963. package/ref-monty/crates/monty-js/__test__/type_check.spec.ts +0 -147
  964. package/ref-monty/crates/monty-js/__test__/types.spec.ts +0 -319
  965. package/ref-monty/crates/monty-js/build.rs +0 -61
  966. package/ref-monty/crates/monty-js/index-header.d.ts +0 -3
  967. package/ref-monty/crates/monty-js/package-lock.json +0 -4694
  968. package/ref-monty/crates/monty-js/package.json +0 -100
  969. package/ref-monty/crates/monty-js/scripts/smoke-test.sh +0 -69
  970. package/ref-monty/crates/monty-js/smoke-test/package.json +0 -17
  971. package/ref-monty/crates/monty-js/smoke-test/test.ts +0 -171
  972. package/ref-monty/crates/monty-js/smoke-test/tsconfig.json +0 -11
  973. package/ref-monty/crates/monty-js/src/convert.rs +0 -648
  974. package/ref-monty/crates/monty-js/src/exceptions.rs +0 -293
  975. package/ref-monty/crates/monty-js/src/lib.rs +0 -41
  976. package/ref-monty/crates/monty-js/src/limits.rs +0 -53
  977. package/ref-monty/crates/monty-js/src/monty_cls.rs +0 -1407
  978. package/ref-monty/crates/monty-js/tsconfig.json +0 -17
  979. package/ref-monty/crates/monty-js/wrapper.ts +0 -701
  980. package/ref-monty/crates/monty-python/Cargo.toml +0 -38
  981. package/ref-monty/crates/monty-python/README.md +0 -134
  982. package/ref-monty/crates/monty-python/build.rs +0 -4
  983. package/ref-monty/crates/monty-python/example.py +0 -40
  984. package/ref-monty/crates/monty-python/exercise.py +0 -46
  985. package/ref-monty/crates/monty-python/pyproject.toml +0 -57
  986. package/ref-monty/crates/monty-python/python/pydantic_monty/__init__.py +0 -281
  987. package/ref-monty/crates/monty-python/python/pydantic_monty/_monty.pyi +0 -677
  988. package/ref-monty/crates/monty-python/python/pydantic_monty/os_access.py +0 -933
  989. package/ref-monty/crates/monty-python/python/pydantic_monty/py.typed +0 -0
  990. package/ref-monty/crates/monty-python/src/convert.rs +0 -273
  991. package/ref-monty/crates/monty-python/src/dataclass.rs +0 -461
  992. package/ref-monty/crates/monty-python/src/exceptions.rs +0 -557
  993. package/ref-monty/crates/monty-python/src/external.rs +0 -165
  994. package/ref-monty/crates/monty-python/src/lib.rs +0 -77
  995. package/ref-monty/crates/monty-python/src/limits.rs +0 -142
  996. package/ref-monty/crates/monty-python/src/monty_cls.rs +0 -1650
  997. package/ref-monty/crates/monty-python/src/repl.rs +0 -470
  998. package/ref-monty/crates/monty-python/src/serialization.rs +0 -761
  999. package/ref-monty/crates/monty-python/tests/test_async.py +0 -1201
  1000. package/ref-monty/crates/monty-python/tests/test_basic.py +0 -66
  1001. package/ref-monty/crates/monty-python/tests/test_dataclasses.py +0 -971
  1002. package/ref-monty/crates/monty-python/tests/test_exceptions.py +0 -361
  1003. package/ref-monty/crates/monty-python/tests/test_external.py +0 -367
  1004. package/ref-monty/crates/monty-python/tests/test_inputs.py +0 -126
  1005. package/ref-monty/crates/monty-python/tests/test_limits.py +0 -257
  1006. package/ref-monty/crates/monty-python/tests/test_os_access.py +0 -1286
  1007. package/ref-monty/crates/monty-python/tests/test_os_access_compat.py +0 -731
  1008. package/ref-monty/crates/monty-python/tests/test_os_access_raw.py +0 -483
  1009. package/ref-monty/crates/monty-python/tests/test_os_calls.py +0 -819
  1010. package/ref-monty/crates/monty-python/tests/test_print.py +0 -208
  1011. package/ref-monty/crates/monty-python/tests/test_re.py +0 -170
  1012. package/ref-monty/crates/monty-python/tests/test_readme_examples.py +0 -20
  1013. package/ref-monty/crates/monty-python/tests/test_repl.py +0 -749
  1014. package/ref-monty/crates/monty-python/tests/test_serialize.py +0 -284
  1015. package/ref-monty/crates/monty-python/tests/test_start.py +0 -346
  1016. package/ref-monty/crates/monty-python/tests/test_threading.py +0 -163
  1017. package/ref-monty/crates/monty-python/tests/test_type_check.py +0 -344
  1018. package/ref-monty/crates/monty-python/tests/test_types.py +0 -553
  1019. package/ref-monty/crates/monty-type-checking/Cargo.toml +0 -32
  1020. package/ref-monty/crates/monty-type-checking/src/db.rs +0 -116
  1021. package/ref-monty/crates/monty-type-checking/src/lib.rs +0 -4
  1022. package/ref-monty/crates/monty-type-checking/src/type_check.rs +0 -280
  1023. package/ref-monty/crates/monty-type-checking/tests/bad_types.py +0 -109
  1024. package/ref-monty/crates/monty-type-checking/tests/bad_types_output.txt +0 -21
  1025. package/ref-monty/crates/monty-type-checking/tests/good_types.py +0 -475
  1026. package/ref-monty/crates/monty-type-checking/tests/main.rs +0 -205
  1027. package/ref-monty/crates/monty-type-checking/tests/reveal_types.py +0 -56
  1028. package/ref-monty/crates/monty-type-checking/tests/reveal_types_output.txt +0 -41
  1029. package/ref-monty/crates/monty-typeshed/Cargo.toml +0 -29
  1030. package/ref-monty/crates/monty-typeshed/README.md +0 -11
  1031. package/ref-monty/crates/monty-typeshed/build.rs +0 -101
  1032. package/ref-monty/crates/monty-typeshed/custom/README.md +0 -1
  1033. package/ref-monty/crates/monty-typeshed/custom/asyncio.pyi +0 -138
  1034. package/ref-monty/crates/monty-typeshed/custom/os.pyi +0 -87
  1035. package/ref-monty/crates/monty-typeshed/custom/sys.pyi +0 -33
  1036. package/ref-monty/crates/monty-typeshed/src/lib.rs +0 -56
  1037. package/ref-monty/crates/monty-typeshed/update.py +0 -321
  1038. package/ref-monty/crates/monty-typeshed/vendor/typeshed/source_commit.txt +0 -1
  1039. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/VERSIONS +0 -20
  1040. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi +0 -105
  1041. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi +0 -394
  1042. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi +0 -138
  1043. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi +0 -1434
  1044. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi +0 -527
  1045. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/abc.pyi +0 -2
  1046. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/dataclasses.pyi +0 -502
  1047. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/enum.pyi +0 -376
  1048. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/math.pyi +0 -149
  1049. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/os.pyi +0 -87
  1050. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/__init__.pyi +0 -395
  1051. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/types.pyi +0 -8
  1052. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/re.pyi +0 -337
  1053. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/sys.pyi +0 -33
  1054. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/types.pyi +0 -741
  1055. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing.pyi +0 -1217
  1056. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing_extensions.pyi +0 -716
  1057. package/ref-monty/docs/usage-guide.md +0 -117
  1058. package/ref-monty/examples/README.md +0 -3
  1059. package/ref-monty/examples/expense_analysis/README.md +0 -3
  1060. package/ref-monty/examples/expense_analysis/data.py +0 -124
  1061. package/ref-monty/examples/expense_analysis/main.py +0 -115
  1062. package/ref-monty/examples/sql_playground/README.md +0 -20
  1063. package/ref-monty/examples/sql_playground/external_functions.py +0 -129
  1064. package/ref-monty/examples/sql_playground/main.py +0 -81
  1065. package/ref-monty/examples/sql_playground/sandbox_code.py +0 -82
  1066. package/ref-monty/examples/sql_playground/type_stubs.pyi +0 -14
  1067. package/ref-monty/examples/web_scraper/README.md +0 -15
  1068. package/ref-monty/examples/web_scraper/browser.py +0 -56
  1069. package/ref-monty/examples/web_scraper/example_code.py +0 -59
  1070. package/ref-monty/examples/web_scraper/external_functions.py +0 -324
  1071. package/ref-monty/examples/web_scraper/main.py +0 -193
  1072. package/ref-monty/examples/web_scraper/sub_agent.py +0 -79
  1073. package/ref-monty/monty-npm.md +0 -235
  1074. package/ref-monty/pyproject.toml +0 -162
  1075. package/ref-monty/scripts/check_imports.py +0 -91
  1076. package/ref-monty/scripts/codecov_diff.py +0 -412
  1077. package/ref-monty/scripts/complete_tests.py +0 -146
  1078. package/ref-monty/scripts/flamegraph_to_text.py +0 -208
  1079. package/ref-monty/scripts/iter_test_methods.py +0 -540
  1080. package/ref-monty/scripts/run_traceback.py +0 -180
  1081. package/ref-monty/scripts/startup_performance.py +0 -130
  1082. package/ref-monty/uv.lock +0 -1779
  1083. package/temp_resend_cli/repo/.github/scripts/pr-title-check.js +0 -34
  1084. package/temp_resend_cli/repo/.github/workflows/ci.yml +0 -67
  1085. package/temp_resend_cli/repo/.github/workflows/post-release.yml +0 -51
  1086. package/temp_resend_cli/repo/.github/workflows/pr-title-check.yml +0 -13
  1087. package/temp_resend_cli/repo/.github/workflows/release.yml +0 -175
  1088. package/temp_resend_cli/repo/.github/workflows/test-install-unix.yml +0 -34
  1089. package/temp_resend_cli/repo/.github/workflows/test-install-windows.yml +0 -48
  1090. package/temp_resend_cli/repo/CHANGELOG.md +0 -31
  1091. package/temp_resend_cli/repo/LICENSE +0 -21
  1092. package/temp_resend_cli/repo/README.md +0 -450
  1093. package/temp_resend_cli/repo/biome.json +0 -36
  1094. package/temp_resend_cli/repo/install.ps1 +0 -141
  1095. package/temp_resend_cli/repo/install.sh +0 -301
  1096. package/temp_resend_cli/repo/package.json +0 -61
  1097. package/temp_resend_cli/repo/pnpm-lock.yaml +0 -2439
  1098. package/temp_resend_cli/repo/renovate.json +0 -4
  1099. package/temp_resend_cli/repo/src/cli.ts +0 -98
  1100. package/temp_resend_cli/repo/src/commands/api-keys/create.ts +0 -114
  1101. package/temp_resend_cli/repo/src/commands/api-keys/delete.ts +0 -47
  1102. package/temp_resend_cli/repo/src/commands/api-keys/index.ts +0 -26
  1103. package/temp_resend_cli/repo/src/commands/api-keys/list.ts +0 -35
  1104. package/temp_resend_cli/repo/src/commands/api-keys/utils.ts +0 -8
  1105. package/temp_resend_cli/repo/src/commands/auth/index.ts +0 -20
  1106. package/temp_resend_cli/repo/src/commands/auth/login.ts +0 -234
  1107. package/temp_resend_cli/repo/src/commands/auth/logout.ts +0 -105
  1108. package/temp_resend_cli/repo/src/commands/broadcasts/create.ts +0 -196
  1109. package/temp_resend_cli/repo/src/commands/broadcasts/delete.ts +0 -46
  1110. package/temp_resend_cli/repo/src/commands/broadcasts/get.ts +0 -59
  1111. package/temp_resend_cli/repo/src/commands/broadcasts/index.ts +0 -43
  1112. package/temp_resend_cli/repo/src/commands/broadcasts/list.ts +0 -60
  1113. package/temp_resend_cli/repo/src/commands/broadcasts/send.ts +0 -56
  1114. package/temp_resend_cli/repo/src/commands/broadcasts/update.ts +0 -95
  1115. package/temp_resend_cli/repo/src/commands/broadcasts/utils.ts +0 -35
  1116. package/temp_resend_cli/repo/src/commands/contact-properties/create.ts +0 -118
  1117. package/temp_resend_cli/repo/src/commands/contact-properties/delete.ts +0 -48
  1118. package/temp_resend_cli/repo/src/commands/contact-properties/get.ts +0 -46
  1119. package/temp_resend_cli/repo/src/commands/contact-properties/index.ts +0 -48
  1120. package/temp_resend_cli/repo/src/commands/contact-properties/list.ts +0 -68
  1121. package/temp_resend_cli/repo/src/commands/contact-properties/update.ts +0 -88
  1122. package/temp_resend_cli/repo/src/commands/contact-properties/utils.ts +0 -17
  1123. package/temp_resend_cli/repo/src/commands/contacts/add-segment.ts +0 -78
  1124. package/temp_resend_cli/repo/src/commands/contacts/create.ts +0 -122
  1125. package/temp_resend_cli/repo/src/commands/contacts/delete.ts +0 -49
  1126. package/temp_resend_cli/repo/src/commands/contacts/get.ts +0 -53
  1127. package/temp_resend_cli/repo/src/commands/contacts/index.ts +0 -58
  1128. package/temp_resend_cli/repo/src/commands/contacts/list.ts +0 -57
  1129. package/temp_resend_cli/repo/src/commands/contacts/remove-segment.ts +0 -48
  1130. package/temp_resend_cli/repo/src/commands/contacts/segments.ts +0 -39
  1131. package/temp_resend_cli/repo/src/commands/contacts/topics.ts +0 -45
  1132. package/temp_resend_cli/repo/src/commands/contacts/update-topics.ts +0 -90
  1133. package/temp_resend_cli/repo/src/commands/contacts/update.ts +0 -77
  1134. package/temp_resend_cli/repo/src/commands/contacts/utils.ts +0 -119
  1135. package/temp_resend_cli/repo/src/commands/doctor.ts +0 -216
  1136. package/temp_resend_cli/repo/src/commands/domains/create.ts +0 -83
  1137. package/temp_resend_cli/repo/src/commands/domains/delete.ts +0 -42
  1138. package/temp_resend_cli/repo/src/commands/domains/get.ts +0 -47
  1139. package/temp_resend_cli/repo/src/commands/domains/index.ts +0 -35
  1140. package/temp_resend_cli/repo/src/commands/domains/list.ts +0 -53
  1141. package/temp_resend_cli/repo/src/commands/domains/update.ts +0 -75
  1142. package/temp_resend_cli/repo/src/commands/domains/utils.ts +0 -44
  1143. package/temp_resend_cli/repo/src/commands/domains/verify.ts +0 -38
  1144. package/temp_resend_cli/repo/src/commands/emails/batch.ts +0 -140
  1145. package/temp_resend_cli/repo/src/commands/emails/get.ts +0 -44
  1146. package/temp_resend_cli/repo/src/commands/emails/index.ts +0 -30
  1147. package/temp_resend_cli/repo/src/commands/emails/list.ts +0 -84
  1148. package/temp_resend_cli/repo/src/commands/emails/receiving/attachment.ts +0 -55
  1149. package/temp_resend_cli/repo/src/commands/emails/receiving/attachments.ts +0 -68
  1150. package/temp_resend_cli/repo/src/commands/emails/receiving/get.ts +0 -58
  1151. package/temp_resend_cli/repo/src/commands/emails/receiving/index.ts +0 -28
  1152. package/temp_resend_cli/repo/src/commands/emails/receiving/list.ts +0 -59
  1153. package/temp_resend_cli/repo/src/commands/emails/receiving/utils.ts +0 -38
  1154. package/temp_resend_cli/repo/src/commands/emails/send.ts +0 -189
  1155. package/temp_resend_cli/repo/src/commands/open.ts +0 -27
  1156. package/temp_resend_cli/repo/src/commands/segments/create.ts +0 -50
  1157. package/temp_resend_cli/repo/src/commands/segments/delete.ts +0 -47
  1158. package/temp_resend_cli/repo/src/commands/segments/get.ts +0 -38
  1159. package/temp_resend_cli/repo/src/commands/segments/index.ts +0 -36
  1160. package/temp_resend_cli/repo/src/commands/segments/list.ts +0 -58
  1161. package/temp_resend_cli/repo/src/commands/segments/utils.ts +0 -7
  1162. package/temp_resend_cli/repo/src/commands/teams/index.ts +0 -10
  1163. package/temp_resend_cli/repo/src/commands/teams/list.ts +0 -35
  1164. package/temp_resend_cli/repo/src/commands/teams/remove.ts +0 -86
  1165. package/temp_resend_cli/repo/src/commands/teams/switch.ts +0 -76
  1166. package/temp_resend_cli/repo/src/commands/topics/create.ts +0 -73
  1167. package/temp_resend_cli/repo/src/commands/topics/delete.ts +0 -47
  1168. package/temp_resend_cli/repo/src/commands/topics/get.ts +0 -42
  1169. package/temp_resend_cli/repo/src/commands/topics/index.ts +0 -42
  1170. package/temp_resend_cli/repo/src/commands/topics/list.ts +0 -34
  1171. package/temp_resend_cli/repo/src/commands/topics/update.ts +0 -59
  1172. package/temp_resend_cli/repo/src/commands/topics/utils.ts +0 -16
  1173. package/temp_resend_cli/repo/src/commands/webhooks/create.ts +0 -128
  1174. package/temp_resend_cli/repo/src/commands/webhooks/delete.ts +0 -49
  1175. package/temp_resend_cli/repo/src/commands/webhooks/get.ts +0 -42
  1176. package/temp_resend_cli/repo/src/commands/webhooks/index.ts +0 -42
  1177. package/temp_resend_cli/repo/src/commands/webhooks/list.ts +0 -55
  1178. package/temp_resend_cli/repo/src/commands/webhooks/listen.ts +0 -379
  1179. package/temp_resend_cli/repo/src/commands/webhooks/update.ts +0 -83
  1180. package/temp_resend_cli/repo/src/commands/webhooks/utils.ts +0 -36
  1181. package/temp_resend_cli/repo/src/commands/whoami.ts +0 -71
  1182. package/temp_resend_cli/repo/src/lib/actions.ts +0 -157
  1183. package/temp_resend_cli/repo/src/lib/client.ts +0 -37
  1184. package/temp_resend_cli/repo/src/lib/config.ts +0 -217
  1185. package/temp_resend_cli/repo/src/lib/files.ts +0 -15
  1186. package/temp_resend_cli/repo/src/lib/help-text.ts +0 -38
  1187. package/temp_resend_cli/repo/src/lib/output.ts +0 -56
  1188. package/temp_resend_cli/repo/src/lib/pagination.ts +0 -36
  1189. package/temp_resend_cli/repo/src/lib/prompts.ts +0 -149
  1190. package/temp_resend_cli/repo/src/lib/spinner.ts +0 -100
  1191. package/temp_resend_cli/repo/src/lib/table.ts +0 -57
  1192. package/temp_resend_cli/repo/src/lib/tty.ts +0 -28
  1193. package/temp_resend_cli/repo/src/lib/update-check.ts +0 -169
  1194. package/temp_resend_cli/repo/src/lib/version.ts +0 -4
  1195. package/temp_resend_cli/repo/tests/commands/api-keys/create.test.ts +0 -196
  1196. package/temp_resend_cli/repo/tests/commands/api-keys/delete.test.ts +0 -157
  1197. package/temp_resend_cli/repo/tests/commands/api-keys/list.test.ts +0 -134
  1198. package/temp_resend_cli/repo/tests/commands/auth/login.test.ts +0 -153
  1199. package/temp_resend_cli/repo/tests/commands/auth/logout.test.ts +0 -153
  1200. package/temp_resend_cli/repo/tests/commands/broadcasts/create.test.ts +0 -454
  1201. package/temp_resend_cli/repo/tests/commands/broadcasts/delete.test.ts +0 -183
  1202. package/temp_resend_cli/repo/tests/commands/broadcasts/get.test.ts +0 -147
  1203. package/temp_resend_cli/repo/tests/commands/broadcasts/list.test.ts +0 -199
  1204. package/temp_resend_cli/repo/tests/commands/broadcasts/send.test.ts +0 -162
  1205. package/temp_resend_cli/repo/tests/commands/broadcasts/update.test.ts +0 -288
  1206. package/temp_resend_cli/repo/tests/commands/contact-properties/create.test.ts +0 -251
  1207. package/temp_resend_cli/repo/tests/commands/contact-properties/delete.test.ts +0 -184
  1208. package/temp_resend_cli/repo/tests/commands/contact-properties/get.test.ts +0 -145
  1209. package/temp_resend_cli/repo/tests/commands/contact-properties/list.test.ts +0 -181
  1210. package/temp_resend_cli/repo/tests/commands/contact-properties/update.test.ts +0 -217
  1211. package/temp_resend_cli/repo/tests/commands/contacts/add-segment.test.ts +0 -189
  1212. package/temp_resend_cli/repo/tests/commands/contacts/create.test.ts +0 -271
  1213. package/temp_resend_cli/repo/tests/commands/contacts/delete.test.ts +0 -193
  1214. package/temp_resend_cli/repo/tests/commands/contacts/get.test.ts +0 -149
  1215. package/temp_resend_cli/repo/tests/commands/contacts/list.test.ts +0 -176
  1216. package/temp_resend_cli/repo/tests/commands/contacts/remove-segment.test.ts +0 -167
  1217. package/temp_resend_cli/repo/tests/commands/contacts/segments.test.ts +0 -168
  1218. package/temp_resend_cli/repo/tests/commands/contacts/topics.test.ts +0 -164
  1219. package/temp_resend_cli/repo/tests/commands/contacts/update-topics.test.ts +0 -248
  1220. package/temp_resend_cli/repo/tests/commands/contacts/update.test.ts +0 -206
  1221. package/temp_resend_cli/repo/tests/commands/doctor.test.ts +0 -164
  1222. package/temp_resend_cli/repo/tests/commands/domains/create.test.ts +0 -193
  1223. package/temp_resend_cli/repo/tests/commands/domains/delete.test.ts +0 -157
  1224. package/temp_resend_cli/repo/tests/commands/domains/get.test.ts +0 -138
  1225. package/temp_resend_cli/repo/tests/commands/domains/list.test.ts +0 -165
  1226. package/temp_resend_cli/repo/tests/commands/domains/update.test.ts +0 -224
  1227. package/temp_resend_cli/repo/tests/commands/domains/verify.test.ts +0 -118
  1228. package/temp_resend_cli/repo/tests/commands/emails/batch.test.ts +0 -324
  1229. package/temp_resend_cli/repo/tests/commands/emails/get.test.ts +0 -132
  1230. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachment.test.ts +0 -141
  1231. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachments.test.ts +0 -169
  1232. package/temp_resend_cli/repo/tests/commands/emails/receiving/get.test.ts +0 -141
  1233. package/temp_resend_cli/repo/tests/commands/emails/receiving/list.test.ts +0 -182
  1234. package/temp_resend_cli/repo/tests/commands/emails/send.test.ts +0 -312
  1235. package/temp_resend_cli/repo/tests/commands/segments/create.test.ts +0 -164
  1236. package/temp_resend_cli/repo/tests/commands/segments/delete.test.ts +0 -183
  1237. package/temp_resend_cli/repo/tests/commands/segments/get.test.ts +0 -138
  1238. package/temp_resend_cli/repo/tests/commands/segments/list.test.ts +0 -174
  1239. package/temp_resend_cli/repo/tests/commands/teams/list.test.ts +0 -62
  1240. package/temp_resend_cli/repo/tests/commands/teams/remove.test.ts +0 -110
  1241. package/temp_resend_cli/repo/tests/commands/teams/switch.test.ts +0 -103
  1242. package/temp_resend_cli/repo/tests/commands/topics/create.test.ts +0 -192
  1243. package/temp_resend_cli/repo/tests/commands/topics/delete.test.ts +0 -157
  1244. package/temp_resend_cli/repo/tests/commands/topics/get.test.ts +0 -126
  1245. package/temp_resend_cli/repo/tests/commands/topics/list.test.ts +0 -125
  1246. package/temp_resend_cli/repo/tests/commands/topics/update.test.ts +0 -178
  1247. package/temp_resend_cli/repo/tests/commands/webhooks/create.test.ts +0 -225
  1248. package/temp_resend_cli/repo/tests/commands/webhooks/delete.test.ts +0 -157
  1249. package/temp_resend_cli/repo/tests/commands/webhooks/get.test.ts +0 -126
  1250. package/temp_resend_cli/repo/tests/commands/webhooks/list.test.ts +0 -178
  1251. package/temp_resend_cli/repo/tests/commands/webhooks/update.test.ts +0 -207
  1252. package/temp_resend_cli/repo/tests/commands/whoami.test.ts +0 -98
  1253. package/temp_resend_cli/repo/tests/e2e/smoke.test.ts +0 -93
  1254. package/temp_resend_cli/repo/tests/helpers.ts +0 -86
  1255. package/temp_resend_cli/repo/tests/lib/client.test.ts +0 -71
  1256. package/temp_resend_cli/repo/tests/lib/config.test.ts +0 -451
  1257. package/temp_resend_cli/repo/tests/lib/files.test.ts +0 -73
  1258. package/temp_resend_cli/repo/tests/lib/help-text.test.ts +0 -97
  1259. package/temp_resend_cli/repo/tests/lib/output.test.ts +0 -136
  1260. package/temp_resend_cli/repo/tests/lib/prompts.test.ts +0 -185
  1261. package/temp_resend_cli/repo/tests/lib/spinner.test.ts +0 -166
  1262. package/temp_resend_cli/repo/tests/lib/table.test.ts +0 -63
  1263. package/temp_resend_cli/repo/tests/lib/tty.test.ts +0 -89
  1264. package/temp_resend_cli/repo/tests/lib/update-check.test.ts +0 -179
  1265. package/temp_resend_cli/repo/tsconfig.json +0 -14
  1266. package/temp_resend_cli/repo/vitest.config.e2e.ts +0 -8
  1267. package/temp_resend_cli/repo/vitest.config.ts +0 -10
  1268. /package/docs/{plugin-examples.md → plugins-examples.md} +0 -0
@@ -1,3015 +0,0 @@
1
- use std::collections::hash_map::Entry;
2
-
3
- use ahash::{AHashMap, AHashSet};
4
-
5
- use crate::{
6
- args::{ArgExprs, CallArg, CallKwarg},
7
- builtins::Builtins,
8
- expressions::{
9
- Callable, CmpOperator, Comprehension, DictItem, Expr, ExprLoc, Identifier, Literal, NameScope, Node, Operator,
10
- PreparedFunctionDef, PreparedNode, SequenceItem, UnpackTarget,
11
- },
12
- fstring::{FStringPart, FormatSpec},
13
- intern::{InternerBuilder, StringId},
14
- namespace::NamespaceId,
15
- parse::{CodeRange, ExceptHandler, ParseError, ParseNode, ParseResult, ParsedSignature, RawFunctionDef, Try},
16
- signature::Signature,
17
- };
18
-
19
- /// Result of the prepare phase, containing everything needed to compile and execute code.
20
- ///
21
- /// This struct holds the outputs of name resolution and AST transformation:
22
- /// - The namespace size (number of slots needed at module level)
23
- /// - A mapping from variable names to their namespace indices (for ref-count testing)
24
- /// - The transformed AST nodes with all names resolved, ready for compilation
25
- /// - The string interner containing all interned identifiers and filenames
26
- pub struct PrepareResult {
27
- /// Number of items in the namespace (at module level, this IS the global namespace)
28
- pub namespace_size: usize,
29
- /// Maps variable names to their indices in the namespace.
30
- ///
31
- /// This map is used by:
32
- /// - ref-count tests for looking up variables by name
33
- /// - REPL incremental compilation to preserve stable global slot IDs across snippets
34
- pub name_map: AHashMap<String, NamespaceId>,
35
- /// The prepared AST nodes with all names resolved to namespace indices.
36
- /// Function definitions are inline as `PreparedFunctionDef` variants.
37
- pub nodes: Vec<PreparedNode>,
38
- /// The string interner containing all interned identifiers and filenames.
39
- pub interner: InternerBuilder,
40
- }
41
-
42
- /// Prepares parsed nodes for compilation by resolving names and building the initial namespace.
43
- ///
44
- /// The namespace will be converted to runtime Objects when execution begins and the heap is available.
45
- /// At module level, the local namespace IS the global namespace.
46
- pub(crate) fn prepare(parse_result: ParseResult, input_names: Vec<String>) -> Result<PrepareResult, ParseError> {
47
- let ParseResult { nodes, interner } = parse_result;
48
- let mut p = Prepare::new_module(input_names, &interner);
49
- let mut prepared_nodes = p.prepare_nodes(nodes)?;
50
-
51
- // In the root frame, the last expression is implicitly returned
52
- // if it's not None. This matches Python REPL behavior where the last expression
53
- // value is displayed/returned.
54
- if let Some(Node::Expr(expr_loc)) = prepared_nodes.last()
55
- && !expr_loc.expr.is_none()
56
- {
57
- let new_expr_loc = expr_loc.clone();
58
- prepared_nodes.pop();
59
- prepared_nodes.push(Node::Return(new_expr_loc));
60
- }
61
-
62
- Ok(PrepareResult {
63
- namespace_size: p.namespace_size,
64
- name_map: p.name_map,
65
- nodes: prepared_nodes,
66
- interner,
67
- })
68
- }
69
-
70
- /// Prepares parsed nodes for REPL-style incremental compilation using an existing global namespace map.
71
- ///
72
- /// Existing bindings keep their original namespace slots; any new names are appended with new slots.
73
- /// This ensures snippets can be compiled independently while sharing one persistent global namespace.
74
- pub(crate) fn prepare_with_existing_names(
75
- parse_result: ParseResult,
76
- existing_name_map: AHashMap<String, NamespaceId>,
77
- ) -> Result<PrepareResult, ParseError> {
78
- let ParseResult { nodes, interner } = parse_result;
79
- let mut p = Prepare::new_module_with_name_map(existing_name_map, &interner);
80
- let mut prepared_nodes = p.prepare_nodes(nodes)?;
81
-
82
- // In the root frame, the last expression is implicitly returned to match REPL behavior.
83
- if let Some(Node::Expr(expr_loc)) = prepared_nodes.last()
84
- && !expr_loc.expr.is_none()
85
- {
86
- let new_expr_loc = expr_loc.clone();
87
- prepared_nodes.pop();
88
- prepared_nodes.push(Node::Return(new_expr_loc));
89
- }
90
-
91
- Ok(PrepareResult {
92
- namespace_size: p.namespace_size,
93
- name_map: p.name_map,
94
- nodes: prepared_nodes,
95
- interner,
96
- })
97
- }
98
-
99
- /// State machine for the preparation phase that transforms parsed AST nodes into a prepared form.
100
- ///
101
- /// This struct maintains the mapping between variable names and their namespace indices,
102
- /// and handles scope resolution. The preparation phase is crucial for converting string-based
103
- /// name lookups into efficient integer-indexed namespace access during compilation and execution.
104
- ///
105
- /// For functions, this struct also tracks:
106
- /// - Which variables are declared `global` (should resolve to module namespace)
107
- /// - Which variables are declared `nonlocal` (should resolve to enclosing scope via cells)
108
- /// - Which variables are assigned locally (determines local vs global scope)
109
- /// - Reference to the global name map for resolving global variable references
110
- /// - Enclosing scope information for closure analysis
111
- struct Prepare<'i> {
112
- /// Reference to the string interner for looking up names in error messages.
113
- interner: &'i InternerBuilder,
114
- /// Maps variable names to their indices in this scope's namespace vector
115
- name_map: AHashMap<String, NamespaceId>,
116
- /// Number of items in the namespace
117
- pub namespace_size: usize,
118
- /// Whether this is the module-level scope.
119
- /// At module level, all variables are global and `global` keyword is a no-op.
120
- is_module_scope: bool,
121
- /// Names declared as `global` in this scope.
122
- /// These names will resolve to the global namespace instead of local.
123
- global_names: AHashSet<String>,
124
- /// Names that are assigned in this scope (from first-pass scan).
125
- /// Used in functions to determine if a variable is local (assigned) or global (only read).
126
- assigned_names: AHashSet<String>,
127
- /// Names that have been assigned so far during the second pass (in order).
128
- /// Used to produce the correct error message for `global x` when x was assigned before.
129
- names_assigned_in_order: AHashSet<String>,
130
- /// Copy of the module-level global name map.
131
- /// Used by functions to resolve global variable references.
132
- /// None at module level (not needed since all names are global there).
133
- global_name_map: Option<AHashMap<String, NamespaceId>>,
134
- /// Names that exist as locals in the enclosing function scope.
135
- /// Used to validate `nonlocal` declarations and resolve captured variables.
136
- /// None at module level or when there's no enclosing function.
137
- enclosing_locals: Option<AHashSet<String>>,
138
- /// Maps free variable names (from nonlocal declarations and implicit captures) to their
139
- /// index in the free_vars vector. Pre-populated with nonlocal names at initialization,
140
- /// then extended with implicit captures discovered during preparation.
141
- free_var_map: AHashMap<String, NamespaceId>,
142
- /// Maps cell variable names to their index in the owned_cells vector.
143
- /// Pre-populated with cell_var names at initialization (excluding pass-through variables
144
- /// that are both nonlocal and captured by nested functions), then extended as new
145
- /// captures are discovered during nested function preparation.
146
- cell_var_map: AHashMap<String, NamespaceId>,
147
- /// Names that were resolved as `LocalUnassigned` in step 8 of `get_id`.
148
- ///
149
- /// These names are never assigned and not parameters - they were only referenced
150
- /// (e.g., external function names). Tracking them prevents step 6 from incorrectly
151
- /// classifying subsequent references as `Local` (like parameters) when the name
152
- /// appears in `name_map` from a previous `get_id` call.
153
- unassigned_ref_names: AHashSet<String>,
154
- }
155
-
156
- impl<'i> Prepare<'i> {
157
- /// Creates a new Prepare instance for module-level code.
158
- ///
159
- /// At module level, all variables are global. The `global` keyword is a no-op
160
- /// since all variables are already in the global namespace.
161
- ///
162
- /// # Arguments
163
- /// * `input_names` - Names that should be pre-registered in the namespace (e.g., input variables)
164
- /// * `interner` - Reference to the string interner for looking up names
165
- fn new_module(input_names: Vec<String>, interner: &'i InternerBuilder) -> Self {
166
- let mut name_map = AHashMap::with_capacity(input_names.len());
167
- for (index, name) in input_names.into_iter().enumerate() {
168
- name_map.insert(name, NamespaceId::new(index));
169
- }
170
- let namespace_size = name_map.len();
171
- Self {
172
- interner,
173
- name_map,
174
- namespace_size,
175
- is_module_scope: true,
176
- global_names: AHashSet::new(),
177
- assigned_names: AHashSet::new(),
178
- names_assigned_in_order: AHashSet::new(),
179
- global_name_map: None,
180
- enclosing_locals: None,
181
- free_var_map: AHashMap::new(),
182
- cell_var_map: AHashMap::new(),
183
- unassigned_ref_names: AHashSet::new(),
184
- }
185
- }
186
-
187
- /// Creates a module-scope Prepare instance from an existing global name map.
188
- ///
189
- /// Used by incremental REPL compilation to keep stable slot assignments across snippets.
190
- fn new_module_with_name_map(name_map: AHashMap<String, NamespaceId>, interner: &'i InternerBuilder) -> Self {
191
- let namespace_size = name_map
192
- .values()
193
- .map(|id| id.index())
194
- .max()
195
- .map_or(0, |max_idx| max_idx + 1);
196
-
197
- Self {
198
- interner,
199
- name_map,
200
- namespace_size,
201
- is_module_scope: true,
202
- global_names: AHashSet::new(),
203
- assigned_names: AHashSet::new(),
204
- names_assigned_in_order: AHashSet::new(),
205
- global_name_map: None,
206
- enclosing_locals: None,
207
- free_var_map: AHashMap::new(),
208
- cell_var_map: AHashMap::new(),
209
- unassigned_ref_names: AHashSet::new(),
210
- }
211
- }
212
-
213
- /// Creates a new Prepare instance for function-level code.
214
- ///
215
- /// Pre-populates `free_var_map` with nonlocal declarations and implicit captures,
216
- /// and `cell_var_map` with cell variables (excluding pass-through variables).
217
- ///
218
- /// # Arguments
219
- /// * `capacity` - Expected number of nodes
220
- /// * `params` - Function parameter StringIds (pre-registered in namespace)
221
- /// * `assigned_names` - Names that are assigned in this function (from first-pass scan)
222
- /// * `global_names` - Names declared as `global` in this function
223
- /// * `nonlocal_names` - Names declared as `nonlocal` in this function
224
- /// * `implicit_captures` - Names captured from enclosing scope without explicit nonlocal
225
- /// * `global_name_map` - Copy of the module-level name map for global resolution
226
- /// * `enclosing_locals` - Names that exist as locals in the enclosing function (for nonlocal resolution)
227
- /// * `cell_var_names` - Names that are captured by nested functions (must be stored in cells)
228
- /// * `interner` - Reference to the string interner for looking up names
229
- #[expect(clippy::too_many_arguments)]
230
- fn new_function(
231
- capacity: usize,
232
- params: &[StringId],
233
- assigned_names: AHashSet<String>,
234
- global_names: AHashSet<String>,
235
- nonlocal_names: AHashSet<String>,
236
- implicit_captures: AHashSet<String>,
237
- global_name_map: AHashMap<String, NamespaceId>,
238
- enclosing_locals: Option<AHashSet<String>>,
239
- cell_var_names: AHashSet<String>,
240
- interner: &'i InternerBuilder,
241
- ) -> Self {
242
- let mut name_map = AHashMap::with_capacity(capacity);
243
- for (index, string_id) in params.iter().enumerate() {
244
- name_map.insert(interner.get_str(*string_id).to_string(), NamespaceId::new(index));
245
- }
246
- let namespace_size = name_map.len();
247
-
248
- // Namespace layout: [params][cell_vars][free_vars][locals]
249
- // This predictable layout allows sequential namespace construction at runtime.
250
-
251
- // Pre-populate cell_var_map with cell variables FIRST (right after params).
252
- // Excludes pass-through variables (names that are both nonlocal and captured by
253
- // nested functions - these stay in free_var_map since we receive the cell, not create it).
254
- // NOTE: We intentionally do NOT add these to name_map here, because the scope
255
- // validation checks name_map to detect "used before declaration" errors
256
- let mut cell_var_map = AHashMap::with_capacity(cell_var_names.len());
257
- let mut namespace_size = namespace_size;
258
- for name in cell_var_names {
259
- if !nonlocal_names.contains(&name) && !implicit_captures.contains(&name) {
260
- let slot = namespace_size;
261
- namespace_size += 1;
262
- cell_var_map.insert(name, NamespaceId::new(slot));
263
- }
264
- }
265
-
266
- // Pre-populate free_var_map with nonlocal declarations AND implicit captures SECOND (after cell_vars).
267
- // Each entry maps name -> namespace slot index where the cell reference will be stored.
268
- // NOTE: We intentionally do NOT add these to name_map here, because the nonlocal
269
- // validation in prepare_nodes checks name_map to detect "used before nonlocal declaration"
270
- let free_var_capacity = nonlocal_names.len() + implicit_captures.len();
271
- let mut free_var_map = AHashMap::with_capacity(free_var_capacity);
272
- for name in nonlocal_names {
273
- let slot = namespace_size;
274
- namespace_size += 1;
275
- free_var_map.insert(name, NamespaceId::new(slot));
276
- }
277
- // Implicit captures (variables accessed from enclosing scope without explicit nonlocal)
278
- for name in implicit_captures {
279
- let slot = namespace_size;
280
- namespace_size += 1;
281
- free_var_map.insert(name, NamespaceId::new(slot));
282
- }
283
-
284
- Self {
285
- interner,
286
- name_map,
287
- namespace_size,
288
- is_module_scope: false,
289
- global_names,
290
- assigned_names,
291
- names_assigned_in_order: AHashSet::new(),
292
- global_name_map: Some(global_name_map),
293
- enclosing_locals,
294
- free_var_map,
295
- cell_var_map,
296
- unassigned_ref_names: AHashSet::new(),
297
- }
298
- }
299
-
300
- /// Recursively prepares a sequence of AST nodes by resolving names and transforming expressions.
301
- ///
302
- /// This method processes each node type differently:
303
- /// - Resolves variable names to namespace indices
304
- /// - Transforms function calls from identifier-based to builtin type-based
305
- /// - Handles special cases like implicit returns in root frames
306
- /// - Validates that names used in attribute calls are already defined
307
- ///
308
- /// # Returns
309
- /// A vector of prepared nodes ready for compilation
310
- fn prepare_nodes(&mut self, nodes: Vec<ParseNode>) -> Result<Vec<PreparedNode>, ParseError> {
311
- let nodes_len = nodes.len();
312
- let mut new_nodes = Vec::with_capacity(nodes_len);
313
- for node in nodes {
314
- match node {
315
- Node::Pass => (),
316
- Node::Expr(expr) => new_nodes.push(Node::Expr(self.prepare_expression(expr)?)),
317
- Node::Return(expr) => new_nodes.push(Node::Return(self.prepare_expression(expr)?)),
318
- Node::ReturnNone => new_nodes.push(Node::ReturnNone),
319
- Node::Raise(exc) => {
320
- let expr = match exc {
321
- Some(expr) => {
322
- let prepared = self.prepare_expression(expr)?;
323
- match prepared.expr {
324
- // Handle raising a builtin exception type without instantiation,
325
- // e.g. `raise TypeError`. Transform into `raise TypeError()`
326
- // so the exception is properly instantiated before being raised.
327
- Expr::Builtin(b) => {
328
- let call_expr = Expr::Call {
329
- callable: Callable::Builtin(b),
330
- args: Box::new(ArgExprs::Empty),
331
- };
332
- Some(ExprLoc::new(prepared.position, call_expr))
333
- }
334
- _ => Some(prepared),
335
- }
336
- }
337
- None => None,
338
- };
339
- new_nodes.push(Node::Raise(expr));
340
- }
341
- Node::Assert { test, msg } => {
342
- let test = self.prepare_expression(test)?;
343
- let msg = match msg {
344
- Some(m) => Some(self.prepare_expression(m)?),
345
- None => None,
346
- };
347
- new_nodes.push(Node::Assert { test, msg });
348
- }
349
- Node::Assign { target, object } => {
350
- let object = self.prepare_expression(object)?;
351
- // Track that this name was assigned before we call get_id
352
- self.names_assigned_in_order
353
- .insert(self.interner.get_str(target.name_id).to_string());
354
- let (target, _) = self.get_id(target);
355
- new_nodes.push(Node::Assign { target, object });
356
- }
357
- Node::UnpackAssign {
358
- targets,
359
- targets_position,
360
- object,
361
- } => {
362
- let object = self.prepare_expression(object)?;
363
- // Recursively resolve all targets (supports nested tuples)
364
- let targets = targets
365
- .into_iter()
366
- .map(|target| self.prepare_unpack_target(target))
367
- .collect();
368
- new_nodes.push(Node::UnpackAssign {
369
- targets,
370
- targets_position,
371
- object,
372
- });
373
- }
374
- Node::OpAssign { target, op, object } => {
375
- // Track that this name was assigned
376
- self.names_assigned_in_order
377
- .insert(self.interner.get_str(target.name_id).to_string());
378
- let target = self.get_id(target).0;
379
- let object = self.prepare_expression(object)?;
380
- new_nodes.push(Node::OpAssign { target, op, object });
381
- }
382
- Node::SubscriptOpAssign {
383
- target,
384
- index,
385
- op,
386
- object,
387
- target_position,
388
- } => {
389
- let target = self.get_id(target).0;
390
- let index = self.prepare_expression(index)?;
391
- let object = self.prepare_expression(object)?;
392
- new_nodes.push(Node::SubscriptOpAssign {
393
- target,
394
- index,
395
- op,
396
- object,
397
- target_position,
398
- });
399
- }
400
- Node::SubscriptAssign {
401
- target,
402
- index,
403
- value,
404
- target_position,
405
- } => {
406
- // SubscriptAssign doesn't assign to the target itself, just modifies it
407
- let target = self.get_id(target).0;
408
- let index = self.prepare_expression(index)?;
409
- let value = self.prepare_expression(value)?;
410
- new_nodes.push(Node::SubscriptAssign {
411
- target,
412
- index,
413
- value,
414
- target_position,
415
- });
416
- }
417
- Node::AttrAssign {
418
- object,
419
- attr,
420
- target_position,
421
- value,
422
- } => {
423
- // AttrAssign doesn't assign to the object itself, just modifies its attribute
424
- let object = self.prepare_expression(object)?;
425
- let value = self.prepare_expression(value)?;
426
- new_nodes.push(Node::AttrAssign {
427
- object,
428
- attr,
429
- target_position,
430
- value,
431
- });
432
- }
433
- Node::For {
434
- target,
435
- iter,
436
- body,
437
- or_else,
438
- } => {
439
- // Prepare target with normal scoping (not comprehension isolation)
440
- let target = self.prepare_unpack_target(target);
441
- new_nodes.push(Node::For {
442
- target,
443
- iter: self.prepare_expression(iter)?,
444
- body: self.prepare_nodes(body)?,
445
- or_else: self.prepare_nodes(or_else)?,
446
- });
447
- }
448
- Node::Break { position } => {
449
- new_nodes.push(Node::Break { position });
450
- }
451
- Node::Continue { position } => {
452
- new_nodes.push(Node::Continue { position });
453
- }
454
- Node::While { test, body, or_else } => {
455
- new_nodes.push(Node::While {
456
- test: self.prepare_expression(test)?,
457
- body: self.prepare_nodes(body)?,
458
- or_else: self.prepare_nodes(or_else)?,
459
- });
460
- }
461
- Node::If { test, body, or_else } => {
462
- let test = self.prepare_expression(test)?;
463
- let body = self.prepare_nodes(body)?;
464
- let or_else = self.prepare_nodes(or_else)?;
465
- new_nodes.push(Node::If { test, body, or_else });
466
- }
467
- Node::FunctionDef(RawFunctionDef {
468
- name,
469
- signature,
470
- body,
471
- is_async,
472
- }) => {
473
- let func_node = self.prepare_function_def(name, &signature, body, is_async)?;
474
- new_nodes.push(func_node);
475
- }
476
- Node::Global { names, position } => {
477
- // At module level, `global` is a no-op since all variables are already global.
478
- // In functions, the global declarations are already collected in the first pass
479
- // (see prepare_function_def), so this is also a no-op at this point.
480
- // The actual effect happens in get_id where we check global_names.
481
- if !self.is_module_scope {
482
- // Validate that names weren't already used/assigned before `global` declaration
483
- for string_id in names {
484
- let name_str = self.interner.get_str(string_id);
485
- if self.names_assigned_in_order.contains(name_str) {
486
- // Name was assigned before the global declaration
487
- return Err(ParseError::syntax(
488
- format!("name '{name_str}' is assigned to before global declaration"),
489
- position,
490
- ));
491
- } else if self.name_map.contains_key(name_str) {
492
- // Name was used (but not assigned) before the global declaration
493
- return Err(ParseError::syntax(
494
- format!("name '{name_str}' is used prior to global declaration"),
495
- position,
496
- ));
497
- }
498
- }
499
- }
500
- // Global statements don't produce any runtime nodes
501
- }
502
- Node::Nonlocal { names, position } => {
503
- // Nonlocal can only be used inside a function, not at module level
504
- if self.is_module_scope {
505
- return Err(ParseError::syntax(
506
- "nonlocal declaration not allowed at module level",
507
- position,
508
- ));
509
- }
510
- // Validate that names weren't already used/assigned before `nonlocal` declaration
511
- // and that the binding exists in an enclosing scope
512
- for string_id in names {
513
- let name_str = self.interner.get_str(string_id);
514
- if self.names_assigned_in_order.contains(name_str) {
515
- // Name was assigned before the nonlocal declaration
516
- return Err(ParseError::syntax(
517
- format!("name '{name_str}' is assigned to before nonlocal declaration"),
518
- position,
519
- ));
520
- } else if self.name_map.contains_key(name_str) {
521
- // Name was used (but not assigned) before the nonlocal declaration
522
- return Err(ParseError::syntax(
523
- format!("name '{name_str}' is used prior to nonlocal declaration"),
524
- position,
525
- ));
526
- }
527
- // Validate that the binding exists in an enclosing scope
528
- if let Some(ref enclosing) = self.enclosing_locals {
529
- if !enclosing.contains(name_str) {
530
- return Err(ParseError::syntax(
531
- format!("no binding for nonlocal '{name_str}' found"),
532
- position,
533
- ));
534
- }
535
- } else {
536
- // No enclosing scope (function defined at module level)
537
- // The nonlocal must reference something in an enclosing function
538
- return Err(ParseError::syntax(
539
- format!("no binding for nonlocal '{name_str}' found"),
540
- position,
541
- ));
542
- }
543
- }
544
- // Nonlocal statements don't produce any runtime nodes
545
- }
546
- Node::Try(Try {
547
- body,
548
- handlers,
549
- or_else,
550
- finally,
551
- }) => {
552
- let body = self.prepare_nodes(body)?;
553
- let handlers = handlers
554
- .into_iter()
555
- .map(|h| self.prepare_except_handler(h))
556
- .collect::<Result<Vec<_>, _>>()?;
557
- let or_else = self.prepare_nodes(or_else)?;
558
- let finally = self.prepare_nodes(finally)?;
559
- new_nodes.push(Node::Try(Try {
560
- body,
561
- handlers,
562
- or_else,
563
- finally,
564
- }));
565
- }
566
- Node::Import { module_name, binding } => {
567
- // Resolve the binding identifier to get the namespace slot
568
- let (resolved_binding, _) = self.get_id(binding);
569
- new_nodes.push(Node::Import {
570
- module_name,
571
- binding: resolved_binding,
572
- });
573
- }
574
- Node::ImportFrom {
575
- module_name,
576
- names,
577
- position,
578
- } => {
579
- // Resolve each binding identifier to get namespace slots
580
- let resolved_names = names
581
- .into_iter()
582
- .map(|(import_name, binding)| {
583
- let (resolved_binding, _) = self.get_id(binding);
584
- (import_name, resolved_binding)
585
- })
586
- .collect();
587
- new_nodes.push(Node::ImportFrom {
588
- module_name,
589
- names: resolved_names,
590
- position,
591
- });
592
- }
593
- }
594
- }
595
- Ok(new_nodes)
596
- }
597
-
598
- /// Prepares an exception handler by resolving names in the exception type and body.
599
- ///
600
- /// The exception variable (if present) is treated as an assigned name in the current scope.
601
- fn prepare_except_handler(
602
- &mut self,
603
- handler: ExceptHandler<ParseNode>,
604
- ) -> Result<ExceptHandler<PreparedNode>, ParseError> {
605
- let exc_type = match handler.exc_type {
606
- Some(expr) => Some(self.prepare_expression(expr)?),
607
- None => None,
608
- };
609
- // The exception variable binding (e.g., `as e:`) is an assignment
610
- let name = match handler.name {
611
- Some(ident) => {
612
- // Track that this name was assigned
613
- self.names_assigned_in_order
614
- .insert(self.interner.get_str(ident.name_id).to_string());
615
- Some(self.get_id(ident).0)
616
- }
617
- None => None,
618
- };
619
- let body = self.prepare_nodes(handler.body)?;
620
- Ok(ExceptHandler { exc_type, name, body })
621
- }
622
-
623
- /// Prepares an expression by resolving names, transforming calls, and applying optimizations.
624
- ///
625
- /// Key transformations performed:
626
- /// - Name lookups are resolved to namespace indices via `get_id`
627
- /// - Function calls are resolved from identifiers to builtin types
628
- /// - Attribute calls validate that the object is already defined (not a new name)
629
- /// - Lists and tuples are recursively prepared
630
- /// - Modulo equality patterns like `x % n == k` (constant right-hand side) are optimized to
631
- /// `CmpOperator::ModEq`
632
- ///
633
- /// # Errors
634
- /// Returns a NameError if an attribute call references an undefined variable
635
- fn prepare_expression(&mut self, loc_expr: ExprLoc) -> Result<ExprLoc, ParseError> {
636
- let ExprLoc { position, expr } = loc_expr;
637
- let expr = match expr {
638
- Expr::Literal(object) => Expr::Literal(object),
639
- Expr::Builtin(callable) => Expr::Builtin(callable),
640
- Expr::Name(name) => self.resolve_name_or_builtin(name),
641
- Expr::Op { left, op, right } => Expr::Op {
642
- left: Box::new(self.prepare_expression(*left)?),
643
- op,
644
- right: Box::new(self.prepare_expression(*right)?),
645
- },
646
- Expr::CmpOp { left, op, right } => Expr::CmpOp {
647
- left: Box::new(self.prepare_expression(*left)?),
648
- op,
649
- right: Box::new(self.prepare_expression(*right)?),
650
- },
651
- Expr::ChainCmp { left, comparisons } => Expr::ChainCmp {
652
- left: Box::new(self.prepare_expression(*left)?),
653
- comparisons: comparisons
654
- .into_iter()
655
- .map(|(op, expr)| Ok((op, self.prepare_expression(expr)?)))
656
- .collect::<Result<Vec<_>, _>>()?,
657
- },
658
- Expr::Call { callable, mut args } => {
659
- // Prepare the arguments
660
- args.prepare_args(|expr| self.prepare_expression(expr))?;
661
- // For Name callables, resolve the identifier in the namespace
662
- // Don't error here if undefined - let runtime raise NameError with proper traceback
663
- let callable = match callable {
664
- Callable::Name(ident) => match self.resolve_name_or_builtin(ident) {
665
- Expr::Builtin(b) => Callable::Builtin(b),
666
- Expr::Name(resolved) => Callable::Name(resolved),
667
- _ => unreachable!("resolve_name_or_builtin returns Name or Builtin"),
668
- },
669
- other @ Callable::Builtin(_) => other,
670
- };
671
- Expr::Call { callable, args }
672
- }
673
- Expr::AttrCall { object, attr, mut args } => {
674
- // Prepare the object expression (supports chained access like a.b.c.method())
675
- let object = Box::new(self.prepare_expression(*object)?);
676
- args.prepare_args(|expr| self.prepare_expression(expr))?;
677
- Expr::AttrCall { object, attr, args }
678
- }
679
- Expr::IndirectCall { callable, mut args } => {
680
- // Prepare the callable expression (e.g., lambda or any expression returning a callable)
681
- let callable = Box::new(self.prepare_expression(*callable)?);
682
- args.prepare_args(|expr| self.prepare_expression(expr))?;
683
- Expr::IndirectCall { callable, args }
684
- }
685
- Expr::AttrGet { object, attr } => {
686
- // Prepare the object expression (supports chained access like a.b.c)
687
- let object = Box::new(self.prepare_expression(*object)?);
688
- Expr::AttrGet { object, attr }
689
- }
690
- Expr::List(elements) => {
691
- let items = elements
692
- .into_iter()
693
- .map(|item| self.prepare_sequence_item(item))
694
- .collect::<Result<_, ParseError>>()?;
695
- Expr::List(items)
696
- }
697
- Expr::Tuple(elements) => {
698
- let items = elements
699
- .into_iter()
700
- .map(|item| self.prepare_sequence_item(item))
701
- .collect::<Result<_, ParseError>>()?;
702
- Expr::Tuple(items)
703
- }
704
- Expr::Subscript { object, index } => Expr::Subscript {
705
- object: Box::new(self.prepare_expression(*object)?),
706
- index: Box::new(self.prepare_expression(*index)?),
707
- },
708
- Expr::Dict(dict_items) => {
709
- let prepared = dict_items
710
- .into_iter()
711
- .map(|item| match item {
712
- DictItem::Pair(k, v) => {
713
- Ok(DictItem::Pair(self.prepare_expression(k)?, self.prepare_expression(v)?))
714
- }
715
- DictItem::Unpack(e) => Ok(DictItem::Unpack(self.prepare_expression(e)?)),
716
- })
717
- .collect::<Result<_, ParseError>>()?;
718
- Expr::Dict(prepared)
719
- }
720
- Expr::Set(elements) => {
721
- let items = elements
722
- .into_iter()
723
- .map(|item| self.prepare_sequence_item(item))
724
- .collect::<Result<_, ParseError>>()?;
725
- Expr::Set(items)
726
- }
727
- Expr::Not(operand) => Expr::Not(Box::new(self.prepare_expression(*operand)?)),
728
- Expr::UnaryMinus(operand) => Expr::UnaryMinus(Box::new(self.prepare_expression(*operand)?)),
729
- Expr::UnaryPlus(operand) => Expr::UnaryPlus(Box::new(self.prepare_expression(*operand)?)),
730
- Expr::UnaryInvert(operand) => Expr::UnaryInvert(Box::new(self.prepare_expression(*operand)?)),
731
- Expr::FString(parts) => {
732
- let prepared_parts = parts
733
- .into_iter()
734
- .map(|part| self.prepare_fstring_part(part))
735
- .collect::<Result<Vec<_>, ParseError>>()?;
736
- Expr::FString(prepared_parts)
737
- }
738
- Expr::IfElse { test, body, orelse } => Expr::IfElse {
739
- test: Box::new(self.prepare_expression(*test)?),
740
- body: Box::new(self.prepare_expression(*body)?),
741
- orelse: Box::new(self.prepare_expression(*orelse)?),
742
- },
743
- Expr::ListComp { elt, generators } => {
744
- let (generators, elt, _) = self.prepare_comprehension(generators, Some(*elt), None)?;
745
- Expr::ListComp {
746
- elt: Box::new(elt.expect("list comp must have elt")),
747
- generators,
748
- }
749
- }
750
- Expr::SetComp { elt, generators } => {
751
- let (generators, elt, _) = self.prepare_comprehension(generators, Some(*elt), None)?;
752
- Expr::SetComp {
753
- elt: Box::new(elt.expect("set comp must have elt")),
754
- generators,
755
- }
756
- }
757
- Expr::DictComp { key, value, generators } => {
758
- let (generators, _, key_value) = self.prepare_comprehension(generators, None, Some((*key, *value)))?;
759
- let (key, value) = key_value.expect("dict comp must have key/value");
760
- Expr::DictComp {
761
- key: Box::new(key),
762
- value: Box::new(value),
763
- generators,
764
- }
765
- }
766
- Expr::LambdaRaw {
767
- name_id,
768
- signature,
769
- body,
770
- } => {
771
- // Convert the raw lambda into a prepared lambda expression
772
- return self.prepare_lambda(name_id, &signature, &body, position);
773
- }
774
- Expr::Lambda { .. } => {
775
- // Lambda should only be created during prepare, never during parsing
776
- unreachable!("Expr::Lambda should not exist before prepare phase")
777
- }
778
- Expr::Slice { lower, upper, step } => Expr::Slice {
779
- lower: lower.map(|e| self.prepare_expression(*e)).transpose()?.map(Box::new),
780
- upper: upper.map(|e| self.prepare_expression(*e)).transpose()?.map(Box::new),
781
- step: step.map(|e| self.prepare_expression(*e)).transpose()?.map(Box::new),
782
- },
783
- Expr::Named { target, value } => {
784
- let value = Box::new(self.prepare_expression(*value)?);
785
- // Register the target as assigned in this scope
786
- self.names_assigned_in_order
787
- .insert(self.interner.get_str(target.name_id).to_string());
788
- let (resolved_target, _) = self.get_id(target);
789
- Expr::Named {
790
- target: resolved_target,
791
- value,
792
- }
793
- }
794
- Expr::Await(value) => Expr::Await(Box::new(self.prepare_expression(*value)?)),
795
- };
796
-
797
- // Optimization: Transform `(x % n) == value` with any constant right-hand side into a
798
- // specialized ModEq operator.
799
- // This is a common pattern in competitive programming (e.g., FizzBuzz checks like `i % 3 == 0`)
800
- // and can be executed more efficiently with a single modulo operation + comparison
801
- // instead of separate modulo, then equality check.
802
- if let Expr::CmpOp { left, op, right } = &expr
803
- && op == &CmpOperator::Eq
804
- && let Expr::Literal(Literal::Int(value)) = right.expr
805
- && let Expr::Op {
806
- left: left2,
807
- op,
808
- right: right2,
809
- } = &left.expr
810
- && op == &Operator::Mod
811
- {
812
- let new_expr = Expr::CmpOp {
813
- left: left2.clone(),
814
- op: CmpOperator::ModEq(value),
815
- right: right2.clone(),
816
- };
817
- return Ok(ExprLoc {
818
- position: left.position,
819
- expr: new_expr,
820
- });
821
- }
822
-
823
- Ok(ExprLoc { position, expr })
824
- }
825
-
826
- /// Resolves a name to either `Expr::Builtin` or `Expr::Name` with scope-aware builtin detection.
827
- ///
828
- /// Python's name resolution follows LEGB order (Local, Enclosing, Global, Builtin).
829
- /// Builtins are only used when the name is not found in any other scope. This method
830
- /// ensures that local assignments (e.g., `int = 42`) properly shadow builtin names.
831
- ///
832
- /// We check before calling `get_id` to avoid allocating unnecessary namespace slots.
833
- /// At module level, a slot allocated for an unassigned builtin would leak into
834
- /// `global_name_map` for nested functions, causing incorrect resolution.
835
- fn resolve_name_or_builtin(&mut self, name: Identifier) -> Expr {
836
- let name_str = self.interner.get_str(name.name_id);
837
-
838
- // Check if the name is assigned in the current scope. If so, it shadows
839
- // any builtin with the same name.
840
- let is_locally_assigned = if self.is_module_scope {
841
- // Module scope: sequential — only names assigned SO FAR shadow builtins
842
- self.names_assigned_in_order.contains(name_str)
843
- } else {
844
- // Function scope: lexical — ANY assignment in the function body makes
845
- // the name local for the entire function
846
- self.assigned_names.contains(name_str)
847
- };
848
-
849
- if !is_locally_assigned {
850
- // In function scope, also check if the name is bound by other mechanisms
851
- // (global declaration, parameter, closure capture, enclosing/global scope).
852
- // Only fall back to builtins if the name is truly unresolved.
853
- let is_otherwise_bound = !self.is_module_scope
854
- && (self.global_names.contains(name_str)
855
- || self.free_var_map.contains_key(name_str)
856
- || self.cell_var_map.contains_key(name_str)
857
- || self.name_map.contains_key(name_str)
858
- || self.enclosing_locals.as_ref().is_some_and(|l| l.contains(name_str))
859
- || self.global_name_map.as_ref().is_some_and(|m| m.contains_key(name_str)));
860
-
861
- if !is_otherwise_bound && let Ok(builtin) = name_str.parse::<Builtins>() {
862
- return Expr::Builtin(builtin);
863
- }
864
- }
865
-
866
- Expr::Name(self.get_id(name).0)
867
- }
868
-
869
- /// Prepares a `SequenceItem` by recursively preparing its inner expression.
870
- ///
871
- /// Both `Value` and `Unpack` variants need their expressions prepared
872
- /// (name resolution, scope analysis, builtin detection, etc.).
873
- fn prepare_sequence_item(&mut self, item: SequenceItem) -> Result<SequenceItem, ParseError> {
874
- match item {
875
- SequenceItem::Value(e) => Ok(SequenceItem::Value(self.prepare_expression(e)?)),
876
- SequenceItem::Unpack(e) => Ok(SequenceItem::Unpack(self.prepare_expression(e)?)),
877
- }
878
- }
879
-
880
- /// Prepares a comprehension with scope isolation for loop variables.
881
- ///
882
- /// Comprehension loop variables are isolated from the enclosing scope - they do not
883
- /// leak after the comprehension completes. CPython scoping rules require:
884
- ///
885
- /// 1. The FIRST generator's iter is evaluated in the enclosing scope
886
- /// 2. ALL loop variables from ALL generators are then shadowed as local
887
- /// 3. Subsequent generators' iters see all loop vars as local (even if unassigned)
888
- ///
889
- /// This means `[y for x in [1] for y in z for z in [[2]]]` raises UnboundLocalError
890
- /// because `z` is treated as local (it's a loop var in generator 3) when evaluating
891
- /// generator 2's iter.
892
- ///
893
- /// For list/set comprehensions, pass `elt` as Some and `key_value` as None.
894
- /// For dict comprehensions, pass `elt` as None and `key_value` as Some((key, value)).
895
- #[expect(clippy::type_complexity)]
896
- fn prepare_comprehension(
897
- &mut self,
898
- generators: Vec<Comprehension>,
899
- elt: Option<ExprLoc>,
900
- key_value: Option<(ExprLoc, ExprLoc)>,
901
- ) -> Result<(Vec<Comprehension>, Option<ExprLoc>, Option<(ExprLoc, ExprLoc)>), ParseError> {
902
- // Per PEP 572, walrus operators inside comprehensions bind in the ENCLOSING scope.
903
- // Pre-register walrus targets before saving scope state, so they persist after restore.
904
- let mut walrus_targets: AHashSet<String> = AHashSet::new();
905
- if let Some(ref e) = elt {
906
- collect_assigned_names_from_expr(e, &mut walrus_targets, self.interner);
907
- }
908
- if let Some((ref k, ref v)) = key_value {
909
- collect_assigned_names_from_expr(k, &mut walrus_targets, self.interner);
910
- collect_assigned_names_from_expr(v, &mut walrus_targets, self.interner);
911
- }
912
- for generator in &generators {
913
- // Note: we don't scan iter expressions here because walrus in iterable is not allowed
914
- for cond in &generator.ifs {
915
- collect_assigned_names_from_expr(cond, &mut walrus_targets, self.interner);
916
- }
917
- }
918
- // Pre-allocate slots for walrus targets in the enclosing scope
919
- for name in &walrus_targets {
920
- if !self.name_map.contains_key(name) {
921
- let slot = NamespaceId::new(self.namespace_size);
922
- self.namespace_size += 1;
923
- self.name_map.insert(name.clone(), slot);
924
- self.names_assigned_in_order.insert(name.clone());
925
- }
926
- }
927
-
928
- // Save current scope state for isolation
929
- let saved_name_map = self.name_map.clone();
930
- let saved_assigned_names = self.names_assigned_in_order.clone();
931
- let saved_free_var_map = self.free_var_map.clone();
932
- let saved_cell_var_map = self.cell_var_map.clone();
933
- let saved_enclosing_locals = self.enclosing_locals.clone();
934
- let saved_unassigned_ref_names = self.unassigned_ref_names.clone();
935
-
936
- // Step 1: Prepare first generator's iter in enclosing scope (before any shadowing)
937
- let mut generators_iter = generators.into_iter();
938
- let first_gen = generators_iter
939
- .next()
940
- .expect("comprehension must have at least one generator");
941
- let first_iter = self.prepare_expression(first_gen.iter)?;
942
-
943
- // Step 2: Collect and shadow ALL loop variable names from ALL generators.
944
- // This must happen BEFORE evaluating any subsequent generator's iter expression.
945
- // We allocate slots but don't mark them as "assigned" yet - this causes
946
- // UnboundLocalError if a later generator's iter references an earlier-declared
947
- // but not-yet-assigned loop variable.
948
- let first_target = self.prepare_unpack_target_for_comprehension(first_gen.target);
949
-
950
- // Collect remaining generators so we can pre-shadow their targets
951
- let remaining_gens: Vec<Comprehension> = generators_iter.collect();
952
-
953
- // Pre-shadow ALL remaining loop variables before evaluating their iters.
954
- // This is the key CPython behavior: all loop vars are local to the comprehension,
955
- // so referencing a later loop var in an earlier iter raises UnboundLocalError.
956
- let mut preshadowed_targets: Vec<UnpackTarget> = Vec::with_capacity(remaining_gens.len());
957
- for generator in &remaining_gens {
958
- preshadowed_targets.push(self.prepare_unpack_target_shadow_only(generator.target.clone()));
959
- }
960
-
961
- // Prepare first generator's filters (can see first loop variable)
962
- let first_ifs = first_gen
963
- .ifs
964
- .into_iter()
965
- .map(|cond| self.prepare_expression(cond))
966
- .collect::<Result<Vec<_>, _>>()?;
967
-
968
- let mut prepared_generators = Vec::with_capacity(1 + remaining_gens.len());
969
- prepared_generators.push(Comprehension {
970
- target: first_target,
971
- iter: first_iter,
972
- ifs: first_ifs,
973
- });
974
-
975
- // Step 3: Process remaining generators - their iters now see all loop vars as local
976
- for (generator, preshadowed_target) in remaining_gens.into_iter().zip(preshadowed_targets) {
977
- let iter = self.prepare_expression(generator.iter)?;
978
- let ifs = generator
979
- .ifs
980
- .into_iter()
981
- .map(|cond| self.prepare_expression(cond))
982
- .collect::<Result<Vec<_>, _>>()?;
983
-
984
- prepared_generators.push(Comprehension {
985
- target: preshadowed_target,
986
- iter,
987
- ifs,
988
- });
989
- }
990
-
991
- // Prepare the element expression(s) - can see all loop variables
992
- let prepared_elt = match elt {
993
- Some(e) => Some(self.prepare_expression(e)?),
994
- None => None,
995
- };
996
- let prepared_key_value = match key_value {
997
- Some((k, v)) => Some((self.prepare_expression(k)?, self.prepare_expression(v)?)),
998
- None => None,
999
- };
1000
-
1001
- // Restore scope state - loop variables do not leak to enclosing scope
1002
- self.name_map = saved_name_map;
1003
- self.names_assigned_in_order = saved_assigned_names;
1004
- self.free_var_map = saved_free_var_map;
1005
- self.cell_var_map = saved_cell_var_map;
1006
- self.enclosing_locals = saved_enclosing_locals;
1007
- self.unassigned_ref_names = saved_unassigned_ref_names;
1008
-
1009
- Ok((prepared_generators, prepared_elt, prepared_key_value))
1010
- }
1011
-
1012
- /// Prepares an unpack target by resolving identifiers recursively.
1013
- ///
1014
- /// Handles both single identifiers and nested tuples like `(a, b), c`.
1015
- fn prepare_unpack_target(&mut self, target: UnpackTarget) -> UnpackTarget {
1016
- match target {
1017
- UnpackTarget::Name(ident) => {
1018
- self.names_assigned_in_order
1019
- .insert(self.interner.get_str(ident.name_id).to_string());
1020
- UnpackTarget::Name(self.get_id(ident).0)
1021
- }
1022
- UnpackTarget::Starred(ident) => {
1023
- self.names_assigned_in_order
1024
- .insert(self.interner.get_str(ident.name_id).to_string());
1025
- UnpackTarget::Starred(self.get_id(ident).0)
1026
- }
1027
- UnpackTarget::Tuple { targets, position } => {
1028
- let resolved_targets: Vec<UnpackTarget> = targets
1029
- .into_iter()
1030
- .map(|t| self.prepare_unpack_target(t)) // Recursive call
1031
- .collect();
1032
- UnpackTarget::Tuple {
1033
- targets: resolved_targets,
1034
- position,
1035
- }
1036
- }
1037
- }
1038
- }
1039
-
1040
- /// Prepares an unpack target for comprehension by allocating fresh namespace slots.
1041
- ///
1042
- /// Unlike regular unpack targets, comprehension targets need new slots to shadow
1043
- /// any existing bindings with the same name.
1044
- fn prepare_unpack_target_for_comprehension(&mut self, target: UnpackTarget) -> UnpackTarget {
1045
- match target {
1046
- UnpackTarget::Name(ident) => {
1047
- let name_str = self.interner.get_str(ident.name_id).to_string();
1048
- let comp_var_id = NamespaceId::new(self.namespace_size);
1049
- self.namespace_size += 1;
1050
-
1051
- // Shadow any existing binding
1052
- self.shadow_for_comprehension(&name_str, comp_var_id);
1053
-
1054
- UnpackTarget::Name(Identifier::new_with_scope(
1055
- ident.name_id,
1056
- ident.position,
1057
- comp_var_id,
1058
- NameScope::Local,
1059
- ))
1060
- }
1061
- UnpackTarget::Starred(ident) => {
1062
- let name_str = self.interner.get_str(ident.name_id).to_string();
1063
- let comp_var_id = NamespaceId::new(self.namespace_size);
1064
- self.namespace_size += 1;
1065
-
1066
- // Shadow any existing binding
1067
- self.shadow_for_comprehension(&name_str, comp_var_id);
1068
-
1069
- UnpackTarget::Starred(Identifier::new_with_scope(
1070
- ident.name_id,
1071
- ident.position,
1072
- comp_var_id,
1073
- NameScope::Local,
1074
- ))
1075
- }
1076
- UnpackTarget::Tuple { targets, position } => {
1077
- let resolved_targets: Vec<UnpackTarget> = targets
1078
- .into_iter()
1079
- .map(|t| self.prepare_unpack_target_for_comprehension(t)) // Recursive call
1080
- .collect();
1081
- UnpackTarget::Tuple {
1082
- targets: resolved_targets,
1083
- position,
1084
- }
1085
- }
1086
- }
1087
- }
1088
-
1089
- /// Pre-shadows an unpack target for comprehension scoping.
1090
- ///
1091
- /// Allocates namespace slots without marking as assigned, causing UnboundLocalError
1092
- /// if accessed before assignment.
1093
- fn prepare_unpack_target_shadow_only(&mut self, target: UnpackTarget) -> UnpackTarget {
1094
- match target {
1095
- UnpackTarget::Name(ident) => {
1096
- let name_str = self.interner.get_str(ident.name_id).to_string();
1097
- let comp_var_id = NamespaceId::new(self.namespace_size);
1098
- self.namespace_size += 1;
1099
-
1100
- // Shadow but do NOT add to names_assigned_in_order yet
1101
- self.name_map.insert(name_str.clone(), comp_var_id);
1102
- self.free_var_map.remove(&name_str);
1103
- self.cell_var_map.remove(&name_str);
1104
- if let Some(ref mut enclosing) = self.enclosing_locals {
1105
- enclosing.remove(&name_str);
1106
- }
1107
-
1108
- UnpackTarget::Name(Identifier::new_with_scope(
1109
- ident.name_id,
1110
- ident.position,
1111
- comp_var_id,
1112
- NameScope::Local,
1113
- ))
1114
- }
1115
- UnpackTarget::Starred(ident) => {
1116
- let name_str = self.interner.get_str(ident.name_id).to_string();
1117
- let comp_var_id = NamespaceId::new(self.namespace_size);
1118
- self.namespace_size += 1;
1119
-
1120
- // Shadow but do NOT add to names_assigned_in_order yet
1121
- self.name_map.insert(name_str.clone(), comp_var_id);
1122
- self.free_var_map.remove(&name_str);
1123
- self.cell_var_map.remove(&name_str);
1124
- if let Some(ref mut enclosing) = self.enclosing_locals {
1125
- enclosing.remove(&name_str);
1126
- }
1127
-
1128
- UnpackTarget::Starred(Identifier::new_with_scope(
1129
- ident.name_id,
1130
- ident.position,
1131
- comp_var_id,
1132
- NameScope::Local,
1133
- ))
1134
- }
1135
- UnpackTarget::Tuple { targets, position } => {
1136
- let resolved_targets: Vec<UnpackTarget> = targets
1137
- .into_iter()
1138
- .map(|t| self.prepare_unpack_target_shadow_only(t)) // Recursive call
1139
- .collect();
1140
- UnpackTarget::Tuple {
1141
- targets: resolved_targets,
1142
- position,
1143
- }
1144
- }
1145
- }
1146
- }
1147
-
1148
- /// Shadows a name in all scope maps for comprehension isolation.
1149
- ///
1150
- /// This ensures the comprehension loop variable takes precedence over any
1151
- /// variable with the same name from enclosing scopes.
1152
- fn shadow_for_comprehension(&mut self, name_str: &str, comp_var_id: NamespaceId) {
1153
- // The lookup order in get_id is: global_declarations, free_var_map, cell_var_map,
1154
- // assigned_names, enclosing_locals, then name_map. So we must update/remove from all maps
1155
- // checked before name_map to ensure the comprehension variable shadows any captured
1156
- // variable with the same name.
1157
- self.name_map.insert(name_str.to_string(), comp_var_id);
1158
- self.names_assigned_in_order.insert(name_str.to_string());
1159
- self.free_var_map.remove(name_str);
1160
- self.cell_var_map.remove(name_str);
1161
- // Also remove from enclosing_locals to prevent get_id from re-capturing the variable
1162
- if let Some(ref mut enclosing) = self.enclosing_locals {
1163
- enclosing.remove(name_str);
1164
- }
1165
- }
1166
-
1167
- /// Prepares a function definition using a two-pass approach for correct scope resolution.
1168
- ///
1169
- /// Pass 1: Scan the function body to collect:
1170
- /// - Names declared as `global`
1171
- /// - Names declared as `nonlocal`
1172
- /// - Names that are assigned (these are local unless declared global/nonlocal)
1173
- ///
1174
- /// Pass 2: Prepare the function body with the scope information from pass 1.
1175
- ///
1176
- /// # Closure Analysis
1177
- ///
1178
- /// When the nested function uses `nonlocal` declarations, those names must exist
1179
- /// in an enclosing scope. The enclosing scope's variable becomes a cell_var
1180
- /// (stored in a heap cell), and the nested function captures it as a free_var.
1181
- fn prepare_function_def(
1182
- &mut self,
1183
- name: Identifier,
1184
- parsed_sig: &ParsedSignature,
1185
- body: Vec<ParseNode>,
1186
- is_async: bool,
1187
- ) -> Result<PreparedNode, ParseError> {
1188
- // Register the function name in the current scope
1189
- let (name, _) = self.get_id(name);
1190
-
1191
- // Extract param names from the parsed signature for scope analysis
1192
- let param_names: Vec<StringId> = parsed_sig.param_names().collect();
1193
-
1194
- // Pass 1: Collect scope information from the function body
1195
- let scope_info = collect_function_scope_info(&body, &param_names, self.interner);
1196
-
1197
- // Get the global name map to pass to the function preparer
1198
- // At module level, use our own name_map; otherwise use the inherited global_name_map
1199
- let global_name_map = if self.is_module_scope {
1200
- self.name_map.clone()
1201
- } else {
1202
- self.global_name_map.clone().unwrap_or_default()
1203
- };
1204
-
1205
- // Build enclosing_locals: names that are local to this scope (including params)
1206
- // These are available for `nonlocal` declarations in nested functions
1207
- let enclosing_locals: AHashSet<String> = if self.is_module_scope {
1208
- // At module level, there are no enclosing locals for nonlocal
1209
- // (module-level variables are accessed via `global`, not `nonlocal`)
1210
- AHashSet::new()
1211
- } else {
1212
- // In a function: our params + assigned_names + existing name_map keys
1213
- // are all potentially available as enclosing locals
1214
- let mut locals = self.assigned_names.clone();
1215
- for key in self.name_map.keys() {
1216
- locals.insert(key.clone());
1217
- }
1218
- locals
1219
- };
1220
-
1221
- // Filter potential_captures to get actual implicit captures.
1222
- // Only names that are ALSO in enclosing_locals are true implicit captures.
1223
- // Names NOT in enclosing_locals are either builtins or globals (handled at runtime).
1224
- let implicit_captures: AHashSet<String> = scope_info
1225
- .potential_captures
1226
- .into_iter()
1227
- .filter(|name| enclosing_locals.contains(name))
1228
- .collect();
1229
-
1230
- // Pass 2: Create child preparer for function body with scope info
1231
- let mut inner_prepare = Prepare::new_function(
1232
- body.len(),
1233
- &param_names,
1234
- scope_info.assigned_names,
1235
- scope_info.global_names,
1236
- scope_info.nonlocal_names,
1237
- implicit_captures,
1238
- global_name_map,
1239
- Some(enclosing_locals),
1240
- scope_info.cell_var_names,
1241
- self.interner,
1242
- );
1243
-
1244
- // Prepare the function body
1245
- let prepared_body = inner_prepare.prepare_nodes(body)?;
1246
-
1247
- // Mark variables that the inner function captures as our cell_vars
1248
- // These are the names that appear in inner_prepare.free_var_map
1249
- // Add to cell_var_map if not already present (may have been pre-populated or added earlier)
1250
- for captured_name in inner_prepare.free_var_map.keys() {
1251
- if !self.cell_var_map.contains_key(captured_name) && !self.free_var_map.contains_key(captured_name) {
1252
- // Only add to cell_var_map if not already a free_var (pass-through case)
1253
- // Allocate a namespace slot for the cell reference
1254
- let slot = match self.name_map.entry(captured_name.clone()) {
1255
- Entry::Occupied(e) => *e.get(),
1256
- Entry::Vacant(e) => {
1257
- let slot = NamespaceId::new(self.namespace_size);
1258
- self.namespace_size += 1;
1259
- e.insert(slot);
1260
- slot
1261
- }
1262
- };
1263
- self.cell_var_map.insert(captured_name.clone(), slot);
1264
- }
1265
- }
1266
-
1267
- // Build free_var_enclosing_slots: enclosing namespace slots for captured variables
1268
- // At call time, cells are pushed sequentially, so we only need the enclosing slots.
1269
- // Sort by our slot index to ensure consistent ordering (matches namespace layout).
1270
- let mut free_var_entries: Vec<_> = inner_prepare.free_var_map.into_iter().collect();
1271
- free_var_entries.sort_by_key(|(_, our_slot)| *our_slot);
1272
-
1273
- let free_var_enclosing_slots: Vec<NamespaceId> = free_var_entries
1274
- .into_iter()
1275
- .map(|(var_name, _our_slot)| {
1276
- // Determine the namespace slot in the enclosing scope where the cell reference lives:
1277
- // - If it's in cell_var_map, it's a cell we own (allocated in this scope)
1278
- // - If it's in free_var_map, it's a cell we captured from further up
1279
- // - Otherwise, this is a prepare-time bug
1280
- if let Some(&slot) = self.cell_var_map.get(&var_name) {
1281
- slot
1282
- } else if let Some(&slot) = self.free_var_map.get(&var_name) {
1283
- slot
1284
- } else {
1285
- panic!("free_var '{var_name}' not found in enclosing scope's cell_var_map or free_var_map");
1286
- }
1287
- })
1288
- .collect();
1289
-
1290
- // cell_var_count: number of cells to create at call time for variables captured by nested functions
1291
- // Slots are implicitly params.len()..params.len()+cell_var_count in the namespace layout
1292
- let cell_var_count = inner_prepare.cell_var_map.len();
1293
- let namespace_size = inner_prepare.namespace_size;
1294
-
1295
- // Build cell_param_indices: maps cell indices to parameter indices for captured parameters.
1296
- // When a parameter is captured by a nested function, we need to copy its value into the cell.
1297
- let cell_param_indices: Vec<Option<usize>> = if cell_var_count == 0 {
1298
- Vec::new()
1299
- } else {
1300
- // Build a map from param name (String) to param index
1301
- let param_name_to_index: AHashMap<String, usize> = param_names
1302
- .iter()
1303
- .enumerate()
1304
- .map(|(idx, &name_id)| (self.interner.get_str(name_id).to_string(), idx))
1305
- .collect();
1306
-
1307
- // Sort cell_var_map entries by slot to get cells in order
1308
- let mut cell_entries: Vec<_> = inner_prepare.cell_var_map.iter().collect();
1309
- cell_entries.sort_by_key(|&(_, slot)| slot);
1310
-
1311
- // For each cell (in slot order), check if it's a parameter
1312
- cell_entries
1313
- .into_iter()
1314
- .map(|(name, _slot)| param_name_to_index.get(name).copied())
1315
- .collect()
1316
- };
1317
-
1318
- // Build the runtime Signature from the parsed signature
1319
- let pos_args: Vec<StringId> = parsed_sig.pos_args.iter().map(|p| p.name).collect();
1320
- let pos_defaults_count = parsed_sig.pos_args.iter().filter(|p| p.default.is_some()).count();
1321
- let args: Vec<StringId> = parsed_sig.args.iter().map(|p| p.name).collect();
1322
- let arg_defaults_count = parsed_sig.args.iter().filter(|p| p.default.is_some()).count();
1323
- let mut kwargs: Vec<StringId> = Vec::with_capacity(parsed_sig.kwargs.len());
1324
- let mut kwarg_default_map: Vec<Option<usize>> = Vec::with_capacity(parsed_sig.kwargs.len());
1325
- let mut kwarg_default_index = 0;
1326
- for param in &parsed_sig.kwargs {
1327
- kwargs.push(param.name);
1328
- if param.default.is_some() {
1329
- kwarg_default_map.push(Some(kwarg_default_index));
1330
- kwarg_default_index += 1;
1331
- } else {
1332
- kwarg_default_map.push(None);
1333
- }
1334
- }
1335
-
1336
- let signature = Signature::new(
1337
- pos_args,
1338
- pos_defaults_count,
1339
- args,
1340
- arg_defaults_count,
1341
- parsed_sig.var_args,
1342
- kwargs,
1343
- kwarg_default_map,
1344
- parsed_sig.var_kwargs,
1345
- );
1346
-
1347
- // Collect and prepare default expressions in order: pos_args -> args -> kwargs
1348
- // Only includes parameters that actually have defaults.
1349
- let mut default_exprs = Vec::with_capacity(signature.total_defaults_count());
1350
- for param in &parsed_sig.pos_args {
1351
- if let Some(ref expr) = param.default {
1352
- default_exprs.push(self.prepare_expression(expr.clone())?);
1353
- }
1354
- }
1355
- for param in &parsed_sig.args {
1356
- if let Some(ref expr) = param.default {
1357
- default_exprs.push(self.prepare_expression(expr.clone())?);
1358
- }
1359
- }
1360
- for param in &parsed_sig.kwargs {
1361
- if let Some(ref expr) = param.default {
1362
- default_exprs.push(self.prepare_expression(expr.clone())?);
1363
- }
1364
- }
1365
-
1366
- // Return the prepared function definition inline in the AST
1367
- Ok(Node::FunctionDef(PreparedFunctionDef {
1368
- name,
1369
- signature,
1370
- body: prepared_body,
1371
- namespace_size,
1372
- free_var_enclosing_slots,
1373
- cell_var_count,
1374
- cell_param_indices,
1375
- default_exprs,
1376
- is_async,
1377
- }))
1378
- }
1379
-
1380
- /// Prepares a lambda expression, converting it into a prepared function definition.
1381
- ///
1382
- /// Lambdas are essentially anonymous functions with an implicit return of their body
1383
- /// expression. This method follows the same preparation logic as `prepare_function_def`
1384
- /// but:
1385
- /// - Uses `<lambda>` as the function name (not registered in scope)
1386
- /// - Wraps the body expression as `Node::Return(body)`
1387
- /// - Returns `ExprLoc` with `Expr::Lambda` instead of `PreparedNode`
1388
- fn prepare_lambda(
1389
- &mut self,
1390
- lambda_name_id: StringId,
1391
- parsed_sig: &ParsedSignature,
1392
- body: &ExprLoc,
1393
- position: CodeRange,
1394
- ) -> Result<ExprLoc, ParseError> {
1395
- // Create a synthetic <lambda> name identifier (not registered in scope)
1396
- let lambda_name = Identifier::new_with_scope(
1397
- lambda_name_id,
1398
- position,
1399
- NamespaceId::new(0), // Placeholder, not actually used for storage
1400
- NameScope::Local,
1401
- );
1402
-
1403
- // Wrap the body expression as a return statement for scope analysis
1404
- let body_as_node: ParseNode = Node::Return(body.clone());
1405
- let body_nodes = vec![body_as_node];
1406
-
1407
- // Extract param names from the parsed signature for scope analysis
1408
- let param_names: Vec<StringId> = parsed_sig.param_names().collect();
1409
-
1410
- // Pass 1: Collect scope information from the lambda body
1411
- // (Lambdas can't have global/nonlocal declarations, but can have nested functions)
1412
- let scope_info = collect_function_scope_info(&body_nodes, &param_names, self.interner);
1413
-
1414
- // Get the global name map to pass to the function preparer
1415
- let global_name_map = if self.is_module_scope {
1416
- self.name_map.clone()
1417
- } else {
1418
- self.global_name_map.clone().unwrap_or_default()
1419
- };
1420
-
1421
- // Build enclosing_locals: names that are local to this scope or captured from enclosing scope.
1422
- // This includes free_vars so that nested lambdas can capture pass-through variables.
1423
- let enclosing_locals: AHashSet<String> = if self.is_module_scope {
1424
- AHashSet::new()
1425
- } else {
1426
- let mut locals = self.assigned_names.clone();
1427
- for key in self.name_map.keys() {
1428
- locals.insert(key.clone());
1429
- }
1430
- // Include free_vars so nested functions/lambdas can capture pass-through variables
1431
- for key in self.free_var_map.keys() {
1432
- locals.insert(key.clone());
1433
- }
1434
- locals
1435
- };
1436
-
1437
- // Filter potential_captures to get actual implicit captures
1438
- let implicit_captures: AHashSet<String> = scope_info
1439
- .potential_captures
1440
- .into_iter()
1441
- .filter(|name| enclosing_locals.contains(name))
1442
- .collect();
1443
-
1444
- // Pass 2: Create child preparer for lambda body with scope info
1445
- let mut inner_prepare = Prepare::new_function(
1446
- body_nodes.len(),
1447
- &param_names,
1448
- scope_info.assigned_names,
1449
- scope_info.global_names,
1450
- scope_info.nonlocal_names,
1451
- implicit_captures,
1452
- global_name_map,
1453
- Some(enclosing_locals),
1454
- scope_info.cell_var_names,
1455
- self.interner,
1456
- );
1457
-
1458
- // Prepare the lambda body
1459
- let prepared_body = inner_prepare.prepare_nodes(body_nodes)?;
1460
-
1461
- // Mark variables that the inner function captures as our cell_vars
1462
- for captured_name in inner_prepare.free_var_map.keys() {
1463
- if !self.cell_var_map.contains_key(captured_name) && !self.free_var_map.contains_key(captured_name) {
1464
- let slot = match self.name_map.entry(captured_name.clone()) {
1465
- Entry::Occupied(e) => *e.get(),
1466
- Entry::Vacant(e) => {
1467
- let slot = NamespaceId::new(self.namespace_size);
1468
- self.namespace_size += 1;
1469
- e.insert(slot);
1470
- slot
1471
- }
1472
- };
1473
- self.cell_var_map.insert(captured_name.clone(), slot);
1474
- }
1475
- }
1476
-
1477
- // Build free_var_enclosing_slots
1478
- let mut free_var_entries: Vec<_> = inner_prepare.free_var_map.into_iter().collect();
1479
- free_var_entries.sort_by_key(|(_, our_slot)| *our_slot);
1480
-
1481
- let free_var_enclosing_slots: Vec<NamespaceId> = free_var_entries
1482
- .into_iter()
1483
- .map(|(var_name, _our_slot)| {
1484
- if let Some(&slot) = self.cell_var_map.get(&var_name) {
1485
- slot
1486
- } else if let Some(&slot) = self.free_var_map.get(&var_name) {
1487
- slot
1488
- } else {
1489
- panic!("free_var '{var_name}' not found in enclosing scope's cell_var_map or free_var_map");
1490
- }
1491
- })
1492
- .collect();
1493
-
1494
- // Build cell_param_indices
1495
- let cell_var_count = inner_prepare.cell_var_map.len();
1496
- let namespace_size = inner_prepare.namespace_size;
1497
-
1498
- let cell_param_indices: Vec<Option<usize>> = if cell_var_count == 0 {
1499
- Vec::new()
1500
- } else {
1501
- let param_name_to_index: AHashMap<String, usize> = param_names
1502
- .iter()
1503
- .enumerate()
1504
- .map(|(idx, &name_id)| (self.interner.get_str(name_id).to_string(), idx))
1505
- .collect();
1506
-
1507
- let mut cell_entries: Vec<_> = inner_prepare.cell_var_map.iter().collect();
1508
- cell_entries.sort_by_key(|&(_, slot)| slot);
1509
-
1510
- cell_entries
1511
- .into_iter()
1512
- .map(|(name, _slot)| param_name_to_index.get(name).copied())
1513
- .collect()
1514
- };
1515
-
1516
- // Build the runtime Signature from the parsed signature
1517
- let pos_args: Vec<StringId> = parsed_sig.pos_args.iter().map(|p| p.name).collect();
1518
- let pos_defaults_count = parsed_sig.pos_args.iter().filter(|p| p.default.is_some()).count();
1519
- let args: Vec<StringId> = parsed_sig.args.iter().map(|p| p.name).collect();
1520
- let arg_defaults_count = parsed_sig.args.iter().filter(|p| p.default.is_some()).count();
1521
- let mut kwargs: Vec<StringId> = Vec::with_capacity(parsed_sig.kwargs.len());
1522
- let mut kwarg_default_map: Vec<Option<usize>> = Vec::with_capacity(parsed_sig.kwargs.len());
1523
- let mut kwarg_default_index = 0;
1524
- for param in &parsed_sig.kwargs {
1525
- kwargs.push(param.name);
1526
- if param.default.is_some() {
1527
- kwarg_default_map.push(Some(kwarg_default_index));
1528
- kwarg_default_index += 1;
1529
- } else {
1530
- kwarg_default_map.push(None);
1531
- }
1532
- }
1533
-
1534
- let signature = Signature::new(
1535
- pos_args,
1536
- pos_defaults_count,
1537
- args,
1538
- arg_defaults_count,
1539
- parsed_sig.var_args,
1540
- kwargs,
1541
- kwarg_default_map,
1542
- parsed_sig.var_kwargs,
1543
- );
1544
-
1545
- // Collect and prepare default expressions (evaluated in enclosing scope)
1546
- let mut default_exprs = Vec::with_capacity(signature.total_defaults_count());
1547
- for param in &parsed_sig.pos_args {
1548
- if let Some(ref expr) = param.default {
1549
- default_exprs.push(self.prepare_expression(expr.clone())?);
1550
- }
1551
- }
1552
- for param in &parsed_sig.args {
1553
- if let Some(ref expr) = param.default {
1554
- default_exprs.push(self.prepare_expression(expr.clone())?);
1555
- }
1556
- }
1557
- for param in &parsed_sig.kwargs {
1558
- if let Some(ref expr) = param.default {
1559
- default_exprs.push(self.prepare_expression(expr.clone())?);
1560
- }
1561
- }
1562
-
1563
- // Create the prepared function definition (lambdas are never async)
1564
- let func_def = PreparedFunctionDef {
1565
- name: lambda_name,
1566
- signature,
1567
- body: prepared_body,
1568
- namespace_size,
1569
- free_var_enclosing_slots,
1570
- cell_var_count,
1571
- cell_param_indices,
1572
- default_exprs,
1573
- is_async: false,
1574
- };
1575
-
1576
- Ok(ExprLoc::new(
1577
- position,
1578
- Expr::Lambda {
1579
- func_def: Box::new(func_def),
1580
- },
1581
- ))
1582
- }
1583
-
1584
- /// Resolves an identifier to its namespace index and scope, creating a new entry if needed.
1585
- ///
1586
- /// TODO This whole implementation seems ugly at best.
1587
- ///
1588
- /// This is the core name resolution mechanism with scope-aware resolution:
1589
- ///
1590
- /// **At module level:** All names go to the local namespace (which IS the global namespace).
1591
- ///
1592
- /// **In functions:**
1593
- /// - If name is declared `global` → resolve to global namespace
1594
- /// - If name is declared `nonlocal` → resolve to enclosing scope via Cell
1595
- /// - If name is assigned in this function → resolve to local namespace
1596
- /// - If name exists in global namespace (read-only access) → resolve to global namespace
1597
- /// - Otherwise → resolve to local namespace (will be NameError at runtime)
1598
- ///
1599
- /// # Returns
1600
- /// A tuple of (resolved Identifier with id and scope set, whether this is a new local name).
1601
- fn get_id(&mut self, ident: Identifier) -> (Identifier, bool) {
1602
- let name_str = self.interner.get_str(ident.name_id);
1603
-
1604
- // At module level, all names are local (which is also the global namespace).
1605
- // The compiler emits global opcodes for these, so the VM reads/writes
1606
- // directly from the globals array rather than the stack.
1607
- if self.is_module_scope {
1608
- return match self.name_map.entry(name_str.to_string()) {
1609
- Entry::Occupied(e) => {
1610
- // Name already exists (from prior reference or pre-registered).
1611
- // Determine scope the same way as for vacant entries: if the name
1612
- // has been assigned so far, it's a true local; otherwise it's an
1613
- // unassigned reference that should yield NameLookup at runtime.
1614
- let scope = if self.names_assigned_in_order.contains(name_str) {
1615
- NameScope::Local
1616
- } else {
1617
- NameScope::LocalUnassigned
1618
- };
1619
- (
1620
- Identifier::new_with_scope(ident.name_id, ident.position, *e.get(), scope),
1621
- false,
1622
- )
1623
- }
1624
- Entry::Vacant(e) => {
1625
- let id = NamespaceId::new(self.namespace_size);
1626
- self.namespace_size += 1;
1627
- e.insert(id);
1628
- // Determine scope: if the name is assigned somewhere (even later in the file),
1629
- // it's a true local that will raise UnboundLocalError if accessed before assignment.
1630
- // If the name is never assigned, it's an undefined reference that raises NameError.
1631
- let scope = if self.names_assigned_in_order.contains(name_str) {
1632
- NameScope::Local
1633
- } else {
1634
- NameScope::LocalUnassigned
1635
- };
1636
- (
1637
- Identifier::new_with_scope(ident.name_id, ident.position, id, scope),
1638
- true,
1639
- )
1640
- }
1641
- };
1642
- }
1643
-
1644
- // In a function: determine scope based on global_names, nonlocal_names, assigned_names, global_name_map
1645
-
1646
- // 1. Check if declared `global`
1647
- if self.global_names.contains(name_str) {
1648
- if let Some(ref global_map) = self.global_name_map
1649
- && let Some(&global_id) = global_map.get(name_str)
1650
- {
1651
- // Name exists in global namespace
1652
- return (
1653
- Identifier::new_with_scope(ident.name_id, ident.position, global_id, NameScope::Global),
1654
- false,
1655
- );
1656
- }
1657
- // Declared global but doesn't exist yet - it will be created when assigned
1658
- // For now, we still need a global index. We'll use a placeholder approach:
1659
- // allocate in global namespace (this is a simplification - in real Python,
1660
- // the global would be created at module level when first assigned)
1661
- // For our implementation, we'll resolve to global but the variable won't exist until assigned.
1662
- // Return a "new" global - but we can't modify global_name_map here.
1663
- // For simplicity, we'll resolve to local with Global scope - runtime will handle the lookup.
1664
- let (id, is_new) = match self.name_map.entry(name_str.to_string()) {
1665
- Entry::Occupied(e) => (*e.get(), false),
1666
- Entry::Vacant(e) => {
1667
- let id = NamespaceId::new(self.namespace_size);
1668
- self.namespace_size += 1;
1669
- e.insert(id);
1670
- (id, true)
1671
- }
1672
- };
1673
- // Mark as Global scope - runtime will need to handle this specially
1674
- return (
1675
- Identifier::new_with_scope(ident.name_id, ident.position, id, NameScope::Global),
1676
- is_new,
1677
- );
1678
- }
1679
-
1680
- // 2. Check if captured from enclosing scope (nonlocal declaration or implicit capture)
1681
- // free_var_map stores namespace slot indices where the cell reference will be stored
1682
- if let Some(&slot) = self.free_var_map.get(name_str) {
1683
- // At runtime, the cell reference is in namespace[slot] as Value::Ref(cell_id)
1684
- return (
1685
- Identifier::new_with_scope(ident.name_id, ident.position, slot, NameScope::Cell),
1686
- false, // Not a new local - it's captured from enclosing scope
1687
- );
1688
- }
1689
-
1690
- // 3. Check if this is a cell variable (captured by nested functions)
1691
- // cell_var_map stores namespace slot indices where the cell reference will be stored
1692
- // At call time, a cell is created and stored as Value::Ref(cell_id) at this slot
1693
- if let Some(&slot) = self.cell_var_map.get(name_str) {
1694
- // The namespace slot was already allocated when cell_var_map was populated
1695
- return (
1696
- Identifier::new_with_scope(ident.name_id, ident.position, slot, NameScope::Cell),
1697
- false, // Not a "new" local - it's a cell variable
1698
- );
1699
- }
1700
-
1701
- // 4. Check if assigned in this function (local variable)
1702
- if self.assigned_names.contains(name_str) {
1703
- let (id, is_new) = match self.name_map.entry(name_str.to_string()) {
1704
- Entry::Occupied(e) => (*e.get(), false),
1705
- Entry::Vacant(e) => {
1706
- let id = NamespaceId::new(self.namespace_size);
1707
- self.namespace_size += 1;
1708
- e.insert(id);
1709
- (id, true)
1710
- }
1711
- };
1712
- return (
1713
- Identifier::new_with_scope(ident.name_id, ident.position, id, NameScope::Local),
1714
- is_new,
1715
- );
1716
- }
1717
-
1718
- // 5. Check if name was pre-populated in name_map (from function parameters)
1719
- // This ensures parameters shadow both enclosing locals and global variables
1720
- // with the same name. Parameters are added to name_map during
1721
- // FunctionScope::new_function() but are NOT in assigned_names (since they're
1722
- // not assigned in the function body). This MUST be checked before
1723
- // enclosing_locals, otherwise a parameter like `def inner(x)` would be
1724
- // incorrectly resolved as a closure capture when an outer scope also has `x`.
1725
- // Excludes names tracked in `unassigned_ref_names` — those were added to
1726
- // `name_map` by step 8 as `LocalUnassigned` references and must stay that way
1727
- // to trigger NameLookup at runtime (e.g., for external function resolution).
1728
- if !self.unassigned_ref_names.contains(name_str)
1729
- && let Some(&id) = self.name_map.get(name_str)
1730
- {
1731
- return (
1732
- Identifier::new_with_scope(ident.name_id, ident.position, id, NameScope::Local),
1733
- false, // Not new - was pre-populated from parameters
1734
- );
1735
- }
1736
-
1737
- // 6. Check if exists in enclosing scope (implicit closure capture)
1738
- // This handles reading variables from enclosing functions without explicit `nonlocal`
1739
- if let Some(ref enclosing) = self.enclosing_locals
1740
- && enclosing.contains(name_str)
1741
- {
1742
- // This is an implicit capture - add to free_var_map with a namespace slot
1743
- let slot = if let Some(&existing_slot) = self.free_var_map.get(name_str) {
1744
- existing_slot
1745
- } else {
1746
- // Allocate a namespace slot for this free variable
1747
- let slot = NamespaceId::new(self.namespace_size);
1748
- self.namespace_size += 1;
1749
- self.name_map.insert(name_str.to_string(), slot);
1750
- self.free_var_map.insert(name_str.to_string(), slot);
1751
- slot
1752
- };
1753
- return (
1754
- Identifier::new_with_scope(ident.name_id, ident.position, slot, NameScope::Cell),
1755
- false, // Not a new local - it's captured from enclosing scope
1756
- );
1757
- }
1758
-
1759
- // 7. Check if exists in global namespace (implicit global read)
1760
- if let Some(ref global_map) = self.global_name_map
1761
- && let Some(&global_id) = global_map.get(name_str)
1762
- {
1763
- return (
1764
- Identifier::new_with_scope(ident.name_id, ident.position, global_id, NameScope::Global),
1765
- false,
1766
- );
1767
- }
1768
-
1769
- // 8. Name not found anywhere - allocate a local slot (will be NameError at runtime)
1770
- // This handles names that are only read (never assigned) and don't exist globally.
1771
- // We allocate a local slot that will never be written to.
1772
- // Mark as LocalUnassigned so runtime raises NameError (not UnboundLocalError).
1773
- // Track in `unassigned_ref_names` so step 6 doesn't treat subsequent references
1774
- // as `Local` (parameters).
1775
- self.unassigned_ref_names.insert(name_str.to_string());
1776
- let (id, is_new) = match self.name_map.entry(name_str.to_string()) {
1777
- Entry::Occupied(e) => (*e.get(), false),
1778
- Entry::Vacant(e) => {
1779
- let id = NamespaceId::new(self.namespace_size);
1780
- self.namespace_size += 1;
1781
- e.insert(id);
1782
- (id, true)
1783
- }
1784
- };
1785
- (
1786
- Identifier::new_with_scope(ident.name_id, ident.position, id, NameScope::LocalUnassigned),
1787
- is_new,
1788
- )
1789
- }
1790
-
1791
- /// Prepares an f-string part by resolving names in interpolated expressions.
1792
- fn prepare_fstring_part(&mut self, part: FStringPart) -> Result<FStringPart, ParseError> {
1793
- match part {
1794
- FStringPart::Literal(s) => Ok(FStringPart::Literal(s)),
1795
- FStringPart::Interpolation {
1796
- expr,
1797
- conversion,
1798
- format_spec,
1799
- debug_prefix,
1800
- } => {
1801
- let prepared_expr = Box::new(self.prepare_expression(*expr)?);
1802
- let prepared_spec = match format_spec {
1803
- Some(FormatSpec::Static(s)) => Some(FormatSpec::Static(s)),
1804
- Some(FormatSpec::Dynamic(parts)) => {
1805
- let prepared = parts
1806
- .into_iter()
1807
- .map(|p| self.prepare_fstring_part(p))
1808
- .collect::<Result<Vec<_>, _>>()?;
1809
- Some(FormatSpec::Dynamic(prepared))
1810
- }
1811
- None => None,
1812
- };
1813
- Ok(FStringPart::Interpolation {
1814
- expr: prepared_expr,
1815
- conversion,
1816
- format_spec: prepared_spec,
1817
- debug_prefix,
1818
- })
1819
- }
1820
- }
1821
- }
1822
- }
1823
-
1824
- /// Information collected from first-pass scan of a function body.
1825
- ///
1826
- /// This struct holds the scope-related information needed for the second pass
1827
- /// of function preparation and for closure analysis.
1828
- struct FunctionScopeInfo {
1829
- /// Names declared as `global`
1830
- global_names: AHashSet<String>,
1831
- /// Names declared as `nonlocal`
1832
- nonlocal_names: AHashSet<String>,
1833
- /// Names that are assigned in this scope
1834
- assigned_names: AHashSet<String>,
1835
- /// Names that are captured by nested functions (must be stored in cells)
1836
- cell_var_names: AHashSet<String>,
1837
- /// Names that are referenced but not local, global, or nonlocal.
1838
- /// These are POTENTIAL implicit captures - they may be captures from an enclosing function
1839
- /// OR they may be builtin/global reads. The actual implicit captures are determined
1840
- /// by filtering against enclosing_locals in new_function.
1841
- potential_captures: AHashSet<String>,
1842
- }
1843
-
1844
- /// Scans a function body to collect scope information (first phase of preparation).
1845
- ///
1846
- /// This function performs three passes over the AST:
1847
- /// 1. Collect global, nonlocal, and assigned names
1848
- /// 2. Identify cell_vars (names captured by nested functions)
1849
- /// 3. Collect potential implicit captures (referenced but not local/global/nonlocal)
1850
- ///
1851
- /// The collected information includes:
1852
- /// - Names declared as `global` (from Global statements)
1853
- /// - Names declared as `nonlocal` (from Nonlocal statements)
1854
- /// - Names that are assigned (from Assign, OpAssign, For targets, etc.)
1855
- /// - Names that are captured by nested functions (cell_var_names)
1856
- /// - Names that might be captured from enclosing scope (potential_captures)
1857
- ///
1858
- /// This information is used to determine whether each name reference should resolve
1859
- /// to the local namespace, global namespace, or an enclosing scope via cells.
1860
- fn collect_function_scope_info(
1861
- nodes: &[ParseNode],
1862
- params: &[StringId],
1863
- interner: &InternerBuilder,
1864
- ) -> FunctionScopeInfo {
1865
- let mut global_names = AHashSet::new();
1866
- let mut nonlocal_names = AHashSet::new();
1867
- let mut assigned_names = AHashSet::new();
1868
- let mut cell_var_names = AHashSet::new();
1869
- let mut referenced_names = AHashSet::new();
1870
-
1871
- // First pass: collect global, nonlocal, and assigned names
1872
- for node in nodes {
1873
- collect_scope_info_from_node(
1874
- node,
1875
- &mut global_names,
1876
- &mut nonlocal_names,
1877
- &mut assigned_names,
1878
- interner,
1879
- );
1880
- }
1881
-
1882
- // Build the set of our locals: params + assigned_names (excluding globals)
1883
- let param_names: AHashSet<String> = params
1884
- .iter()
1885
- .map(|string_id| interner.get_str(*string_id).to_string())
1886
- .collect();
1887
-
1888
- let our_locals: AHashSet<String> = param_names
1889
- .iter()
1890
- .cloned()
1891
- .chain(assigned_names.iter().cloned())
1892
- .filter(|name| !global_names.contains(name))
1893
- .collect();
1894
-
1895
- // Second pass: find what nested functions capture from us
1896
- for node in nodes {
1897
- collect_cell_vars_from_node(node, &our_locals, &mut cell_var_names, interner);
1898
- }
1899
-
1900
- // Third pass: collect all referenced names to identify potential implicit captures.
1901
- // These are names that might be captured from an enclosing function scope.
1902
- // We can't fully determine implicit captures here because we don't know yet what
1903
- // the enclosing scope's locals are - that's determined later when we call new_function.
1904
- for node in nodes {
1905
- collect_referenced_names_from_node(node, &mut referenced_names, interner);
1906
- }
1907
-
1908
- // Potential implicit captures are names that are:
1909
- // - Referenced in the function body
1910
- // - Not local (not params, not assigned)
1911
- // - Not declared global
1912
- // - Not declared nonlocal (those are handled separately)
1913
- // The actual implicit captures will be filtered against enclosing_locals in new_function.
1914
- let potential_captures: AHashSet<String> = referenced_names
1915
- .into_iter()
1916
- .filter(|name| !our_locals.contains(name) && !global_names.contains(name) && !nonlocal_names.contains(name))
1917
- .collect();
1918
-
1919
- FunctionScopeInfo {
1920
- global_names,
1921
- nonlocal_names,
1922
- assigned_names,
1923
- cell_var_names,
1924
- potential_captures,
1925
- }
1926
- }
1927
-
1928
- /// Helper to collect scope info from a single node.
1929
- fn collect_scope_info_from_node(
1930
- node: &ParseNode,
1931
- global_names: &mut AHashSet<String>,
1932
- nonlocal_names: &mut AHashSet<String>,
1933
- assigned_names: &mut AHashSet<String>,
1934
- interner: &InternerBuilder,
1935
- ) {
1936
- match node {
1937
- Node::Global { names, .. } => {
1938
- for string_id in names {
1939
- global_names.insert(interner.get_str(*string_id).to_string());
1940
- }
1941
- }
1942
- Node::Nonlocal { names, .. } => {
1943
- for string_id in names {
1944
- nonlocal_names.insert(interner.get_str(*string_id).to_string());
1945
- }
1946
- }
1947
- Node::Assign { target, object } => {
1948
- assigned_names.insert(interner.get_str(target.name_id).to_string());
1949
- // Scan value expression for walrus operators
1950
- collect_assigned_names_from_expr(object, assigned_names, interner);
1951
- }
1952
- Node::UnpackAssign { targets, object, .. } => {
1953
- // Recursively collect all names from nested unpack targets
1954
- for target in targets {
1955
- collect_names_from_unpack_target(target, assigned_names, interner);
1956
- }
1957
- // Scan value expression for walrus operators
1958
- collect_assigned_names_from_expr(object, assigned_names, interner);
1959
- }
1960
- Node::OpAssign { target, object, .. } => {
1961
- assigned_names.insert(interner.get_str(target.name_id).to_string());
1962
- // Scan value expression for walrus operators
1963
- collect_assigned_names_from_expr(object, assigned_names, interner);
1964
- }
1965
- Node::SubscriptOpAssign { index, object, .. } => {
1966
- collect_assigned_names_from_expr(index, assigned_names, interner);
1967
- collect_assigned_names_from_expr(object, assigned_names, interner);
1968
- }
1969
- Node::SubscriptAssign { index, value, .. } => {
1970
- // Subscript assignment doesn't create a new name, it modifies existing container
1971
- // But scan expressions for walrus operators
1972
- collect_assigned_names_from_expr(index, assigned_names, interner);
1973
- collect_assigned_names_from_expr(value, assigned_names, interner);
1974
- }
1975
- Node::AttrAssign { object, value, .. } => {
1976
- // Attribute assignment doesn't create a new name, it modifies existing object
1977
- // But scan expressions for walrus operators
1978
- collect_assigned_names_from_expr(object, assigned_names, interner);
1979
- collect_assigned_names_from_expr(value, assigned_names, interner);
1980
- }
1981
- Node::For {
1982
- target,
1983
- iter,
1984
- body,
1985
- or_else,
1986
- } => {
1987
- // For loop target is assigned - collect all names from the target
1988
- collect_names_from_unpack_target(target, assigned_names, interner);
1989
- // Scan iter expression for walrus operators
1990
- collect_assigned_names_from_expr(iter, assigned_names, interner);
1991
- // Recurse into body and else
1992
- for n in body {
1993
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
1994
- }
1995
- for n in or_else {
1996
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
1997
- }
1998
- }
1999
- Node::While { test, body, or_else } => {
2000
- // Scan test expression for walrus operators
2001
- collect_assigned_names_from_expr(test, assigned_names, interner);
2002
- // Recurse into body and else blocks
2003
- for n in body {
2004
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
2005
- }
2006
- for n in or_else {
2007
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
2008
- }
2009
- }
2010
- Node::If { test, body, or_else } => {
2011
- // Scan test expression for walrus operators
2012
- collect_assigned_names_from_expr(test, assigned_names, interner);
2013
- // Recurse into branches
2014
- for n in body {
2015
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
2016
- }
2017
- for n in or_else {
2018
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
2019
- }
2020
- }
2021
- Node::FunctionDef(RawFunctionDef { name, .. }) => {
2022
- // Function definition creates a local binding for the function name
2023
- // But we don't recurse into the function body - that's a separate scope
2024
- assigned_names.insert(interner.get_str(name.name_id).to_string());
2025
- }
2026
- Node::Try(Try {
2027
- body,
2028
- handlers,
2029
- or_else,
2030
- finally,
2031
- }) => {
2032
- // Recurse into all blocks
2033
- for n in body {
2034
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
2035
- }
2036
- for handler in handlers {
2037
- // Exception variable name is assigned
2038
- if let Some(ref name) = handler.name {
2039
- assigned_names.insert(interner.get_str(name.name_id).to_string());
2040
- }
2041
- for n in &handler.body {
2042
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
2043
- }
2044
- }
2045
- for n in or_else {
2046
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
2047
- }
2048
- for n in finally {
2049
- collect_scope_info_from_node(n, global_names, nonlocal_names, assigned_names, interner);
2050
- }
2051
- }
2052
- // Import creates a binding for the module name (or alias)
2053
- Node::Import { binding, .. } => {
2054
- assigned_names.insert(interner.get_str(binding.name_id).to_string());
2055
- }
2056
- // ImportFrom creates bindings for each imported name (or alias)
2057
- Node::ImportFrom { names, .. } => {
2058
- for (_import_name, binding) in names {
2059
- assigned_names.insert(interner.get_str(binding.name_id).to_string());
2060
- }
2061
- }
2062
- // Statements with expressions that may contain walrus operators
2063
- Node::Expr(expr) | Node::Return(expr) => {
2064
- collect_assigned_names_from_expr(expr, assigned_names, interner);
2065
- }
2066
- Node::Raise(Some(expr)) => {
2067
- collect_assigned_names_from_expr(expr, assigned_names, interner);
2068
- }
2069
- Node::Assert { test, msg } => {
2070
- collect_assigned_names_from_expr(test, assigned_names, interner);
2071
- if let Some(m) = msg {
2072
- collect_assigned_names_from_expr(m, assigned_names, interner);
2073
- }
2074
- }
2075
- // These don't create new names
2076
- Node::Pass | Node::ReturnNone | Node::Raise(None) | Node::Break { .. } | Node::Continue { .. } => {}
2077
- }
2078
- }
2079
-
2080
- /// Collects names assigned by walrus operators (`:=`) within an expression.
2081
- ///
2082
- /// Per PEP 572, walrus operator targets are assignments in the enclosing scope.
2083
- /// This function recursively scans expressions to find all `Named` expression targets.
2084
- /// It does NOT recurse into lambda bodies as those have their own scope.
2085
- fn collect_assigned_names_from_expr(expr: &ExprLoc, assigned_names: &mut AHashSet<String>, interner: &InternerBuilder) {
2086
- match &expr.expr {
2087
- Expr::Named { target, value } => {
2088
- // The target of a walrus operator is assigned in this scope
2089
- assigned_names.insert(interner.get_str(target.name_id).to_string());
2090
- // Also scan the value expression
2091
- collect_assigned_names_from_expr(value, assigned_names, interner);
2092
- }
2093
- // Recurse into sub-expressions
2094
- Expr::List(items) | Expr::Tuple(items) | Expr::Set(items) => {
2095
- for item in items {
2096
- let expr = match item {
2097
- SequenceItem::Value(e) | SequenceItem::Unpack(e) => e,
2098
- };
2099
- collect_assigned_names_from_expr(expr, assigned_names, interner);
2100
- }
2101
- }
2102
- Expr::Dict(dict_items) => {
2103
- for item in dict_items {
2104
- match item {
2105
- DictItem::Pair(key, value) => {
2106
- collect_assigned_names_from_expr(key, assigned_names, interner);
2107
- collect_assigned_names_from_expr(value, assigned_names, interner);
2108
- }
2109
- DictItem::Unpack(e) => collect_assigned_names_from_expr(e, assigned_names, interner),
2110
- }
2111
- }
2112
- }
2113
- Expr::Op { left, right, .. } | Expr::CmpOp { left, right, .. } => {
2114
- collect_assigned_names_from_expr(left, assigned_names, interner);
2115
- collect_assigned_names_from_expr(right, assigned_names, interner);
2116
- }
2117
- Expr::ChainCmp { left, comparisons } => {
2118
- collect_assigned_names_from_expr(left, assigned_names, interner);
2119
- for (_, expr) in comparisons {
2120
- collect_assigned_names_from_expr(expr, assigned_names, interner);
2121
- }
2122
- }
2123
- Expr::Not(operand)
2124
- | Expr::UnaryMinus(operand)
2125
- | Expr::UnaryPlus(operand)
2126
- | Expr::UnaryInvert(operand)
2127
- | Expr::Await(operand) => {
2128
- collect_assigned_names_from_expr(operand, assigned_names, interner);
2129
- }
2130
- Expr::Subscript { object, index } => {
2131
- collect_assigned_names_from_expr(object, assigned_names, interner);
2132
- collect_assigned_names_from_expr(index, assigned_names, interner);
2133
- }
2134
- Expr::Call { args, .. } => {
2135
- collect_assigned_names_from_args(args, assigned_names, interner);
2136
- }
2137
- Expr::AttrCall { object, args, .. } => {
2138
- collect_assigned_names_from_expr(object, assigned_names, interner);
2139
- collect_assigned_names_from_args(args, assigned_names, interner);
2140
- }
2141
- Expr::IndirectCall { callable, args } => {
2142
- collect_assigned_names_from_expr(callable, assigned_names, interner);
2143
- collect_assigned_names_from_args(args, assigned_names, interner);
2144
- }
2145
- Expr::AttrGet { object, .. } => {
2146
- collect_assigned_names_from_expr(object, assigned_names, interner);
2147
- }
2148
- Expr::IfElse { test, body, orelse } => {
2149
- collect_assigned_names_from_expr(test, assigned_names, interner);
2150
- collect_assigned_names_from_expr(body, assigned_names, interner);
2151
- collect_assigned_names_from_expr(orelse, assigned_names, interner);
2152
- }
2153
- // Per PEP 572, walrus in comprehensions assigns to the ENCLOSING scope
2154
- Expr::ListComp { elt, generators } | Expr::SetComp { elt, generators } => {
2155
- collect_assigned_names_from_expr(elt, assigned_names, interner);
2156
- for generator in generators {
2157
- collect_assigned_names_from_expr(&generator.iter, assigned_names, interner);
2158
- for cond in &generator.ifs {
2159
- collect_assigned_names_from_expr(cond, assigned_names, interner);
2160
- }
2161
- }
2162
- }
2163
- Expr::DictComp { key, value, generators } => {
2164
- collect_assigned_names_from_expr(key, assigned_names, interner);
2165
- collect_assigned_names_from_expr(value, assigned_names, interner);
2166
- for generator in generators {
2167
- collect_assigned_names_from_expr(&generator.iter, assigned_names, interner);
2168
- for cond in &generator.ifs {
2169
- collect_assigned_names_from_expr(cond, assigned_names, interner);
2170
- }
2171
- }
2172
- }
2173
- Expr::FString(parts) => {
2174
- for part in parts {
2175
- if let FStringPart::Interpolation { expr, .. } = part {
2176
- collect_assigned_names_from_expr(expr, assigned_names, interner);
2177
- }
2178
- }
2179
- }
2180
- Expr::Slice { lower, upper, step } => {
2181
- if let Some(e) = lower {
2182
- collect_assigned_names_from_expr(e, assigned_names, interner);
2183
- }
2184
- if let Some(e) = upper {
2185
- collect_assigned_names_from_expr(e, assigned_names, interner);
2186
- }
2187
- if let Some(e) = step {
2188
- collect_assigned_names_from_expr(e, assigned_names, interner);
2189
- }
2190
- }
2191
- // Lambda bodies have their own scope - walrus inside them doesn't affect us
2192
- Expr::LambdaRaw { .. } | Expr::Lambda { .. } => {}
2193
- // Leaf expressions don't contain walrus operators
2194
- Expr::Literal(_) | Expr::Builtin(_) | Expr::Name(_) => {}
2195
- }
2196
- }
2197
-
2198
- /// Helper to collect assigned names from argument expressions.
2199
- fn collect_assigned_names_from_args(
2200
- args: &ArgExprs,
2201
- assigned_names: &mut AHashSet<String>,
2202
- interner: &InternerBuilder,
2203
- ) {
2204
- match args {
2205
- ArgExprs::Empty => {}
2206
- ArgExprs::One(arg) => collect_assigned_names_from_expr(arg, assigned_names, interner),
2207
- ArgExprs::Two(arg1, arg2) => {
2208
- collect_assigned_names_from_expr(arg1, assigned_names, interner);
2209
- collect_assigned_names_from_expr(arg2, assigned_names, interner);
2210
- }
2211
- ArgExprs::Args(args) => {
2212
- for arg in args {
2213
- collect_assigned_names_from_expr(arg, assigned_names, interner);
2214
- }
2215
- }
2216
- ArgExprs::Kwargs(kwargs) => {
2217
- for kwarg in kwargs {
2218
- collect_assigned_names_from_expr(&kwarg.value, assigned_names, interner);
2219
- }
2220
- }
2221
- ArgExprs::ArgsKargs {
2222
- args,
2223
- kwargs,
2224
- var_args,
2225
- var_kwargs,
2226
- } => {
2227
- if let Some(args) = args {
2228
- for arg in args {
2229
- collect_assigned_names_from_expr(arg, assigned_names, interner);
2230
- }
2231
- }
2232
- if let Some(kwargs) = kwargs {
2233
- for kwarg in kwargs {
2234
- collect_assigned_names_from_expr(&kwarg.value, assigned_names, interner);
2235
- }
2236
- }
2237
- if let Some(var_args) = var_args {
2238
- collect_assigned_names_from_expr(var_args, assigned_names, interner);
2239
- }
2240
- if let Some(var_kwargs) = var_kwargs {
2241
- collect_assigned_names_from_expr(var_kwargs, assigned_names, interner);
2242
- }
2243
- }
2244
- ArgExprs::GeneralizedCall { args, kwargs } => {
2245
- for arg in args {
2246
- match arg {
2247
- CallArg::Value(e) | CallArg::Unpack(e) => {
2248
- collect_assigned_names_from_expr(e, assigned_names, interner);
2249
- }
2250
- }
2251
- }
2252
- for kwarg in kwargs {
2253
- match kwarg {
2254
- CallKwarg::Named(kw) => {
2255
- collect_assigned_names_from_expr(&kw.value, assigned_names, interner);
2256
- }
2257
- CallKwarg::Unpack(e) => {
2258
- collect_assigned_names_from_expr(e, assigned_names, interner);
2259
- }
2260
- }
2261
- }
2262
- }
2263
- }
2264
- }
2265
-
2266
- /// Collects cell_vars by analyzing what nested functions capture from our scope.
2267
- ///
2268
- /// For each FunctionDef node, we recursively analyze its body to find what names it
2269
- /// references. Any name that is in `our_locals` and referenced by the nested function
2270
- /// (not as a local of the nested function) becomes a cell_var.
2271
- fn collect_cell_vars_from_node(
2272
- node: &ParseNode,
2273
- our_locals: &AHashSet<String>,
2274
- cell_vars: &mut AHashSet<String>,
2275
- interner: &InternerBuilder,
2276
- ) {
2277
- match node {
2278
- Node::FunctionDef(RawFunctionDef { signature, body, .. }) => {
2279
- // Find what names are referenced inside this nested function
2280
- let mut referenced = AHashSet::new();
2281
- for n in body {
2282
- collect_referenced_names_from_node(n, &mut referenced, interner);
2283
- }
2284
-
2285
- // Extract param names from signature for scope analysis
2286
- let param_names: Vec<StringId> = signature.param_names().collect();
2287
-
2288
- // Collect the nested function's own locals (params + assigned)
2289
- let nested_scope = collect_function_scope_info(body, &param_names, interner);
2290
-
2291
- // Any name that is:
2292
- // - Referenced by the nested function
2293
- // - Not a local of the nested function
2294
- // - Not declared global in the nested function
2295
- // - In our locals
2296
- // becomes a cell_var
2297
- for name in &referenced {
2298
- if !nested_scope.assigned_names.contains(name)
2299
- && !param_names.iter().any(|p| interner.get_str(*p) == name)
2300
- && !nested_scope.global_names.contains(name)
2301
- && our_locals.contains(name)
2302
- {
2303
- cell_vars.insert(name.clone());
2304
- }
2305
- }
2306
-
2307
- // Also check what the nested function explicitly declares as nonlocal
2308
- for name in &nested_scope.nonlocal_names {
2309
- if our_locals.contains(name) {
2310
- cell_vars.insert(name.clone());
2311
- }
2312
- }
2313
- }
2314
- // Recurse into control flow structures
2315
- Node::For { body, or_else, .. } => {
2316
- for n in body {
2317
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2318
- }
2319
- for n in or_else {
2320
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2321
- }
2322
- }
2323
- Node::While { body, or_else, .. } => {
2324
- for n in body {
2325
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2326
- }
2327
- for n in or_else {
2328
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2329
- }
2330
- }
2331
- Node::If { body, or_else, .. } => {
2332
- for n in body {
2333
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2334
- }
2335
- for n in or_else {
2336
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2337
- }
2338
- }
2339
- Node::Try(Try {
2340
- body,
2341
- handlers,
2342
- or_else,
2343
- finally,
2344
- }) => {
2345
- for n in body {
2346
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2347
- }
2348
- for handler in handlers {
2349
- for n in &handler.body {
2350
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2351
- }
2352
- }
2353
- for n in or_else {
2354
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2355
- }
2356
- for n in finally {
2357
- collect_cell_vars_from_node(n, our_locals, cell_vars, interner);
2358
- }
2359
- }
2360
- // Handle expressions that may contain lambdas
2361
- Node::Expr(expr) | Node::Return(expr) => {
2362
- collect_cell_vars_from_expr(expr, our_locals, cell_vars, interner);
2363
- }
2364
- Node::Assign { object, .. } | Node::UnpackAssign { object, .. } => {
2365
- collect_cell_vars_from_expr(object, our_locals, cell_vars, interner);
2366
- }
2367
- Node::OpAssign { object, .. } => {
2368
- collect_cell_vars_from_expr(object, our_locals, cell_vars, interner);
2369
- }
2370
- Node::SubscriptOpAssign { index, object, .. } => {
2371
- collect_cell_vars_from_expr(index, our_locals, cell_vars, interner);
2372
- collect_cell_vars_from_expr(object, our_locals, cell_vars, interner);
2373
- }
2374
- Node::SubscriptAssign { index, value, .. } => {
2375
- collect_cell_vars_from_expr(index, our_locals, cell_vars, interner);
2376
- collect_cell_vars_from_expr(value, our_locals, cell_vars, interner);
2377
- }
2378
- Node::AttrAssign { object, value, .. } => {
2379
- collect_cell_vars_from_expr(object, our_locals, cell_vars, interner);
2380
- collect_cell_vars_from_expr(value, our_locals, cell_vars, interner);
2381
- }
2382
- // Other nodes don't contain nested function definitions or lambdas
2383
- _ => {}
2384
- }
2385
- }
2386
-
2387
- /// Collects cell_vars from lambda expressions within an expression.
2388
- ///
2389
- /// Recursively searches through an expression tree to find lambda expressions
2390
- /// that capture variables from the enclosing scope.
2391
- fn collect_cell_vars_from_expr(
2392
- expr: &ExprLoc,
2393
- our_locals: &AHashSet<String>,
2394
- cell_vars: &mut AHashSet<String>,
2395
- interner: &InternerBuilder,
2396
- ) {
2397
- use crate::expressions::Expr;
2398
- match &expr.expr {
2399
- Expr::LambdaRaw { signature, body, .. } => {
2400
- // This lambda captures variables from our scope
2401
- // Find what names are referenced in the lambda body
2402
- let mut referenced = AHashSet::new();
2403
- collect_referenced_names_from_expr(body, &mut referenced, interner);
2404
- // Also collect from default expressions
2405
- for param in &signature.pos_args {
2406
- if let Some(ref default) = param.default {
2407
- collect_referenced_names_from_expr(default, &mut referenced, interner);
2408
- }
2409
- }
2410
- for param in &signature.args {
2411
- if let Some(ref default) = param.default {
2412
- collect_referenced_names_from_expr(default, &mut referenced, interner);
2413
- }
2414
- }
2415
- for param in &signature.kwargs {
2416
- if let Some(ref default) = param.default {
2417
- collect_referenced_names_from_expr(default, &mut referenced, interner);
2418
- }
2419
- }
2420
-
2421
- // Extract param names from signature
2422
- let param_names: Vec<StringId> = signature.param_names().collect();
2423
-
2424
- // Any name that is:
2425
- // - Referenced by the lambda
2426
- // - Not a param of the lambda
2427
- // - In our locals
2428
- // becomes a cell_var
2429
- for name in &referenced {
2430
- if !param_names.iter().any(|p| interner.get_str(*p) == name) && our_locals.contains(name) {
2431
- cell_vars.insert(name.clone());
2432
- }
2433
- }
2434
-
2435
- // Recursively check the lambda body for nested lambdas.
2436
- // For nested lambdas, extend our_locals to include this lambda's parameters
2437
- // so that inner lambdas can find them for closure capture.
2438
- let mut extended_locals = our_locals.clone();
2439
- for param_id in &param_names {
2440
- extended_locals.insert(interner.get_str(*param_id).to_string());
2441
- }
2442
- collect_cell_vars_from_expr(body, &extended_locals, cell_vars, interner);
2443
- }
2444
- // Recurse into sub-expressions
2445
- Expr::List(items) | Expr::Tuple(items) | Expr::Set(items) => {
2446
- for item in items {
2447
- let expr = match item {
2448
- SequenceItem::Value(e) | SequenceItem::Unpack(e) => e,
2449
- };
2450
- collect_cell_vars_from_expr(expr, our_locals, cell_vars, interner);
2451
- }
2452
- }
2453
- Expr::Dict(dict_items) => {
2454
- for item in dict_items {
2455
- match item {
2456
- DictItem::Pair(key, value) => {
2457
- collect_cell_vars_from_expr(key, our_locals, cell_vars, interner);
2458
- collect_cell_vars_from_expr(value, our_locals, cell_vars, interner);
2459
- }
2460
- DictItem::Unpack(e) => collect_cell_vars_from_expr(e, our_locals, cell_vars, interner),
2461
- }
2462
- }
2463
- }
2464
- Expr::Op { left, right, .. } | Expr::CmpOp { left, right, .. } => {
2465
- collect_cell_vars_from_expr(left, our_locals, cell_vars, interner);
2466
- collect_cell_vars_from_expr(right, our_locals, cell_vars, interner);
2467
- }
2468
- Expr::ChainCmp { left, comparisons } => {
2469
- collect_cell_vars_from_expr(left, our_locals, cell_vars, interner);
2470
- for (_, expr) in comparisons {
2471
- collect_cell_vars_from_expr(expr, our_locals, cell_vars, interner);
2472
- }
2473
- }
2474
- Expr::Not(operand) | Expr::UnaryMinus(operand) | Expr::UnaryPlus(operand) | Expr::UnaryInvert(operand) => {
2475
- collect_cell_vars_from_expr(operand, our_locals, cell_vars, interner);
2476
- }
2477
- Expr::Subscript { object, index } => {
2478
- collect_cell_vars_from_expr(object, our_locals, cell_vars, interner);
2479
- collect_cell_vars_from_expr(index, our_locals, cell_vars, interner);
2480
- }
2481
- Expr::Call { args, .. } => {
2482
- collect_cell_vars_from_args(args, our_locals, cell_vars, interner);
2483
- }
2484
- Expr::AttrCall { object, args, .. } => {
2485
- collect_cell_vars_from_expr(object, our_locals, cell_vars, interner);
2486
- collect_cell_vars_from_args(args, our_locals, cell_vars, interner);
2487
- }
2488
- Expr::IndirectCall { callable, args } => {
2489
- collect_cell_vars_from_expr(callable, our_locals, cell_vars, interner);
2490
- collect_cell_vars_from_args(args, our_locals, cell_vars, interner);
2491
- }
2492
- Expr::AttrGet { object, .. } => {
2493
- collect_cell_vars_from_expr(object, our_locals, cell_vars, interner);
2494
- }
2495
- Expr::IfElse { test, body, orelse } => {
2496
- collect_cell_vars_from_expr(test, our_locals, cell_vars, interner);
2497
- collect_cell_vars_from_expr(body, our_locals, cell_vars, interner);
2498
- collect_cell_vars_from_expr(orelse, our_locals, cell_vars, interner);
2499
- }
2500
- Expr::ListComp { elt, generators } | Expr::SetComp { elt, generators } => {
2501
- collect_cell_vars_from_expr(elt, our_locals, cell_vars, interner);
2502
- for generator in generators {
2503
- collect_cell_vars_from_expr(&generator.iter, our_locals, cell_vars, interner);
2504
- for cond in &generator.ifs {
2505
- collect_cell_vars_from_expr(cond, our_locals, cell_vars, interner);
2506
- }
2507
- }
2508
- }
2509
- Expr::DictComp { key, value, generators } => {
2510
- collect_cell_vars_from_expr(key, our_locals, cell_vars, interner);
2511
- collect_cell_vars_from_expr(value, our_locals, cell_vars, interner);
2512
- for generator in generators {
2513
- collect_cell_vars_from_expr(&generator.iter, our_locals, cell_vars, interner);
2514
- for cond in &generator.ifs {
2515
- collect_cell_vars_from_expr(cond, our_locals, cell_vars, interner);
2516
- }
2517
- }
2518
- }
2519
- Expr::FString(parts) => {
2520
- for part in parts {
2521
- if let crate::fstring::FStringPart::Interpolation { expr, .. } = part {
2522
- collect_cell_vars_from_expr(expr, our_locals, cell_vars, interner);
2523
- }
2524
- }
2525
- }
2526
- Expr::Named { value, .. } => {
2527
- // Only scan the value expression for cell vars
2528
- collect_cell_vars_from_expr(value, our_locals, cell_vars, interner);
2529
- }
2530
- Expr::Await(value) => {
2531
- collect_cell_vars_from_expr(value, our_locals, cell_vars, interner);
2532
- }
2533
- // Leaf expressions
2534
- Expr::Literal(_) | Expr::Builtin(_) | Expr::Name(_) | Expr::Lambda { .. } | Expr::Slice { .. } => {}
2535
- }
2536
- }
2537
-
2538
- /// Helper to collect cell vars from argument expressions.
2539
- fn collect_cell_vars_from_args(
2540
- args: &ArgExprs,
2541
- our_locals: &AHashSet<String>,
2542
- cell_vars: &mut AHashSet<String>,
2543
- interner: &InternerBuilder,
2544
- ) {
2545
- match args {
2546
- ArgExprs::Empty => {}
2547
- ArgExprs::One(arg) => collect_cell_vars_from_expr(arg, our_locals, cell_vars, interner),
2548
- ArgExprs::Two(arg1, arg2) => {
2549
- collect_cell_vars_from_expr(arg1, our_locals, cell_vars, interner);
2550
- collect_cell_vars_from_expr(arg2, our_locals, cell_vars, interner);
2551
- }
2552
- ArgExprs::Args(args) => {
2553
- for arg in args {
2554
- collect_cell_vars_from_expr(arg, our_locals, cell_vars, interner);
2555
- }
2556
- }
2557
- ArgExprs::Kwargs(kwargs) => {
2558
- for kwarg in kwargs {
2559
- collect_cell_vars_from_expr(&kwarg.value, our_locals, cell_vars, interner);
2560
- }
2561
- }
2562
- ArgExprs::ArgsKargs {
2563
- args,
2564
- kwargs,
2565
- var_args,
2566
- var_kwargs,
2567
- } => {
2568
- if let Some(args) = args {
2569
- for arg in args {
2570
- collect_cell_vars_from_expr(arg, our_locals, cell_vars, interner);
2571
- }
2572
- }
2573
- if let Some(kwargs) = kwargs {
2574
- for kwarg in kwargs {
2575
- collect_cell_vars_from_expr(&kwarg.value, our_locals, cell_vars, interner);
2576
- }
2577
- }
2578
- if let Some(var_args) = var_args {
2579
- collect_cell_vars_from_expr(var_args, our_locals, cell_vars, interner);
2580
- }
2581
- if let Some(var_kwargs) = var_kwargs {
2582
- collect_cell_vars_from_expr(var_kwargs, our_locals, cell_vars, interner);
2583
- }
2584
- }
2585
- ArgExprs::GeneralizedCall { args, kwargs } => {
2586
- for arg in args {
2587
- match arg {
2588
- CallArg::Value(e) | CallArg::Unpack(e) => {
2589
- collect_cell_vars_from_expr(e, our_locals, cell_vars, interner);
2590
- }
2591
- }
2592
- }
2593
- for kwarg in kwargs {
2594
- match kwarg {
2595
- CallKwarg::Named(kw) => {
2596
- collect_cell_vars_from_expr(&kw.value, our_locals, cell_vars, interner);
2597
- }
2598
- CallKwarg::Unpack(e) => {
2599
- collect_cell_vars_from_expr(e, our_locals, cell_vars, interner);
2600
- }
2601
- }
2602
- }
2603
- }
2604
- }
2605
- }
2606
-
2607
- /// Collects all names referenced (read) in a node and its descendants.
2608
- ///
2609
- /// This is used to find what names a nested function references from enclosing scopes.
2610
- fn collect_referenced_names_from_node(node: &ParseNode, referenced: &mut AHashSet<String>, interner: &InternerBuilder) {
2611
- match node {
2612
- Node::Expr(expr) => collect_referenced_names_from_expr(expr, referenced, interner),
2613
- Node::Return(expr) => collect_referenced_names_from_expr(expr, referenced, interner),
2614
- Node::Raise(Some(expr)) => collect_referenced_names_from_expr(expr, referenced, interner),
2615
- Node::Raise(None) => {}
2616
- Node::Assert { test, msg } => {
2617
- collect_referenced_names_from_expr(test, referenced, interner);
2618
- if let Some(m) = msg {
2619
- collect_referenced_names_from_expr(m, referenced, interner);
2620
- }
2621
- }
2622
- Node::Assign { object, .. } => {
2623
- collect_referenced_names_from_expr(object, referenced, interner);
2624
- }
2625
- Node::UnpackAssign { object, .. } => {
2626
- collect_referenced_names_from_expr(object, referenced, interner);
2627
- }
2628
- Node::OpAssign { target, object, .. } => {
2629
- // OpAssign reads the target before writing
2630
- referenced.insert(interner.get_str(target.name_id).to_string());
2631
- collect_referenced_names_from_expr(object, referenced, interner);
2632
- }
2633
- Node::SubscriptOpAssign {
2634
- target, index, object, ..
2635
- } => {
2636
- referenced.insert(interner.get_str(target.name_id).to_string());
2637
- collect_referenced_names_from_expr(index, referenced, interner);
2638
- collect_referenced_names_from_expr(object, referenced, interner);
2639
- }
2640
- Node::SubscriptAssign {
2641
- target, index, value, ..
2642
- } => {
2643
- referenced.insert(interner.get_str(target.name_id).to_string());
2644
- collect_referenced_names_from_expr(index, referenced, interner);
2645
- collect_referenced_names_from_expr(value, referenced, interner);
2646
- }
2647
- Node::AttrAssign { object, value, .. } => {
2648
- collect_referenced_names_from_expr(object, referenced, interner);
2649
- collect_referenced_names_from_expr(value, referenced, interner);
2650
- }
2651
- Node::For {
2652
- iter, body, or_else, ..
2653
- } => {
2654
- collect_referenced_names_from_expr(iter, referenced, interner);
2655
- for n in body {
2656
- collect_referenced_names_from_node(n, referenced, interner);
2657
- }
2658
- for n in or_else {
2659
- collect_referenced_names_from_node(n, referenced, interner);
2660
- }
2661
- }
2662
- Node::While { test, body, or_else } => {
2663
- collect_referenced_names_from_expr(test, referenced, interner);
2664
- for n in body {
2665
- collect_referenced_names_from_node(n, referenced, interner);
2666
- }
2667
- for n in or_else {
2668
- collect_referenced_names_from_node(n, referenced, interner);
2669
- }
2670
- }
2671
- Node::If { test, body, or_else } => {
2672
- collect_referenced_names_from_expr(test, referenced, interner);
2673
- for n in body {
2674
- collect_referenced_names_from_node(n, referenced, interner);
2675
- }
2676
- for n in or_else {
2677
- collect_referenced_names_from_node(n, referenced, interner);
2678
- }
2679
- }
2680
- Node::FunctionDef(_) => {
2681
- // Don't recurse into nested function bodies - they have their own scope
2682
- }
2683
- Node::Try(Try {
2684
- body,
2685
- handlers,
2686
- or_else,
2687
- finally,
2688
- }) => {
2689
- for n in body {
2690
- collect_referenced_names_from_node(n, referenced, interner);
2691
- }
2692
- for handler in handlers {
2693
- // Exception type expression may reference names
2694
- if let Some(ref exc_type) = handler.exc_type {
2695
- collect_referenced_names_from_expr(exc_type, referenced, interner);
2696
- }
2697
- for n in &handler.body {
2698
- collect_referenced_names_from_node(n, referenced, interner);
2699
- }
2700
- }
2701
- for n in or_else {
2702
- collect_referenced_names_from_node(n, referenced, interner);
2703
- }
2704
- for n in finally {
2705
- collect_referenced_names_from_node(n, referenced, interner);
2706
- }
2707
- }
2708
- // Imports create bindings but don't reference names
2709
- Node::Import { .. } | Node::ImportFrom { .. } => {}
2710
- Node::Pass
2711
- | Node::ReturnNone
2712
- | Node::Global { .. }
2713
- | Node::Nonlocal { .. }
2714
- | Node::Break { .. }
2715
- | Node::Continue { .. } => {}
2716
- }
2717
- }
2718
-
2719
- /// Collects all names referenced in an expression.
2720
- fn collect_referenced_names_from_expr(
2721
- expr: &crate::expressions::ExprLoc,
2722
- referenced: &mut AHashSet<String>,
2723
- interner: &InternerBuilder,
2724
- ) {
2725
- use crate::expressions::Expr;
2726
- match &expr.expr {
2727
- Expr::Name(ident) => {
2728
- referenced.insert(interner.get_str(ident.name_id).to_string());
2729
- }
2730
- Expr::Literal(_) => {}
2731
- Expr::Builtin(_) => {}
2732
- Expr::List(items) | Expr::Tuple(items) | Expr::Set(items) => {
2733
- for item in items {
2734
- let expr = match item {
2735
- SequenceItem::Value(e) | SequenceItem::Unpack(e) => e,
2736
- };
2737
- collect_referenced_names_from_expr(expr, referenced, interner);
2738
- }
2739
- }
2740
- Expr::Dict(dict_items) => {
2741
- for item in dict_items {
2742
- match item {
2743
- DictItem::Pair(key, value) => {
2744
- collect_referenced_names_from_expr(key, referenced, interner);
2745
- collect_referenced_names_from_expr(value, referenced, interner);
2746
- }
2747
- DictItem::Unpack(e) => collect_referenced_names_from_expr(e, referenced, interner),
2748
- }
2749
- }
2750
- }
2751
- Expr::Op { left, right, .. } | Expr::CmpOp { left, right, .. } => {
2752
- collect_referenced_names_from_expr(left, referenced, interner);
2753
- collect_referenced_names_from_expr(right, referenced, interner);
2754
- }
2755
- Expr::ChainCmp { left, comparisons } => {
2756
- collect_referenced_names_from_expr(left, referenced, interner);
2757
- for (_, expr) in comparisons {
2758
- collect_referenced_names_from_expr(expr, referenced, interner);
2759
- }
2760
- }
2761
- Expr::Not(operand) | Expr::UnaryMinus(operand) | Expr::UnaryPlus(operand) | Expr::UnaryInvert(operand) => {
2762
- collect_referenced_names_from_expr(operand, referenced, interner);
2763
- }
2764
- Expr::FString(parts) => {
2765
- collect_referenced_names_from_fstring_parts(parts, referenced, interner);
2766
- }
2767
- Expr::Subscript { object, index } => {
2768
- collect_referenced_names_from_expr(object, referenced, interner);
2769
- collect_referenced_names_from_expr(index, referenced, interner);
2770
- }
2771
- Expr::Call { callable, args } => {
2772
- // Check if the callable is a Name reference
2773
- if let Callable::Name(ident) = callable {
2774
- referenced.insert(interner.get_str(ident.name_id).to_string());
2775
- }
2776
- collect_referenced_names_from_args(args, referenced, interner);
2777
- }
2778
- Expr::AttrCall { object, args, .. } => {
2779
- collect_referenced_names_from_expr(object, referenced, interner);
2780
- collect_referenced_names_from_args(args, referenced, interner);
2781
- }
2782
- Expr::AttrGet { object, .. } => {
2783
- collect_referenced_names_from_expr(object, referenced, interner);
2784
- }
2785
- Expr::IndirectCall { callable, args } => {
2786
- // Collect references from the callable expression and arguments
2787
- collect_referenced_names_from_expr(callable, referenced, interner);
2788
- collect_referenced_names_from_args(args, referenced, interner);
2789
- }
2790
- Expr::IfElse { test, body, orelse } => {
2791
- collect_referenced_names_from_expr(test, referenced, interner);
2792
- collect_referenced_names_from_expr(body, referenced, interner);
2793
- collect_referenced_names_from_expr(orelse, referenced, interner);
2794
- }
2795
- Expr::ListComp { elt, generators } | Expr::SetComp { elt, generators } => {
2796
- collect_referenced_names_from_comprehension(generators, Some(elt), None, referenced, interner);
2797
- }
2798
- Expr::DictComp { key, value, generators } => {
2799
- collect_referenced_names_from_comprehension(generators, None, Some((key, value)), referenced, interner);
2800
- }
2801
- Expr::LambdaRaw { signature, body, .. } => {
2802
- // Build set of parameter names (these are local to the lambda, not free variables)
2803
- let lambda_params: AHashSet<String> = signature
2804
- .param_names()
2805
- .map(|s| interner.get_str(s).to_string())
2806
- .collect();
2807
-
2808
- // Collect references from the body expression into a temporary set
2809
- let mut body_refs: AHashSet<String> = AHashSet::new();
2810
- collect_referenced_names_from_expr(body, &mut body_refs, interner);
2811
-
2812
- // Filter out the lambda's own parameters before adding to referenced set.
2813
- // The lambda's parameters are bound by the lambda, not free from outer scope.
2814
- for name in body_refs {
2815
- if !lambda_params.contains(&name) {
2816
- referenced.insert(name);
2817
- }
2818
- }
2819
-
2820
- // Default value expressions are evaluated in the enclosing scope, not the lambda's
2821
- // scope, so they can reference outer scope without filtering.
2822
- for param in &signature.pos_args {
2823
- if let Some(ref default) = param.default {
2824
- collect_referenced_names_from_expr(default, referenced, interner);
2825
- }
2826
- }
2827
- for param in &signature.args {
2828
- if let Some(ref default) = param.default {
2829
- collect_referenced_names_from_expr(default, referenced, interner);
2830
- }
2831
- }
2832
- for param in &signature.kwargs {
2833
- if let Some(ref default) = param.default {
2834
- collect_referenced_names_from_expr(default, referenced, interner);
2835
- }
2836
- }
2837
- }
2838
- Expr::Lambda { .. } => {
2839
- // Lambda should only exist after preparation; this function operates on raw expressions
2840
- unreachable!("Expr::Lambda should not exist during scope analysis")
2841
- }
2842
- Expr::Named { value, .. } => {
2843
- // Only the value is referenced; target is being assigned, not read
2844
- collect_referenced_names_from_expr(value, referenced, interner);
2845
- }
2846
- Expr::Slice { lower, upper, step } => {
2847
- if let Some(expr) = lower {
2848
- collect_referenced_names_from_expr(expr, referenced, interner);
2849
- }
2850
- if let Some(expr) = upper {
2851
- collect_referenced_names_from_expr(expr, referenced, interner);
2852
- }
2853
- if let Some(expr) = step {
2854
- collect_referenced_names_from_expr(expr, referenced, interner);
2855
- }
2856
- }
2857
- Expr::Await(value) => {
2858
- collect_referenced_names_from_expr(value, referenced, interner);
2859
- }
2860
- }
2861
- }
2862
-
2863
- /// Collects referenced names from comprehension expressions.
2864
- ///
2865
- /// Handles the special scoping rules: loop variables are local to the comprehension,
2866
- /// so we collect references from iterators and conditions but exclude loop variable names.
2867
- fn collect_referenced_names_from_comprehension(
2868
- generators: &[Comprehension],
2869
- elt: Option<&ExprLoc>,
2870
- key_value: Option<(&ExprLoc, &ExprLoc)>,
2871
- referenced: &mut AHashSet<String>,
2872
- interner: &InternerBuilder,
2873
- ) {
2874
- // Track loop variable names (these are local to the comprehension)
2875
- let mut comp_locals: AHashSet<String> = AHashSet::new();
2876
-
2877
- // Collect references from expressions that can see prior loop variables.
2878
- // These need to be filtered against comp_locals before adding to referenced.
2879
- let mut inner_refs: AHashSet<String> = AHashSet::new();
2880
-
2881
- for (i, comp) in generators.iter().enumerate() {
2882
- if i == 0 {
2883
- // FIRST generator's iter expression truly references enclosing scope
2884
- // (evaluated before any loop variable is defined).
2885
- collect_referenced_names_from_expr(&comp.iter, referenced, interner);
2886
- } else {
2887
- // SUBSEQUENT generators' iter expressions can reference prior loop variables.
2888
- // For example, in `[y for x in xs for y in x]`, the `x` in the second
2889
- // generator's iter is the first generator's loop variable, not outer scope.
2890
- collect_referenced_names_from_expr(&comp.iter, &mut inner_refs, interner);
2891
- }
2892
-
2893
- // Add this generator's target(s) to local set
2894
- collect_names_from_unpack_target(&comp.target, &mut comp_locals, interner);
2895
-
2896
- // Filter conditions can see prior loop variables - collect separately
2897
- for cond in &comp.ifs {
2898
- collect_referenced_names_from_expr(cond, &mut inner_refs, interner);
2899
- }
2900
- }
2901
-
2902
- // Element expression(s) can see all loop variables - collect separately
2903
- if let Some(e) = elt {
2904
- collect_referenced_names_from_expr(e, &mut inner_refs, interner);
2905
- }
2906
- if let Some((k, v)) = key_value {
2907
- collect_referenced_names_from_expr(k, &mut inner_refs, interner);
2908
- collect_referenced_names_from_expr(v, &mut inner_refs, interner);
2909
- }
2910
-
2911
- // Add inner references that are NOT comprehension-locals to the outer referenced set.
2912
- // Names that ARE comp_locals refer to the comprehension's loop variable, not enclosing scope.
2913
- for name in inner_refs {
2914
- if !comp_locals.contains(&name) {
2915
- referenced.insert(name);
2916
- }
2917
- }
2918
- }
2919
-
2920
- /// Collects referenced names from argument expressions.
2921
- fn collect_referenced_names_from_args(args: &ArgExprs, referenced: &mut AHashSet<String>, interner: &InternerBuilder) {
2922
- match args {
2923
- ArgExprs::Empty => {}
2924
- ArgExprs::One(e) => collect_referenced_names_from_expr(e, referenced, interner),
2925
- ArgExprs::Two(e1, e2) => {
2926
- collect_referenced_names_from_expr(e1, referenced, interner);
2927
- collect_referenced_names_from_expr(e2, referenced, interner);
2928
- }
2929
- ArgExprs::Args(exprs) => {
2930
- for e in exprs {
2931
- collect_referenced_names_from_expr(e, referenced, interner);
2932
- }
2933
- }
2934
- ArgExprs::Kwargs(kwargs) => {
2935
- for kwarg in kwargs {
2936
- collect_referenced_names_from_expr(&kwarg.value, referenced, interner);
2937
- }
2938
- }
2939
- ArgExprs::ArgsKargs {
2940
- args,
2941
- kwargs,
2942
- var_args,
2943
- var_kwargs,
2944
- } => {
2945
- if let Some(args) = args {
2946
- for e in args {
2947
- collect_referenced_names_from_expr(e, referenced, interner);
2948
- }
2949
- }
2950
- if let Some(kwargs) = kwargs {
2951
- for kwarg in kwargs {
2952
- collect_referenced_names_from_expr(&kwarg.value, referenced, interner);
2953
- }
2954
- }
2955
- if let Some(e) = var_args {
2956
- collect_referenced_names_from_expr(e, referenced, interner);
2957
- }
2958
- if let Some(e) = var_kwargs {
2959
- collect_referenced_names_from_expr(e, referenced, interner);
2960
- }
2961
- }
2962
- ArgExprs::GeneralizedCall { args, kwargs } => {
2963
- for arg in args {
2964
- match arg {
2965
- CallArg::Value(e) | CallArg::Unpack(e) => {
2966
- collect_referenced_names_from_expr(e, referenced, interner);
2967
- }
2968
- }
2969
- }
2970
- for kwarg in kwargs {
2971
- match kwarg {
2972
- CallKwarg::Named(kw) => {
2973
- collect_referenced_names_from_expr(&kw.value, referenced, interner);
2974
- }
2975
- CallKwarg::Unpack(e) => {
2976
- collect_referenced_names_from_expr(e, referenced, interner);
2977
- }
2978
- }
2979
- }
2980
- }
2981
- }
2982
- }
2983
-
2984
- /// Collects referenced names from f-string parts (both expressions and dynamic format specs).
2985
- fn collect_referenced_names_from_fstring_parts(
2986
- parts: &[FStringPart],
2987
- referenced: &mut AHashSet<String>,
2988
- interner: &InternerBuilder,
2989
- ) {
2990
- for part in parts {
2991
- if let FStringPart::Interpolation { expr, format_spec, .. } = part {
2992
- collect_referenced_names_from_expr(expr, referenced, interner);
2993
- // Also check dynamic format specs which can contain interpolated expressions
2994
- if let Some(FormatSpec::Dynamic(spec_parts)) = format_spec {
2995
- collect_referenced_names_from_fstring_parts(spec_parts, referenced, interner);
2996
- }
2997
- }
2998
- }
2999
- }
3000
-
3001
- /// Collects all names from an unpack target into the given set.
3002
- ///
3003
- /// Recursively traverses nested tuples to find all identifier names.
3004
- fn collect_names_from_unpack_target(target: &UnpackTarget, names: &mut AHashSet<String>, interner: &InternerBuilder) {
3005
- match target {
3006
- UnpackTarget::Name(ident) | UnpackTarget::Starred(ident) => {
3007
- names.insert(interner.get_str(ident.name_id).to_string());
3008
- }
3009
- UnpackTarget::Tuple { targets, .. } => {
3010
- for t in targets {
3011
- collect_names_from_unpack_target(t, names, interner);
3012
- }
3013
- }
3014
- }
3015
- }