superacli 1.1.6 → 1.1.7

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 (1262) hide show
  1. package/README.md +77 -53
  2. package/__tests__/azd-plugin.test.js +109 -0
  3. package/__tests__/config.test.js +4 -3
  4. package/__tests__/discover.test.js +59 -0
  5. package/__tests__/goose-plugin.test.js +149 -0
  6. package/__tests__/help-json.test.js +2 -0
  7. package/__tests__/openhands-plugin.test.js +106 -0
  8. package/__tests__/plugin-cocoindex-code-uninstall.test.js +19 -0
  9. package/__tests__/plugin-cocoindex-code.test.js +37 -0
  10. package/__tests__/plugin-install-guidance.test.js +81 -0
  11. package/__tests__/plugins-registry.test.js +44 -0
  12. package/__tests__/plugins-store.test.js +40 -5
  13. package/__tests__/process-adapter.test.js +50 -1
  14. package/__tests__/server-app.test.js +1 -0
  15. package/__tests__/server-routes-commands.test.js +20 -2
  16. package/__tests__/server-routes-plugins.test.js +130 -0
  17. package/__tests__/skills.test.js +26 -0
  18. package/__tests__/squirrelscan-plugin.test.js +129 -0
  19. package/__tests__/uipath-plugin.test.js +104 -0
  20. package/__tests__/uipathcli-plugin.test.js +95 -0
  21. package/cli/adapters/mcp.js +2 -0
  22. package/cli/adapters/process.js +49 -2
  23. package/cli/config.js +240 -3
  24. package/cli/discover.js +157 -0
  25. package/cli/help-json.js +16 -1
  26. package/cli/plugin-install-guidance.js +92 -37
  27. package/cli/plugins-manager.js +1 -0
  28. package/cli/plugins-registry.js +74 -8
  29. package/cli/plugins-store.js +78 -17
  30. package/cli/skills-mcp.js +1 -1
  31. package/cli/skills.js +39 -2
  32. package/cli/supercli.js +87 -11
  33. package/docs/feature-gaps.md +8 -8
  34. package/docs/features/azd-uipath-plugins.md +43 -0
  35. package/docs/features/server-plugins.md +62 -0
  36. package/docs/features/skills.md +9 -5
  37. package/docs/{supported-harnesses.md → plugins-available.md} +4 -3
  38. package/docs/{plugin-harness-guide.md → plugins-how-to.md} +1 -1
  39. package/docs/plugins.md +26 -20
  40. package/docs/server-plugins-usage-guide.md +182 -0
  41. package/docs/skills-catalog.md +12 -10
  42. package/package.json +1 -1
  43. package/plugins/agent-browser/README.md +69 -0
  44. package/plugins/agent-browser/plugin.json +111 -0
  45. package/plugins/agent-browser/skills/quickstart/SKILL.md +66 -0
  46. package/plugins/aider/README.md +53 -0
  47. package/plugins/aider/plugin.json +105 -0
  48. package/plugins/aider/scripts/aider-wrapper.js +243 -0
  49. package/plugins/aider/scripts/setup-aider.js +37 -0
  50. package/plugins/aider/skills/dry-run-review.md +24 -0
  51. package/plugins/aider/skills/model-and-provider.md +24 -0
  52. package/plugins/aider/skills/one-shot-edits.md +30 -0
  53. package/plugins/aider/skills/quickstart/SKILL.md +51 -0
  54. package/plugins/azd/README.md +28 -0
  55. package/plugins/azd/plugin.json +87 -0
  56. package/plugins/azd/skills/quickstart/SKILL.md +41 -0
  57. package/plugins/blogwatcher/README.md +3 -3
  58. package/plugins/boxlite/Dockerfile +9 -0
  59. package/plugins/boxlite/README.md +62 -0
  60. package/plugins/boxlite/plugin.json +201 -0
  61. package/plugins/boxlite/scripts/run-boxlite.js +106 -0
  62. package/plugins/boxlite/skills/quickstart/SKILL.md +40 -0
  63. package/plugins/cass/plugin.json +150 -0
  64. package/plugins/cass/scripts/setup-cass.js +47 -0
  65. package/plugins/cass/skills/quickstart/SKILL.md +46 -0
  66. package/plugins/clever/README.md +46 -0
  67. package/plugins/clever/plugin.json +119 -0
  68. package/plugins/clever/scripts/setup-clever.js +28 -0
  69. package/plugins/clever/skills/auth-and-profile.md +29 -0
  70. package/plugins/clever/skills/passthrough-safety.md +21 -0
  71. package/plugins/clever/skills/quickstart/SKILL.md +45 -0
  72. package/plugins/clever/skills/resource-inventory.md +24 -0
  73. package/plugins/clix/README.md +4 -4
  74. package/plugins/cocoindex-code/README.md +64 -0
  75. package/plugins/cocoindex-code/plugin.json +81 -0
  76. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-310.pyc +0 -0
  77. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-311.pyc +0 -0
  78. package/plugins/cocoindex-code/scripts/post-install.js +61 -0
  79. package/plugins/cocoindex-code/scripts/post-uninstall.js +25 -0
  80. package/plugins/cocoindex-code/scripts/query.py +88 -0
  81. package/plugins/cocoindex-code/scripts/run-query.js +50 -0
  82. package/plugins/cocoindex-code/skills/quickstart/SKILL.md +73 -0
  83. package/plugins/copilot/README.md +24 -0
  84. package/plugins/copilot/plugin.json +80 -0
  85. package/plugins/copilot/skills/quickstart/SKILL.md +44 -0
  86. package/plugins/gemini/README.md +24 -0
  87. package/plugins/gemini/plugin.json +98 -0
  88. package/plugins/gemini/skills/quickstart/SKILL.md +44 -0
  89. package/plugins/gifcap/plugin.json +119 -0
  90. package/plugins/gifcap/scripts/setup-gifcap.js +44 -0
  91. package/plugins/gifcap/skills/quickstart/SKILL.md +34 -0
  92. package/plugins/gifcap/test-record-quiet.gif +0 -0
  93. package/plugins/gifcap/test-record.gif +0 -0
  94. package/plugins/goose/README.md +36 -0
  95. package/plugins/goose/plugin.json +183 -0
  96. package/plugins/goose/skills/quickstart/SKILL.md +44 -0
  97. package/plugins/json-server/README.md +58 -0
  98. package/plugins/json-server/plugin.json +113 -0
  99. package/plugins/json-server/skills/quickstart/SKILL.md +57 -0
  100. package/plugins/lightpanda/README.md +145 -0
  101. package/plugins/lightpanda/package-lock.json +1375 -0
  102. package/plugins/lightpanda/package.json +12 -0
  103. package/plugins/lightpanda/plugin.json +116 -0
  104. package/plugins/lightpanda/scripts/lightpanda-contacts.js +494 -0
  105. package/plugins/lightpanda/scripts/lightpanda-generic-extract.js +403 -0
  106. package/plugins/lightpanda/scripts/lightpanda-wrapper.js +480 -0
  107. package/plugins/lightpanda/scripts/setup-lightpanda.js +39 -0
  108. package/plugins/lightpanda/skills/contact-discovery.md +51 -0
  109. package/plugins/lightpanda/skills/generic-extraction.md +66 -0
  110. package/plugins/lightpanda/skills/quickstart/SKILL.md +103 -0
  111. package/plugins/lightpanda/skills/resilient-navigation.md +42 -0
  112. package/plugins/monty/README.md +2 -2
  113. package/plugins/nullclaw/README.md +3 -3
  114. package/plugins/offline-ai/README.md +23 -0
  115. package/plugins/offline-ai/plugin.json +82 -0
  116. package/plugins/offline-ai/skills/quickstart/SKILL.md +43 -0
  117. package/plugins/openhands/README.md +25 -0
  118. package/plugins/openhands/plugin.json +116 -0
  119. package/plugins/openhands/skills/quickstart/SKILL.md +26 -0
  120. package/plugins/plandex/README.md +25 -0
  121. package/plugins/plandex/plugin.json +130 -0
  122. package/plugins/plandex/skills/quickstart/SKILL.md +50 -0
  123. package/plugins/plugins.json +188 -0
  124. package/plugins/squirrelscan/Dockerfile +5 -0
  125. package/plugins/squirrelscan/README.md +47 -0
  126. package/plugins/squirrelscan/plugin.json +493 -0
  127. package/plugins/squirrelscan/scripts/post-install.js +33 -0
  128. package/plugins/squirrelscan/scripts/post-uninstall.js +25 -0
  129. package/plugins/squirrelscan/scripts/run-squirrel.js +73 -0
  130. package/plugins/squirrelscan/skills/audit-workflow/SKILL.md +33 -0
  131. package/plugins/squirrelscan/skills/publish-report/SKILL.md +33 -0
  132. package/plugins/squirrelscan/skills/quickstart/SKILL.md +41 -0
  133. package/plugins/uipath/README.md +27 -0
  134. package/plugins/uipath/plugin.json +86 -0
  135. package/plugins/uipath/skills/quickstart/SKILL.md +47 -0
  136. package/plugins/uipathcli/README.md +28 -0
  137. package/plugins/uipathcli/plugin.json +120 -0
  138. package/plugins/uipathcli/scripts/run-uipath-cli.js +49 -0
  139. package/plugins/uipathcli/skills/quickstart/SKILL.md +22 -0
  140. package/plugins/xurl/README.md +4 -4
  141. package/server/app.js +5 -2
  142. package/server/public/app.js +3 -0
  143. package/server/routes/commands.js +95 -12
  144. package/server/routes/plugins.js +262 -0
  145. package/server/services/pluginsService.js +303 -0
  146. package/server/views/command-edit.ejs +196 -14
  147. package/server/views/partials/head.ejs +1 -0
  148. package/server/views/plugins.ejs +264 -0
  149. package/tests/test-plugins-registry.js +30 -0
  150. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl +0 -20
  151. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl.meta.json +0 -1
  152. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl +0 -21
  153. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl.meta.json +0 -1
  154. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl +0 -22
  155. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl.meta.json +0 -1
  156. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl +0 -23
  157. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl.meta.json +0 -1
  158. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl +0 -24
  159. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl.meta.json +0 -1
  160. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl +0 -24
  161. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl.meta.json +0 -1
  162. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl +0 -24
  163. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl.meta.json +0 -1
  164. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl +0 -24
  165. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl.meta.json +0 -1
  166. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl +0 -24
  167. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl.meta.json +0 -1
  168. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl +0 -24
  169. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl.meta.json +0 -1
  170. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl +0 -24
  171. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl.meta.json +0 -1
  172. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl +0 -24
  173. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl.meta.json +0 -1
  174. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl +0 -24
  175. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl.meta.json +0 -1
  176. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl +0 -25
  177. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl.meta.json +0 -1
  178. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl +0 -25
  179. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl.meta.json +0 -1
  180. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl +0 -25
  181. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl.meta.json +0 -1
  182. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl +0 -26
  183. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl.meta.json +0 -1
  184. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl +0 -27
  185. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl.meta.json +0 -1
  186. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl +0 -28
  187. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl.meta.json +0 -1
  188. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl +0 -29
  189. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl.meta.json +0 -1
  190. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl +0 -30
  191. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl.meta.json +0 -1
  192. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl +0 -31
  193. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl.meta.json +0 -1
  194. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl +0 -32
  195. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl.meta.json +0 -1
  196. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl +0 -32
  197. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl.meta.json +0 -1
  198. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl +0 -32
  199. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl.meta.json +0 -1
  200. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl +0 -32
  201. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl.meta.json +0 -1
  202. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl +0 -32
  203. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl.meta.json +0 -1
  204. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl +0 -32
  205. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl.meta.json +0 -1
  206. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl +0 -32
  207. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl.meta.json +0 -1
  208. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl +0 -32
  209. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl.meta.json +0 -1
  210. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl +0 -32
  211. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl.meta.json +0 -1
  212. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl +0 -32
  213. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl.meta.json +0 -1
  214. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl +0 -32
  215. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl.meta.json +0 -1
  216. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl +0 -32
  217. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl.meta.json +0 -1
  218. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl +0 -32
  219. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl.meta.json +0 -1
  220. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl +0 -32
  221. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl.meta.json +0 -1
  222. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl +0 -33
  223. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl.meta.json +0 -1
  224. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl +0 -33
  225. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl.meta.json +0 -1
  226. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl +0 -34
  227. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl.meta.json +0 -1
  228. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl +0 -34
  229. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl.meta.json +0 -1
  230. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl +0 -35
  231. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl.meta.json +0 -1
  232. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl +0 -36
  233. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl.meta.json +0 -1
  234. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl +0 -37
  235. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl.meta.json +0 -1
  236. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl +0 -38
  237. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl.meta.json +0 -1
  238. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl +0 -39
  239. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl.meta.json +0 -1
  240. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl +0 -40
  241. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl.meta.json +0 -1
  242. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl +0 -41
  243. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl.meta.json +0 -1
  244. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl +0 -42
  245. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl.meta.json +0 -1
  246. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl +0 -43
  247. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl.meta.json +0 -1
  248. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl +0 -44
  249. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl.meta.json +0 -1
  250. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl +0 -45
  251. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl.meta.json +0 -1
  252. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl +0 -46
  253. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl.meta.json +0 -1
  254. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl +0 -47
  255. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl.meta.json +0 -1
  256. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl +0 -48
  257. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl.meta.json +0 -1
  258. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl +0 -49
  259. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl.meta.json +0 -1
  260. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl +0 -50
  261. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl.meta.json +0 -1
  262. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl +0 -51
  263. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl.meta.json +0 -1
  264. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl +0 -52
  265. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl.meta.json +0 -1
  266. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl +0 -53
  267. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl.meta.json +0 -1
  268. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl +0 -54
  269. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl.meta.json +0 -1
  270. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl +0 -55
  271. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl.meta.json +0 -1
  272. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl +0 -56
  273. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl.meta.json +0 -1
  274. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl +0 -57
  275. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl.meta.json +0 -1
  276. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl +0 -57
  277. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl.meta.json +0 -1
  278. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl +0 -57
  279. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl.meta.json +0 -1
  280. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl +0 -57
  281. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl.meta.json +0 -1
  282. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl +0 -57
  283. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl.meta.json +0 -1
  284. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl +0 -57
  285. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl.meta.json +0 -1
  286. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl +0 -57
  287. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl.meta.json +0 -1
  288. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl +0 -57
  289. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl.meta.json +0 -1
  290. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl +0 -57
  291. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl.meta.json +0 -1
  292. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl +0 -57
  293. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl.meta.json +0 -1
  294. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl +0 -57
  295. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl.meta.json +0 -1
  296. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl +0 -57
  297. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl.meta.json +0 -1
  298. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl +0 -57
  299. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl.meta.json +0 -1
  300. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl +0 -57
  301. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl.meta.json +0 -1
  302. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl +0 -57
  303. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl.meta.json +0 -1
  304. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl +0 -57
  305. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl.meta.json +0 -1
  306. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl +0 -57
  307. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl.meta.json +0 -1
  308. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl +0 -57
  309. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl.meta.json +0 -1
  310. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl +0 -57
  311. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl.meta.json +0 -1
  312. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl +0 -57
  313. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl.meta.json +0 -1
  314. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl +0 -57
  315. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl.meta.json +0 -1
  316. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl +0 -57
  317. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl.meta.json +0 -1
  318. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl +0 -57
  319. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl.meta.json +0 -1
  320. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl +0 -57
  321. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl.meta.json +0 -1
  322. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl +0 -57
  323. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl.meta.json +0 -1
  324. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl +0 -57
  325. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl.meta.json +0 -1
  326. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl +0 -57
  327. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl.meta.json +0 -1
  328. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl +0 -57
  329. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl.meta.json +0 -1
  330. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl +0 -57
  331. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl.meta.json +0 -1
  332. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl +0 -57
  333. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl.meta.json +0 -1
  334. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl +0 -58
  335. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl.meta.json +0 -1
  336. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl +0 -59
  337. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl.meta.json +0 -1
  338. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl +0 -60
  339. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl.meta.json +0 -1
  340. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl +0 -60
  341. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl.meta.json +0 -1
  342. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl +0 -60
  343. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl.meta.json +0 -1
  344. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl +0 -60
  345. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl.meta.json +0 -1
  346. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl +0 -60
  347. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl.meta.json +0 -1
  348. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl +0 -60
  349. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl.meta.json +0 -1
  350. package/.beads/config.yaml +0 -4
  351. package/.beads/issues.jsonl +0 -60
  352. package/.beads/metadata.json +0 -4
  353. package/docs/mcp-cheatsheet.md +0 -324
  354. package/docs/visual-overview.md +0 -21
  355. package/ref-monty/.cargo/config.toml +0 -3
  356. package/ref-monty/.claude/settings.json +0 -60
  357. package/ref-monty/.claude/skills/fastmod/SKILL.md +0 -22
  358. package/ref-monty/.claude/skills/python-playground/SKILL.md +0 -47
  359. package/ref-monty/.codecov.yml +0 -12
  360. package/ref-monty/.github/actions/build-pgo-wheel/action.yml +0 -72
  361. package/ref-monty/.github/workflows/ci.yml +0 -776
  362. package/ref-monty/.github/workflows/codspeed.yml +0 -45
  363. package/ref-monty/.github/workflows/init-npm-packages.yml +0 -82
  364. package/ref-monty/.pre-commit-config.yaml +0 -47
  365. package/ref-monty/.python-version +0 -1
  366. package/ref-monty/.rustfmt.toml +0 -4
  367. package/ref-monty/.zed/settings.json +0 -11
  368. package/ref-monty/CLAUDE.md +0 -535
  369. package/ref-monty/Cargo.lock +0 -3798
  370. package/ref-monty/Cargo.toml +0 -87
  371. package/ref-monty/LICENSE +0 -21
  372. package/ref-monty/Makefile +0 -216
  373. package/ref-monty/README.md +0 -430
  374. package/ref-monty/RELEASING.md +0 -47
  375. package/ref-monty/crates/fuzz/Cargo.toml +0 -30
  376. package/ref-monty/crates/fuzz/fuzz_targets/string_input_panic.rs +0 -37
  377. package/ref-monty/crates/fuzz/fuzz_targets/tokens_input_panic.rs +0 -552
  378. package/ref-monty/crates/monty/Cargo.toml +0 -68
  379. package/ref-monty/crates/monty/benches/main.rs +0 -247
  380. package/ref-monty/crates/monty/build.rs +0 -10
  381. package/ref-monty/crates/monty/src/args.rs +0 -733
  382. package/ref-monty/crates/monty/src/asyncio.rs +0 -179
  383. package/ref-monty/crates/monty/src/builtins/abs.rs +0 -55
  384. package/ref-monty/crates/monty/src/builtins/all.rs +0 -30
  385. package/ref-monty/crates/monty/src/builtins/any.rs +0 -30
  386. package/ref-monty/crates/monty/src/builtins/bin.rs +0 -59
  387. package/ref-monty/crates/monty/src/builtins/chr.rs +0 -46
  388. package/ref-monty/crates/monty/src/builtins/divmod.rs +0 -164
  389. package/ref-monty/crates/monty/src/builtins/enumerate.rs +0 -52
  390. package/ref-monty/crates/monty/src/builtins/filter.rs +0 -67
  391. package/ref-monty/crates/monty/src/builtins/getattr.rs +0 -65
  392. package/ref-monty/crates/monty/src/builtins/hash.rs +0 -28
  393. package/ref-monty/crates/monty/src/builtins/hex.rs +0 -58
  394. package/ref-monty/crates/monty/src/builtins/id.rs +0 -24
  395. package/ref-monty/crates/monty/src/builtins/isinstance.rs +0 -68
  396. package/ref-monty/crates/monty/src/builtins/len.rs +0 -25
  397. package/ref-monty/crates/monty/src/builtins/map.rs +0 -98
  398. package/ref-monty/crates/monty/src/builtins/min_max.rs +0 -113
  399. package/ref-monty/crates/monty/src/builtins/mod.rs +0 -246
  400. package/ref-monty/crates/monty/src/builtins/next.rs +0 -21
  401. package/ref-monty/crates/monty/src/builtins/oct.rs +0 -59
  402. package/ref-monty/crates/monty/src/builtins/ord.rs +0 -67
  403. package/ref-monty/crates/monty/src/builtins/pow.rs +0 -365
  404. package/ref-monty/crates/monty/src/builtins/print.rs +0 -141
  405. package/ref-monty/crates/monty/src/builtins/repr.rs +0 -16
  406. package/ref-monty/crates/monty/src/builtins/reversed.rs +0 -28
  407. package/ref-monty/crates/monty/src/builtins/round.rs +0 -174
  408. package/ref-monty/crates/monty/src/builtins/sorted.rs +0 -151
  409. package/ref-monty/crates/monty/src/builtins/sum.rs +0 -66
  410. package/ref-monty/crates/monty/src/builtins/type_.rs +0 -16
  411. package/ref-monty/crates/monty/src/builtins/zip.rs +0 -77
  412. package/ref-monty/crates/monty/src/bytecode/builder.rs +0 -699
  413. package/ref-monty/crates/monty/src/bytecode/code.rs +0 -310
  414. package/ref-monty/crates/monty/src/bytecode/compiler.rs +0 -3206
  415. package/ref-monty/crates/monty/src/bytecode/mod.rs +0 -24
  416. package/ref-monty/crates/monty/src/bytecode/op.rs +0 -617
  417. package/ref-monty/crates/monty/src/bytecode/vm/async_exec.rs +0 -1058
  418. package/ref-monty/crates/monty/src/bytecode/vm/attr.rs +0 -63
  419. package/ref-monty/crates/monty/src/bytecode/vm/binary.rs +0 -487
  420. package/ref-monty/crates/monty/src/bytecode/vm/call.rs +0 -767
  421. package/ref-monty/crates/monty/src/bytecode/vm/collections.rs +0 -741
  422. package/ref-monty/crates/monty/src/bytecode/vm/compare.rs +0 -147
  423. package/ref-monty/crates/monty/src/bytecode/vm/exceptions.rs +0 -297
  424. package/ref-monty/crates/monty/src/bytecode/vm/format.rs +0 -132
  425. package/ref-monty/crates/monty/src/bytecode/vm/mod.rs +0 -1958
  426. package/ref-monty/crates/monty/src/bytecode/vm/scheduler.rs +0 -620
  427. package/ref-monty/crates/monty/src/exception_private.rs +0 -1513
  428. package/ref-monty/crates/monty/src/exception_public.rs +0 -346
  429. package/ref-monty/crates/monty/src/expressions.rs +0 -694
  430. package/ref-monty/crates/monty/src/fstring.rs +0 -854
  431. package/ref-monty/crates/monty/src/function.rs +0 -119
  432. package/ref-monty/crates/monty/src/heap.rs +0 -1073
  433. package/ref-monty/crates/monty/src/heap_data.rs +0 -985
  434. package/ref-monty/crates/monty/src/heap_traits.rs +0 -312
  435. package/ref-monty/crates/monty/src/intern.rs +0 -837
  436. package/ref-monty/crates/monty/src/io.rs +0 -106
  437. package/ref-monty/crates/monty/src/lib.rs +0 -52
  438. package/ref-monty/crates/monty/src/modules/asyncio.rs +0 -144
  439. package/ref-monty/crates/monty/src/modules/math.rs +0 -1453
  440. package/ref-monty/crates/monty/src/modules/mod.rs +0 -120
  441. package/ref-monty/crates/monty/src/modules/os.rs +0 -116
  442. package/ref-monty/crates/monty/src/modules/pathlib.rs +0 -33
  443. package/ref-monty/crates/monty/src/modules/re.rs +0 -606
  444. package/ref-monty/crates/monty/src/modules/sys.rs +0 -60
  445. package/ref-monty/crates/monty/src/modules/typing.rs +0 -70
  446. package/ref-monty/crates/monty/src/namespace.rs +0 -21
  447. package/ref-monty/crates/monty/src/object.rs +0 -1040
  448. package/ref-monty/crates/monty/src/os.rs +0 -215
  449. package/ref-monty/crates/monty/src/parse.rs +0 -1730
  450. package/ref-monty/crates/monty/src/prepare.rs +0 -3015
  451. package/ref-monty/crates/monty/src/repl.rs +0 -1109
  452. package/ref-monty/crates/monty/src/resource.rs +0 -559
  453. package/ref-monty/crates/monty/src/run.rs +0 -457
  454. package/ref-monty/crates/monty/src/run_progress.rs +0 -821
  455. package/ref-monty/crates/monty/src/signature.rs +0 -651
  456. package/ref-monty/crates/monty/src/sorting.rs +0 -100
  457. package/ref-monty/crates/monty/src/types/bytes.rs +0 -2356
  458. package/ref-monty/crates/monty/src/types/dataclass.rs +0 -345
  459. package/ref-monty/crates/monty/src/types/dict.rs +0 -879
  460. package/ref-monty/crates/monty/src/types/dict_view.rs +0 -619
  461. package/ref-monty/crates/monty/src/types/iter.rs +0 -799
  462. package/ref-monty/crates/monty/src/types/list.rs +0 -929
  463. package/ref-monty/crates/monty/src/types/long_int.rs +0 -211
  464. package/ref-monty/crates/monty/src/types/mod.rs +0 -48
  465. package/ref-monty/crates/monty/src/types/module.rs +0 -146
  466. package/ref-monty/crates/monty/src/types/namedtuple.rs +0 -261
  467. package/ref-monty/crates/monty/src/types/path.rs +0 -596
  468. package/ref-monty/crates/monty/src/types/property.rs +0 -35
  469. package/ref-monty/crates/monty/src/types/py_trait.rs +0 -322
  470. package/ref-monty/crates/monty/src/types/range.rs +0 -285
  471. package/ref-monty/crates/monty/src/types/re_match.rs +0 -522
  472. package/ref-monty/crates/monty/src/types/re_pattern.rs +0 -726
  473. package/ref-monty/crates/monty/src/types/set.rs +0 -1373
  474. package/ref-monty/crates/monty/src/types/slice.rs +0 -257
  475. package/ref-monty/crates/monty/src/types/str.rs +0 -2051
  476. package/ref-monty/crates/monty/src/types/tuple.rs +0 -376
  477. package/ref-monty/crates/monty/src/types/type.rs +0 -407
  478. package/ref-monty/crates/monty/src/value.rs +0 -2558
  479. package/ref-monty/crates/monty/test_cases/args__dict_get_no_args.py +0 -3
  480. package/ref-monty/crates/monty/test_cases/args__dict_get_too_many.py +0 -3
  481. package/ref-monty/crates/monty/test_cases/args__dict_items_with_args.py +0 -3
  482. package/ref-monty/crates/monty/test_cases/args__dict_keys_with_args.py +0 -3
  483. package/ref-monty/crates/monty/test_cases/args__dict_pop_no_args.py +0 -3
  484. package/ref-monty/crates/monty/test_cases/args__dict_pop_too_many.py +0 -3
  485. package/ref-monty/crates/monty/test_cases/args__dict_values_with_args.py +0 -3
  486. package/ref-monty/crates/monty/test_cases/args__id_too_many.py +0 -2
  487. package/ref-monty/crates/monty/test_cases/args__len_no_args.py +0 -2
  488. package/ref-monty/crates/monty/test_cases/args__len_too_many.py +0 -2
  489. package/ref-monty/crates/monty/test_cases/args__len_type_error_int.py +0 -9
  490. package/ref-monty/crates/monty/test_cases/args__len_type_error_none.py +0 -9
  491. package/ref-monty/crates/monty/test_cases/args__list_append_no_args.py +0 -3
  492. package/ref-monty/crates/monty/test_cases/args__list_append_too_many.py +0 -3
  493. package/ref-monty/crates/monty/test_cases/args__list_insert_too_few.py +0 -3
  494. package/ref-monty/crates/monty/test_cases/args__list_insert_too_many.py +0 -3
  495. package/ref-monty/crates/monty/test_cases/args__repr_no_args.py +0 -2
  496. package/ref-monty/crates/monty/test_cases/arith__div_zero_float.py +0 -2
  497. package/ref-monty/crates/monty/test_cases/arith__div_zero_int.py +0 -2
  498. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_float.py +0 -2
  499. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_int.py +0 -2
  500. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg.py +0 -2
  501. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg_builtin.py +0 -9
  502. package/ref-monty/crates/monty/test_cases/assert__expr_fail.py +0 -2
  503. package/ref-monty/crates/monty/test_cases/assert__fail.py +0 -2
  504. package/ref-monty/crates/monty/test_cases/assert__fail_msg.py +0 -2
  505. package/ref-monty/crates/monty/test_cases/assert__fn_fail.py +0 -3
  506. package/ref-monty/crates/monty/test_cases/assert__ops.py +0 -11
  507. package/ref-monty/crates/monty/test_cases/async__asyncio_run.py +0 -47
  508. package/ref-monty/crates/monty/test_cases/async__basic.py +0 -10
  509. package/ref-monty/crates/monty/test_cases/async__closure.py +0 -14
  510. package/ref-monty/crates/monty/test_cases/async__double_await_coroutine.py +0 -16
  511. package/ref-monty/crates/monty/test_cases/async__exception.py +0 -10
  512. package/ref-monty/crates/monty/test_cases/async__ext_call.py +0 -73
  513. package/ref-monty/crates/monty/test_cases/async__gather_all.py +0 -85
  514. package/ref-monty/crates/monty/test_cases/async__nested_await.py +0 -15
  515. package/ref-monty/crates/monty/test_cases/async__nested_gather_ext.py +0 -37
  516. package/ref-monty/crates/monty/test_cases/async__not_awaitable.py +0 -10
  517. package/ref-monty/crates/monty/test_cases/async__not_imported.py +0 -14
  518. package/ref-monty/crates/monty/test_cases/async__recursion_depth_isolation.py +0 -27
  519. package/ref-monty/crates/monty/test_cases/async__return_types.py +0 -31
  520. package/ref-monty/crates/monty/test_cases/async__sequential.py +0 -16
  521. package/ref-monty/crates/monty/test_cases/async__traceback.py +0 -19
  522. package/ref-monty/crates/monty/test_cases/async__with_args.py +0 -14
  523. package/ref-monty/crates/monty/test_cases/attr__get_int_error.py +0 -9
  524. package/ref-monty/crates/monty/test_cases/attr__get_list_error.py +0 -9
  525. package/ref-monty/crates/monty/test_cases/attr__set_frozen_nonfield.py +0 -12
  526. package/ref-monty/crates/monty/test_cases/attr__set_int_error.py +0 -10
  527. package/ref-monty/crates/monty/test_cases/attr__set_list_error.py +0 -10
  528. package/ref-monty/crates/monty/test_cases/bench__kitchen_sink.py +0 -68
  529. package/ref-monty/crates/monty/test_cases/bool__ops.py +0 -20
  530. package/ref-monty/crates/monty/test_cases/builtin__add_type_error.py +0 -2
  531. package/ref-monty/crates/monty/test_cases/builtin__filter.py +0 -62
  532. package/ref-monty/crates/monty/test_cases/builtin__filter_not_iterable.py +0 -11
  533. package/ref-monty/crates/monty/test_cases/builtin__getattr.py +0 -84
  534. package/ref-monty/crates/monty/test_cases/builtin__iter_funcs.py +0 -42
  535. package/ref-monty/crates/monty/test_cases/builtin__iter_next.py +0 -66
  536. package/ref-monty/crates/monty/test_cases/builtin__map.py +0 -74
  537. package/ref-monty/crates/monty/test_cases/builtin__map_not_iterable.py +0 -11
  538. package/ref-monty/crates/monty/test_cases/builtin__math_funcs.py +0 -154
  539. package/ref-monty/crates/monty/test_cases/builtin__more_iter_funcs.py +0 -148
  540. package/ref-monty/crates/monty/test_cases/builtin__next_stop_iteration.py +0 -10
  541. package/ref-monty/crates/monty/test_cases/builtin__print_invalid_kwarg.py +0 -9
  542. package/ref-monty/crates/monty/test_cases/builtin__print_kwargs.py +0 -12
  543. package/ref-monty/crates/monty/test_cases/builtin__repr.py +0 -3
  544. package/ref-monty/crates/monty/test_cases/builtin__string_funcs.py +0 -73
  545. package/ref-monty/crates/monty/test_cases/bytes__decode_invalid_utf8.py +0 -18
  546. package/ref-monty/crates/monty/test_cases/bytes__endswith_str_error.py +0 -10
  547. package/ref-monty/crates/monty/test_cases/bytes__getitem_index_error.py +0 -10
  548. package/ref-monty/crates/monty/test_cases/bytes__index_start_gt_end.py +0 -10
  549. package/ref-monty/crates/monty/test_cases/bytes__methods.py +0 -394
  550. package/ref-monty/crates/monty/test_cases/bytes__negative_count.py +0 -9
  551. package/ref-monty/crates/monty/test_cases/bytes__ops.py +0 -90
  552. package/ref-monty/crates/monty/test_cases/bytes__startswith_str_error.py +0 -10
  553. package/ref-monty/crates/monty/test_cases/call_object.py +0 -3
  554. package/ref-monty/crates/monty/test_cases/chain_comparison__all.py +0 -79
  555. package/ref-monty/crates/monty/test_cases/closure__param_shadows_outer.py +0 -81
  556. package/ref-monty/crates/monty/test_cases/closure__pep448.py +0 -203
  557. package/ref-monty/crates/monty/test_cases/closure__undefined_nonlocal.py +0 -13
  558. package/ref-monty/crates/monty/test_cases/compare__mixed_types.py +0 -120
  559. package/ref-monty/crates/monty/test_cases/comprehension__all.py +0 -208
  560. package/ref-monty/crates/monty/test_cases/comprehension__scope.py +0 -7
  561. package/ref-monty/crates/monty/test_cases/comprehension__unbound_local.py +0 -14
  562. package/ref-monty/crates/monty/test_cases/dataclass__basic.py +0 -238
  563. package/ref-monty/crates/monty/test_cases/dataclass__call_field_error.py +0 -12
  564. package/ref-monty/crates/monty/test_cases/dataclass__frozen_set_error.py +0 -12
  565. package/ref-monty/crates/monty/test_cases/dataclass__get_missing_attr_error.py +0 -11
  566. package/ref-monty/crates/monty/test_cases/dict__get_unhashable_key.py +0 -3
  567. package/ref-monty/crates/monty/test_cases/dict__literal_unhashable_key.py +0 -2
  568. package/ref-monty/crates/monty/test_cases/dict__method_pop_missing_error.py +0 -3
  569. package/ref-monty/crates/monty/test_cases/dict__methods.py +0 -151
  570. package/ref-monty/crates/monty/test_cases/dict__ops.py +0 -133
  571. package/ref-monty/crates/monty/test_cases/dict__pop_unhashable_key.py +0 -4
  572. package/ref-monty/crates/monty/test_cases/dict__popitem_empty.py +0 -9
  573. package/ref-monty/crates/monty/test_cases/dict__subscript_missing_key.py +0 -3
  574. package/ref-monty/crates/monty/test_cases/dict__unhashable_dict_key.py +0 -2
  575. package/ref-monty/crates/monty/test_cases/dict__unhashable_list_key.py +0 -2
  576. package/ref-monty/crates/monty/test_cases/dict__unpack_type_error.py +0 -2
  577. package/ref-monty/crates/monty/test_cases/dict__views.py +0 -165
  578. package/ref-monty/crates/monty/test_cases/edge__all.py +0 -26
  579. package/ref-monty/crates/monty/test_cases/edge__float_int_mod.py +0 -2
  580. package/ref-monty/crates/monty/test_cases/edge__int_float_mod.py +0 -2
  581. package/ref-monty/crates/monty/test_cases/exc__args.py +0 -16
  582. package/ref-monty/crates/monty/test_cases/exc__str.py +0 -15
  583. package/ref-monty/crates/monty/test_cases/execute_ok__all.py +0 -54
  584. package/ref-monty/crates/monty/test_cases/execute_raise__error_instance_str.py +0 -2
  585. package/ref-monty/crates/monty/test_cases/execute_raise__error_no_args.py +0 -2
  586. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg.py +0 -2
  587. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg_quotes.py +0 -2
  588. package/ref-monty/crates/monty/test_cases/execute_raise__error_type.py +0 -2
  589. package/ref-monty/crates/monty/test_cases/execute_raise__raise_instance_via_var.py +0 -4
  590. package/ref-monty/crates/monty/test_cases/execute_raise__raise_list.py +0 -2
  591. package/ref-monty/crates/monty/test_cases/execute_raise__raise_number.py +0 -2
  592. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_call_via_var.py +0 -4
  593. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_direct.py +0 -3
  594. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_via_var.py +0 -4
  595. package/ref-monty/crates/monty/test_cases/ext_call__arg_side_effect_bug.py +0 -22
  596. package/ref-monty/crates/monty/test_cases/ext_call__augmented.py +0 -17
  597. package/ref-monty/crates/monty/test_cases/ext_call__augmented_refcount_bug.py +0 -7
  598. package/ref-monty/crates/monty/test_cases/ext_call__bare_raise_after_resume.py +0 -34
  599. package/ref-monty/crates/monty/test_cases/ext_call__basic.py +0 -99
  600. package/ref-monty/crates/monty/test_cases/ext_call__boolean.py +0 -37
  601. package/ref-monty/crates/monty/test_cases/ext_call__boolean_side_effect_hang.py +0 -17
  602. package/ref-monty/crates/monty/test_cases/ext_call__closure_bug.py +0 -16
  603. package/ref-monty/crates/monty/test_cases/ext_call__comparison.py +0 -26
  604. package/ref-monty/crates/monty/test_cases/ext_call__deep_call_stack.py +0 -18
  605. package/ref-monty/crates/monty/test_cases/ext_call__elif.py +0 -171
  606. package/ref-monty/crates/monty/test_cases/ext_call__exc.py +0 -4
  607. package/ref-monty/crates/monty/test_cases/ext_call__exc_deep_stack.py +0 -39
  608. package/ref-monty/crates/monty/test_cases/ext_call__exc_in_function.py +0 -17
  609. package/ref-monty/crates/monty/test_cases/ext_call__exc_nested_functions.py +0 -31
  610. package/ref-monty/crates/monty/test_cases/ext_call__ext_exc.py +0 -171
  611. package/ref-monty/crates/monty/test_cases/ext_call__for.py +0 -114
  612. package/ref-monty/crates/monty/test_cases/ext_call__fstring.py +0 -12
  613. package/ref-monty/crates/monty/test_cases/ext_call__if.py +0 -135
  614. package/ref-monty/crates/monty/test_cases/ext_call__if_condition.py +0 -37
  615. package/ref-monty/crates/monty/test_cases/ext_call__in_closure.py +0 -14
  616. package/ref-monty/crates/monty/test_cases/ext_call__in_function.py +0 -40
  617. package/ref-monty/crates/monty/test_cases/ext_call__in_function_simple.py +0 -7
  618. package/ref-monty/crates/monty/test_cases/ext_call__literals.py +0 -17
  619. package/ref-monty/crates/monty/test_cases/ext_call__multi_in_func.py +0 -32
  620. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup.py +0 -69
  621. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup_undefined.py +0 -4
  622. package/ref-monty/crates/monty/test_cases/ext_call__nested_calls.py +0 -14
  623. package/ref-monty/crates/monty/test_cases/ext_call__recursion_bug.py +0 -19
  624. package/ref-monty/crates/monty/test_cases/ext_call__return.py +0 -28
  625. package/ref-monty/crates/monty/test_cases/ext_call__side_effects.py +0 -25
  626. package/ref-monty/crates/monty/test_cases/ext_call__subscript.py +0 -7
  627. package/ref-monty/crates/monty/test_cases/ext_call__ternary.py +0 -28
  628. package/ref-monty/crates/monty/test_cases/ext_call__try.py +0 -280
  629. package/ref-monty/crates/monty/test_cases/ext_call__try_simple.py +0 -10
  630. package/ref-monty/crates/monty/test_cases/ext_call__unary.py +0 -13
  631. package/ref-monty/crates/monty/test_cases/frozenset__ops.py +0 -178
  632. package/ref-monty/crates/monty/test_cases/fstring__all.py +0 -236
  633. package/ref-monty/crates/monty/test_cases/fstring__error_eq_align_on_str.py +0 -3
  634. package/ref-monty/crates/monty/test_cases/fstring__error_float_f_on_str.py +0 -3
  635. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_float.py +0 -3
  636. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_str.py +0 -3
  637. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec.py +0 -4
  638. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_dynamic.py +0 -4
  639. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_str.py +0 -4
  640. package/ref-monty/crates/monty/test_cases/fstring__error_str_s_on_int.py +0 -3
  641. package/ref-monty/crates/monty/test_cases/function__call_duplicate_kwargs.py +0 -6
  642. package/ref-monty/crates/monty/test_cases/function__call_unpack.py +0 -42
  643. package/ref-monty/crates/monty/test_cases/function__defaults.py +0 -117
  644. package/ref-monty/crates/monty/test_cases/function__err_duplicate_arg.py +0 -7
  645. package/ref-monty/crates/monty/test_cases/function__err_duplicate_first_arg.py +0 -7
  646. package/ref-monty/crates/monty/test_cases/function__err_duplicate_kwarg_cleanup.py +0 -9
  647. package/ref-monty/crates/monty/test_cases/function__err_kwonly_as_positional.py +0 -7
  648. package/ref-monty/crates/monty/test_cases/function__err_missing_all_posonly.py +0 -7
  649. package/ref-monty/crates/monty/test_cases/function__err_missing_heap_cleanup.py +0 -9
  650. package/ref-monty/crates/monty/test_cases/function__err_missing_kwonly.py +0 -7
  651. package/ref-monty/crates/monty/test_cases/function__err_missing_posonly_with_kwarg.py +0 -7
  652. package/ref-monty/crates/monty/test_cases/function__err_missing_with_posonly.py +0 -7
  653. package/ref-monty/crates/monty/test_cases/function__err_posonly_as_kwarg.py +0 -7
  654. package/ref-monty/crates/monty/test_cases/function__err_posonly_first_as_kwarg.py +0 -7
  655. package/ref-monty/crates/monty/test_cases/function__err_too_many_posonly.py +0 -7
  656. package/ref-monty/crates/monty/test_cases/function__err_too_many_with_kwonly.py +0 -7
  657. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg.py +0 -7
  658. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_cleanup.py +0 -9
  659. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_quote.py +0 -13
  660. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_simple.py +0 -7
  661. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_arg.py +0 -6
  662. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_heap.py +0 -8
  663. package/ref-monty/crates/monty/test_cases/function__err_unpack_int.py +0 -6
  664. package/ref-monty/crates/monty/test_cases/function__err_unpack_nonstring_key.py +0 -6
  665. package/ref-monty/crates/monty/test_cases/function__err_unpack_not_mapping.py +0 -6
  666. package/ref-monty/crates/monty/test_cases/function__kwargs_unpacking.py +0 -173
  667. package/ref-monty/crates/monty/test_cases/function__ops.py +0 -294
  668. package/ref-monty/crates/monty/test_cases/function__return_none.py +0 -42
  669. package/ref-monty/crates/monty/test_cases/function__signatures.py +0 -47
  670. package/ref-monty/crates/monty/test_cases/function__too_few_args_all.py +0 -6
  671. package/ref-monty/crates/monty/test_cases/function__too_few_args_one.py +0 -6
  672. package/ref-monty/crates/monty/test_cases/function__too_few_args_two.py +0 -6
  673. package/ref-monty/crates/monty/test_cases/function__too_many_args_one.py +0 -6
  674. package/ref-monty/crates/monty/test_cases/function__too_many_args_two.py +0 -6
  675. package/ref-monty/crates/monty/test_cases/function__too_many_args_zero.py +0 -6
  676. package/ref-monty/crates/monty/test_cases/global__error_assigned_before.py +0 -7
  677. package/ref-monty/crates/monty/test_cases/global__ops.py +0 -163
  678. package/ref-monty/crates/monty/test_cases/hash__dict_unhashable.py +0 -2
  679. package/ref-monty/crates/monty/test_cases/hash__list_unhashable.py +0 -2
  680. package/ref-monty/crates/monty/test_cases/hash__ops.py +0 -153
  681. package/ref-monty/crates/monty/test_cases/id__bytes_literals_distinct.py +0 -3
  682. package/ref-monty/crates/monty/test_cases/id__int_copy_distinct.py +0 -5
  683. package/ref-monty/crates/monty/test_cases/id__is_number_is_number.py +0 -3
  684. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_distinct_types.py +0 -10
  685. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_same_types.py +0 -6
  686. package/ref-monty/crates/monty/test_cases/id__ops.py +0 -97
  687. package/ref-monty/crates/monty/test_cases/id__str_literals_same.py +0 -3
  688. package/ref-monty/crates/monty/test_cases/if__elif_else.py +0 -207
  689. package/ref-monty/crates/monty/test_cases/if__raise_elif.py +0 -11
  690. package/ref-monty/crates/monty/test_cases/if__raise_else.py +0 -13
  691. package/ref-monty/crates/monty/test_cases/if__raise_if.py +0 -9
  692. package/ref-monty/crates/monty/test_cases/if__raise_in_elif_condition.py +0 -18
  693. package/ref-monty/crates/monty/test_cases/if__raise_in_if_condition.py +0 -16
  694. package/ref-monty/crates/monty/test_cases/if_else_expr__all.py +0 -55
  695. package/ref-monty/crates/monty/test_cases/import__error_cannot_import.py +0 -9
  696. package/ref-monty/crates/monty/test_cases/import__error_module_not_found.py +0 -9
  697. package/ref-monty/crates/monty/test_cases/import__local_scope.py +0 -68
  698. package/ref-monty/crates/monty/test_cases/import__os.py +0 -25
  699. package/ref-monty/crates/monty/test_cases/import__relative_error.py +0 -9
  700. package/ref-monty/crates/monty/test_cases/import__relative_no_module_error.py +0 -9
  701. package/ref-monty/crates/monty/test_cases/import__runtime_error_when_executed.py +0 -14
  702. package/ref-monty/crates/monty/test_cases/import__star_error.py +0 -11
  703. package/ref-monty/crates/monty/test_cases/import__sys.py +0 -47
  704. package/ref-monty/crates/monty/test_cases/import__sys_monty.py +0 -28
  705. package/ref-monty/crates/monty/test_cases/import__type_checking_guard.py +0 -37
  706. package/ref-monty/crates/monty/test_cases/import__typing.py +0 -25
  707. package/ref-monty/crates/monty/test_cases/import__typing_type_ignore.py +0 -4
  708. package/ref-monty/crates/monty/test_cases/int__bigint.py +0 -467
  709. package/ref-monty/crates/monty/test_cases/int__bigint_errors.py +0 -260
  710. package/ref-monty/crates/monty/test_cases/int__ops.py +0 -219
  711. package/ref-monty/crates/monty/test_cases/int__overflow_division.py +0 -84
  712. package/ref-monty/crates/monty/test_cases/is_variant__all.py +0 -36
  713. package/ref-monty/crates/monty/test_cases/isinstance__arg2_list_error.py +0 -2
  714. package/ref-monty/crates/monty/test_cases/isinstance__arg2_type_error.py +0 -2
  715. package/ref-monty/crates/monty/test_cases/iter__dict_mutation.py +0 -4
  716. package/ref-monty/crates/monty/test_cases/iter__for.py +0 -243
  717. package/ref-monty/crates/monty/test_cases/iter__for_loop_unpacking.py +0 -66
  718. package/ref-monty/crates/monty/test_cases/iter__generator_expr.py +0 -20
  719. package/ref-monty/crates/monty/test_cases/iter__generator_expr_type.py +0 -7
  720. package/ref-monty/crates/monty/test_cases/iter__not_iterable.py +0 -3
  721. package/ref-monty/crates/monty/test_cases/lambda__all.py +0 -145
  722. package/ref-monty/crates/monty/test_cases/list__extend_not_iterable.py +0 -7
  723. package/ref-monty/crates/monty/test_cases/list__getitem_out_of_bounds.py +0 -3
  724. package/ref-monty/crates/monty/test_cases/list__index_not_found.py +0 -9
  725. package/ref-monty/crates/monty/test_cases/list__index_start_gt_end.py +0 -10
  726. package/ref-monty/crates/monty/test_cases/list__ops.py +0 -473
  727. package/ref-monty/crates/monty/test_cases/list__pop_empty.py +0 -9
  728. package/ref-monty/crates/monty/test_cases/list__pop_out_of_range.py +0 -9
  729. package/ref-monty/crates/monty/test_cases/list__pop_type_error.py +0 -9
  730. package/ref-monty/crates/monty/test_cases/list__remove_not_found.py +0 -9
  731. package/ref-monty/crates/monty/test_cases/list__setitem_dict_index.py +0 -13
  732. package/ref-monty/crates/monty/test_cases/list__setitem_huge_int_index.py +0 -13
  733. package/ref-monty/crates/monty/test_cases/list__setitem_index_error.py +0 -10
  734. package/ref-monty/crates/monty/test_cases/list__setitem_type_error.py +0 -10
  735. package/ref-monty/crates/monty/test_cases/list__unpack_type_error.py +0 -2
  736. package/ref-monty/crates/monty/test_cases/longint__index_error.py +0 -3
  737. package/ref-monty/crates/monty/test_cases/longint__repeat_error.py +0 -3
  738. package/ref-monty/crates/monty/test_cases/loop__break_continue.py +0 -113
  739. package/ref-monty/crates/monty/test_cases/loop__break_finally.py +0 -69
  740. package/ref-monty/crates/monty/test_cases/loop__break_in_function_error.py +0 -13
  741. package/ref-monty/crates/monty/test_cases/loop__break_in_if_error.py +0 -11
  742. package/ref-monty/crates/monty/test_cases/loop__break_nested_except_clears.py +0 -55
  743. package/ref-monty/crates/monty/test_cases/loop__break_outside_error.py +0 -9
  744. package/ref-monty/crates/monty/test_cases/loop__continue_finally.py +0 -81
  745. package/ref-monty/crates/monty/test_cases/loop__continue_in_function_error.py +0 -13
  746. package/ref-monty/crates/monty/test_cases/loop__continue_in_if_error.py +0 -11
  747. package/ref-monty/crates/monty/test_cases/loop__continue_nested_except_clears.py +0 -60
  748. package/ref-monty/crates/monty/test_cases/loop__continue_outside_error.py +0 -9
  749. package/ref-monty/crates/monty/test_cases/math__acos_domain_error.py +0 -11
  750. package/ref-monty/crates/monty/test_cases/math__acosh_domain_error.py +0 -11
  751. package/ref-monty/crates/monty/test_cases/math__asin_domain_error.py +0 -11
  752. package/ref-monty/crates/monty/test_cases/math__atanh_domain_error.py +0 -11
  753. package/ref-monty/crates/monty/test_cases/math__cos_inf_error.py +0 -11
  754. package/ref-monty/crates/monty/test_cases/math__cosh_overflow_error.py +0 -11
  755. package/ref-monty/crates/monty/test_cases/math__exp_overflow_error.py +0 -11
  756. package/ref-monty/crates/monty/test_cases/math__factorial_float_error.py +0 -11
  757. package/ref-monty/crates/monty/test_cases/math__factorial_negative_error.py +0 -11
  758. package/ref-monty/crates/monty/test_cases/math__floor_inf_error.py +0 -11
  759. package/ref-monty/crates/monty/test_cases/math__floor_nan_error.py +0 -11
  760. package/ref-monty/crates/monty/test_cases/math__floor_str_error.py +0 -11
  761. package/ref-monty/crates/monty/test_cases/math__fmod_inf_error.py +0 -11
  762. package/ref-monty/crates/monty/test_cases/math__gamma_neg_int_error.py +0 -11
  763. package/ref-monty/crates/monty/test_cases/math__gcd_float_error.py +0 -11
  764. package/ref-monty/crates/monty/test_cases/math__isqrt_negative_error.py +0 -11
  765. package/ref-monty/crates/monty/test_cases/math__ldexp_overflow_error.py +0 -11
  766. package/ref-monty/crates/monty/test_cases/math__log1p_domain_error.py +0 -11
  767. package/ref-monty/crates/monty/test_cases/math__log_base1_error.py +0 -11
  768. package/ref-monty/crates/monty/test_cases/math__log_zero_error.py +0 -11
  769. package/ref-monty/crates/monty/test_cases/math__module.py +0 -1432
  770. package/ref-monty/crates/monty/test_cases/math__pow_domain_error.py +0 -11
  771. package/ref-monty/crates/monty/test_cases/math__sin_inf_error.py +0 -11
  772. package/ref-monty/crates/monty/test_cases/math__sqrt_negative_error.py +0 -11
  773. package/ref-monty/crates/monty/test_cases/math__tan_inf_error.py +0 -11
  774. package/ref-monty/crates/monty/test_cases/math__trunc_str_error.py +0 -11
  775. package/ref-monty/crates/monty/test_cases/method__args_kwargs_unpacking.py +0 -259
  776. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_func.py +0 -19
  777. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_module.py +0 -12
  778. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_chained.py +0 -9
  779. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_expr.py +0 -9
  780. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_function.py +0 -16
  781. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_with_args.py +0 -9
  782. package/ref-monty/crates/monty/test_cases/name_error__undefined_global.py +0 -10
  783. package/ref-monty/crates/monty/test_cases/namedtuple__missing_attr.py +0 -11
  784. package/ref-monty/crates/monty/test_cases/namedtuple__ops.py +0 -34
  785. package/ref-monty/crates/monty/test_cases/nonlocal__error_module_level.py +0 -3
  786. package/ref-monty/crates/monty/test_cases/nonlocal__ops.py +0 -353
  787. package/ref-monty/crates/monty/test_cases/os__environ.py +0 -40
  788. package/ref-monty/crates/monty/test_cases/os__getenv_key_list_error.py +0 -5
  789. package/ref-monty/crates/monty/test_cases/os__getenv_key_type_error.py +0 -5
  790. package/ref-monty/crates/monty/test_cases/parse_error__complex.py +0 -3
  791. package/ref-monty/crates/monty/test_cases/pathlib__import.py +0 -11
  792. package/ref-monty/crates/monty/test_cases/pathlib__os.py +0 -136
  793. package/ref-monty/crates/monty/test_cases/pathlib__os_read_error.py +0 -12
  794. package/ref-monty/crates/monty/test_cases/pathlib__pure.py +0 -81
  795. package/ref-monty/crates/monty/test_cases/pyobject__cycle_dict_self.py +0 -5
  796. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_dict.py +0 -6
  797. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_self.py +0 -5
  798. package/ref-monty/crates/monty/test_cases/pyobject__cycle_multiple_refs.py +0 -6
  799. package/ref-monty/crates/monty/test_cases/range__error_no_args.py +0 -2
  800. package/ref-monty/crates/monty/test_cases/range__error_step_zero.py +0 -2
  801. package/ref-monty/crates/monty/test_cases/range__error_too_many_args.py +0 -2
  802. package/ref-monty/crates/monty/test_cases/range__getitem_index_error.py +0 -10
  803. package/ref-monty/crates/monty/test_cases/range__ops.py +0 -236
  804. package/ref-monty/crates/monty/test_cases/re__basic.py +0 -756
  805. package/ref-monty/crates/monty/test_cases/re__grouping.py +0 -241
  806. package/ref-monty/crates/monty/test_cases/re__match.py +0 -148
  807. package/ref-monty/crates/monty/test_cases/recursion__deep_drop.py +0 -26
  808. package/ref-monty/crates/monty/test_cases/recursion__deep_eq.py +0 -23
  809. package/ref-monty/crates/monty/test_cases/recursion__deep_hash.py +0 -46
  810. package/ref-monty/crates/monty/test_cases/recursion__deep_repr.py +0 -12
  811. package/ref-monty/crates/monty/test_cases/recursion__function_depth.py +0 -13
  812. package/ref-monty/crates/monty/test_cases/refcount__cycle_mutual_reference.py +0 -18
  813. package/ref-monty/crates/monty/test_cases/refcount__cycle_self_reference.py +0 -12
  814. package/ref-monty/crates/monty/test_cases/refcount__dict_basic.py +0 -5
  815. package/ref-monty/crates/monty/test_cases/refcount__dict_get.py +0 -5
  816. package/ref-monty/crates/monty/test_cases/refcount__dict_keys_and.py +0 -14
  817. package/ref-monty/crates/monty/test_cases/refcount__dict_overwrite.py +0 -6
  818. package/ref-monty/crates/monty/test_cases/refcount__gather_cleanup.py +0 -16
  819. package/ref-monty/crates/monty/test_cases/refcount__gather_exception.py +0 -18
  820. package/ref-monty/crates/monty/test_cases/refcount__gather_nested_cancel.py +0 -25
  821. package/ref-monty/crates/monty/test_cases/refcount__immediate_skipped.py +0 -4
  822. package/ref-monty/crates/monty/test_cases/refcount__kwargs_unpacking.py +0 -27
  823. package/ref-monty/crates/monty/test_cases/refcount__list_append_multiple.py +0 -6
  824. package/ref-monty/crates/monty/test_cases/refcount__list_append_ref.py +0 -5
  825. package/ref-monty/crates/monty/test_cases/refcount__list_concat.py +0 -5
  826. package/ref-monty/crates/monty/test_cases/refcount__list_getitem.py +0 -5
  827. package/ref-monty/crates/monty/test_cases/refcount__list_iadd.py +0 -5
  828. package/ref-monty/crates/monty/test_cases/refcount__nested_list.py +0 -4
  829. package/ref-monty/crates/monty/test_cases/refcount__re_pattern_sub_error_paths.py +0 -37
  830. package/ref-monty/crates/monty/test_cases/refcount__re_search_match.py +0 -34
  831. package/ref-monty/crates/monty/test_cases/refcount__re_sub_error_paths.py +0 -31
  832. package/ref-monty/crates/monty/test_cases/refcount__shared_reference.py +0 -4
  833. package/ref-monty/crates/monty/test_cases/refcount__single_list.py +0 -3
  834. package/ref-monty/crates/monty/test_cases/repr__cycle_detection.py +0 -24
  835. package/ref-monty/crates/monty/test_cases/set__ops.py +0 -191
  836. package/ref-monty/crates/monty/test_cases/set__review_bugs.py +0 -35
  837. package/ref-monty/crates/monty/test_cases/set__unpack_type_error.py +0 -2
  838. package/ref-monty/crates/monty/test_cases/slice__invalid_indices.py +0 -2
  839. package/ref-monty/crates/monty/test_cases/slice__kwargs.py +0 -9
  840. package/ref-monty/crates/monty/test_cases/slice__no_args.py +0 -9
  841. package/ref-monty/crates/monty/test_cases/slice__ops.py +0 -149
  842. package/ref-monty/crates/monty/test_cases/slice__step_zero.py +0 -9
  843. package/ref-monty/crates/monty/test_cases/slice__step_zero_bytes.py +0 -9
  844. package/ref-monty/crates/monty/test_cases/slice__step_zero_range.py +0 -9
  845. package/ref-monty/crates/monty/test_cases/slice__step_zero_str.py +0 -9
  846. package/ref-monty/crates/monty/test_cases/slice__step_zero_tuple.py +0 -9
  847. package/ref-monty/crates/monty/test_cases/slice__too_many_args.py +0 -9
  848. package/ref-monty/crates/monty/test_cases/str__getitem_index_error.py +0 -10
  849. package/ref-monty/crates/monty/test_cases/str__index_not_found.py +0 -9
  850. package/ref-monty/crates/monty/test_cases/str__join_no_args.py +0 -9
  851. package/ref-monty/crates/monty/test_cases/str__join_non_string.py +0 -9
  852. package/ref-monty/crates/monty/test_cases/str__join_not_iterable.py +0 -9
  853. package/ref-monty/crates/monty/test_cases/str__join_too_many_args.py +0 -9
  854. package/ref-monty/crates/monty/test_cases/str__methods.py +0 -327
  855. package/ref-monty/crates/monty/test_cases/str__ops.py +0 -162
  856. package/ref-monty/crates/monty/test_cases/str__partition_empty.py +0 -9
  857. package/ref-monty/crates/monty/test_cases/str__rsplit_empty_sep.py +0 -9
  858. package/ref-monty/crates/monty/test_cases/str__split_empty_sep.py +0 -9
  859. package/ref-monty/crates/monty/test_cases/sys__types.py +0 -7
  860. package/ref-monty/crates/monty/test_cases/traceback__division_error.py +0 -30
  861. package/ref-monty/crates/monty/test_cases/traceback__index_error.py +0 -17
  862. package/ref-monty/crates/monty/test_cases/traceback__insert_as_int.py +0 -10
  863. package/ref-monty/crates/monty/test_cases/traceback__nested_call.py +0 -29
  864. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_module_scope.py +0 -10
  865. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_unbound.py +0 -24
  866. package/ref-monty/crates/monty/test_cases/traceback__range_as_int.py +0 -9
  867. package/ref-monty/crates/monty/test_cases/traceback__recursion_error.py +0 -23
  868. package/ref-monty/crates/monty/test_cases/traceback__set_mutation.py +0 -11
  869. package/ref-monty/crates/monty/test_cases/traceback__undefined_attr_call.py +0 -16
  870. package/ref-monty/crates/monty/test_cases/traceback__undefined_call.py +0 -16
  871. package/ref-monty/crates/monty/test_cases/traceback__undefined_raise.py +0 -16
  872. package/ref-monty/crates/monty/test_cases/try_except__all.py +0 -472
  873. package/ref-monty/crates/monty/test_cases/try_except__bare_raise_no_context.py +0 -2
  874. package/ref-monty/crates/monty/test_cases/try_except__invalid_type.py +0 -5
  875. package/ref-monty/crates/monty/test_cases/tuple__getitem_out_of_bounds.py +0 -3
  876. package/ref-monty/crates/monty/test_cases/tuple__index_not_found.py +0 -9
  877. package/ref-monty/crates/monty/test_cases/tuple__index_start_gt_end.py +0 -10
  878. package/ref-monty/crates/monty/test_cases/tuple__methods.py +0 -19
  879. package/ref-monty/crates/monty/test_cases/tuple__ops.py +0 -133
  880. package/ref-monty/crates/monty/test_cases/tuple__unpack_type_error.py +0 -2
  881. package/ref-monty/crates/monty/test_cases/type__builtin_attr_error.py +0 -9
  882. package/ref-monty/crates/monty/test_cases/type__bytes_negative.py +0 -2
  883. package/ref-monty/crates/monty/test_cases/type__cell_not_builtin.py +0 -9
  884. package/ref-monty/crates/monty/test_cases/type__exception_attr_error.py +0 -11
  885. package/ref-monty/crates/monty/test_cases/type__float_conversion_error.py +0 -2
  886. package/ref-monty/crates/monty/test_cases/type__float_repr_both_quotes.py +0 -9
  887. package/ref-monty/crates/monty/test_cases/type__float_repr_newline.py +0 -9
  888. package/ref-monty/crates/monty/test_cases/type__float_repr_single_quote.py +0 -9
  889. package/ref-monty/crates/monty/test_cases/type__int_conversion_error.py +0 -2
  890. package/ref-monty/crates/monty/test_cases/type__list_not_iterable.py +0 -2
  891. package/ref-monty/crates/monty/test_cases/type__non_builtin_name_error.py +0 -9
  892. package/ref-monty/crates/monty/test_cases/type__ops.py +0 -200
  893. package/ref-monty/crates/monty/test_cases/type__shadow_exc.py +0 -3
  894. package/ref-monty/crates/monty/test_cases/type__shadow_int.py +0 -9
  895. package/ref-monty/crates/monty/test_cases/type__shadow_len.py +0 -3
  896. package/ref-monty/crates/monty/test_cases/type__tuple_not_iterable.py +0 -2
  897. package/ref-monty/crates/monty/test_cases/type_error__int_add_list.py +0 -2
  898. package/ref-monty/crates/monty/test_cases/type_error__int_div_str.py +0 -2
  899. package/ref-monty/crates/monty/test_cases/type_error__int_floordiv_str.py +0 -2
  900. package/ref-monty/crates/monty/test_cases/type_error__int_iadd_str.py +0 -3
  901. package/ref-monty/crates/monty/test_cases/type_error__int_mod_str.py +0 -2
  902. package/ref-monty/crates/monty/test_cases/type_error__int_pow_str.py +0 -2
  903. package/ref-monty/crates/monty/test_cases/type_error__int_sub_str.py +0 -2
  904. package/ref-monty/crates/monty/test_cases/type_error__list_add_int.py +0 -2
  905. package/ref-monty/crates/monty/test_cases/type_error__list_add_str.py +0 -2
  906. package/ref-monty/crates/monty/test_cases/type_error__list_iadd_int.py +0 -6
  907. package/ref-monty/crates/monty/test_cases/type_error__str_add_int.py +0 -2
  908. package/ref-monty/crates/monty/test_cases/type_error__str_iadd_int.py +0 -3
  909. package/ref-monty/crates/monty/test_cases/type_error__unary_invert_str.py +0 -3
  910. package/ref-monty/crates/monty/test_cases/type_error__unary_minus_str.py +0 -4
  911. package/ref-monty/crates/monty/test_cases/type_error__unary_neg_str.py +0 -3
  912. package/ref-monty/crates/monty/test_cases/type_error__unary_plus_str.py +0 -4
  913. package/ref-monty/crates/monty/test_cases/typing__types.py +0 -24
  914. package/ref-monty/crates/monty/test_cases/unpack__nested.py +0 -48
  915. package/ref-monty/crates/monty/test_cases/unpack__non_sequence.py +0 -9
  916. package/ref-monty/crates/monty/test_cases/unpack__not_enough.py +0 -9
  917. package/ref-monty/crates/monty/test_cases/unpack__ops.py +0 -153
  918. package/ref-monty/crates/monty/test_cases/unpack__star_not_enough.py +0 -9
  919. package/ref-monty/crates/monty/test_cases/unpack__too_many.py +0 -9
  920. package/ref-monty/crates/monty/test_cases/version__cpython.py +0 -4
  921. package/ref-monty/crates/monty/test_cases/walrus__all.py +0 -178
  922. package/ref-monty/crates/monty/test_cases/while__all.py +0 -206
  923. package/ref-monty/crates/monty/tests/asyncio.rs +0 -764
  924. package/ref-monty/crates/monty/tests/binary_serde.rs +0 -185
  925. package/ref-monty/crates/monty/tests/bytecode_limits.rs +0 -248
  926. package/ref-monty/crates/monty/tests/datatest_runner.rs +0 -2029
  927. package/ref-monty/crates/monty/tests/inputs.rs +0 -420
  928. package/ref-monty/crates/monty/tests/json_serde.rs +0 -250
  929. package/ref-monty/crates/monty/tests/main.rs +0 -71
  930. package/ref-monty/crates/monty/tests/math_module.rs +0 -114
  931. package/ref-monty/crates/monty/tests/name_lookup.rs +0 -482
  932. package/ref-monty/crates/monty/tests/os_tests.rs +0 -459
  933. package/ref-monty/crates/monty/tests/parse_errors.rs +0 -441
  934. package/ref-monty/crates/monty/tests/print_writer.rs +0 -238
  935. package/ref-monty/crates/monty/tests/py_object.rs +0 -121
  936. package/ref-monty/crates/monty/tests/regex.rs +0 -90
  937. package/ref-monty/crates/monty/tests/repl.rs +0 -344
  938. package/ref-monty/crates/monty/tests/resource_limits.rs +0 -1826
  939. package/ref-monty/crates/monty/tests/try_from.rs +0 -167
  940. package/ref-monty/crates/monty-cli/Cargo.toml +0 -25
  941. package/ref-monty/crates/monty-cli/src/main.rs +0 -541
  942. package/ref-monty/crates/monty-js/.cargo/config.toml +0 -2
  943. package/ref-monty/crates/monty-js/.prettierignore +0 -8
  944. package/ref-monty/crates/monty-js/Cargo.toml +0 -32
  945. package/ref-monty/crates/monty-js/README.md +0 -207
  946. package/ref-monty/crates/monty-js/__test__/async.spec.ts +0 -350
  947. package/ref-monty/crates/monty-js/__test__/basic.spec.ts +0 -114
  948. package/ref-monty/crates/monty-js/__test__/exceptions.spec.ts +0 -427
  949. package/ref-monty/crates/monty-js/__test__/external.spec.ts +0 -354
  950. package/ref-monty/crates/monty-js/__test__/inputs.spec.ts +0 -143
  951. package/ref-monty/crates/monty-js/__test__/limits.spec.ts +0 -162
  952. package/ref-monty/crates/monty-js/__test__/package.json +0 -3
  953. package/ref-monty/crates/monty-js/__test__/print.spec.ts +0 -229
  954. package/ref-monty/crates/monty-js/__test__/repl.spec.ts +0 -34
  955. package/ref-monty/crates/monty-js/__test__/serialize.spec.ts +0 -205
  956. package/ref-monty/crates/monty-js/__test__/start.spec.ts +0 -443
  957. package/ref-monty/crates/monty-js/__test__/type_check.spec.ts +0 -147
  958. package/ref-monty/crates/monty-js/__test__/types.spec.ts +0 -319
  959. package/ref-monty/crates/monty-js/build.rs +0 -61
  960. package/ref-monty/crates/monty-js/index-header.d.ts +0 -3
  961. package/ref-monty/crates/monty-js/package-lock.json +0 -4694
  962. package/ref-monty/crates/monty-js/package.json +0 -100
  963. package/ref-monty/crates/monty-js/scripts/smoke-test.sh +0 -69
  964. package/ref-monty/crates/monty-js/smoke-test/package.json +0 -17
  965. package/ref-monty/crates/monty-js/smoke-test/test.ts +0 -171
  966. package/ref-monty/crates/monty-js/smoke-test/tsconfig.json +0 -11
  967. package/ref-monty/crates/monty-js/src/convert.rs +0 -648
  968. package/ref-monty/crates/monty-js/src/exceptions.rs +0 -293
  969. package/ref-monty/crates/monty-js/src/lib.rs +0 -41
  970. package/ref-monty/crates/monty-js/src/limits.rs +0 -53
  971. package/ref-monty/crates/monty-js/src/monty_cls.rs +0 -1407
  972. package/ref-monty/crates/monty-js/tsconfig.json +0 -17
  973. package/ref-monty/crates/monty-js/wrapper.ts +0 -701
  974. package/ref-monty/crates/monty-python/Cargo.toml +0 -38
  975. package/ref-monty/crates/monty-python/README.md +0 -134
  976. package/ref-monty/crates/monty-python/build.rs +0 -4
  977. package/ref-monty/crates/monty-python/example.py +0 -40
  978. package/ref-monty/crates/monty-python/exercise.py +0 -46
  979. package/ref-monty/crates/monty-python/pyproject.toml +0 -57
  980. package/ref-monty/crates/monty-python/python/pydantic_monty/__init__.py +0 -281
  981. package/ref-monty/crates/monty-python/python/pydantic_monty/_monty.pyi +0 -677
  982. package/ref-monty/crates/monty-python/python/pydantic_monty/os_access.py +0 -933
  983. package/ref-monty/crates/monty-python/python/pydantic_monty/py.typed +0 -0
  984. package/ref-monty/crates/monty-python/src/convert.rs +0 -273
  985. package/ref-monty/crates/monty-python/src/dataclass.rs +0 -461
  986. package/ref-monty/crates/monty-python/src/exceptions.rs +0 -557
  987. package/ref-monty/crates/monty-python/src/external.rs +0 -165
  988. package/ref-monty/crates/monty-python/src/lib.rs +0 -77
  989. package/ref-monty/crates/monty-python/src/limits.rs +0 -142
  990. package/ref-monty/crates/monty-python/src/monty_cls.rs +0 -1650
  991. package/ref-monty/crates/monty-python/src/repl.rs +0 -470
  992. package/ref-monty/crates/monty-python/src/serialization.rs +0 -761
  993. package/ref-monty/crates/monty-python/tests/test_async.py +0 -1201
  994. package/ref-monty/crates/monty-python/tests/test_basic.py +0 -66
  995. package/ref-monty/crates/monty-python/tests/test_dataclasses.py +0 -971
  996. package/ref-monty/crates/monty-python/tests/test_exceptions.py +0 -361
  997. package/ref-monty/crates/monty-python/tests/test_external.py +0 -367
  998. package/ref-monty/crates/monty-python/tests/test_inputs.py +0 -126
  999. package/ref-monty/crates/monty-python/tests/test_limits.py +0 -257
  1000. package/ref-monty/crates/monty-python/tests/test_os_access.py +0 -1286
  1001. package/ref-monty/crates/monty-python/tests/test_os_access_compat.py +0 -731
  1002. package/ref-monty/crates/monty-python/tests/test_os_access_raw.py +0 -483
  1003. package/ref-monty/crates/monty-python/tests/test_os_calls.py +0 -819
  1004. package/ref-monty/crates/monty-python/tests/test_print.py +0 -208
  1005. package/ref-monty/crates/monty-python/tests/test_re.py +0 -170
  1006. package/ref-monty/crates/monty-python/tests/test_readme_examples.py +0 -20
  1007. package/ref-monty/crates/monty-python/tests/test_repl.py +0 -749
  1008. package/ref-monty/crates/monty-python/tests/test_serialize.py +0 -284
  1009. package/ref-monty/crates/monty-python/tests/test_start.py +0 -346
  1010. package/ref-monty/crates/monty-python/tests/test_threading.py +0 -163
  1011. package/ref-monty/crates/monty-python/tests/test_type_check.py +0 -344
  1012. package/ref-monty/crates/monty-python/tests/test_types.py +0 -553
  1013. package/ref-monty/crates/monty-type-checking/Cargo.toml +0 -32
  1014. package/ref-monty/crates/monty-type-checking/src/db.rs +0 -116
  1015. package/ref-monty/crates/monty-type-checking/src/lib.rs +0 -4
  1016. package/ref-monty/crates/monty-type-checking/src/type_check.rs +0 -280
  1017. package/ref-monty/crates/monty-type-checking/tests/bad_types.py +0 -109
  1018. package/ref-monty/crates/monty-type-checking/tests/bad_types_output.txt +0 -21
  1019. package/ref-monty/crates/monty-type-checking/tests/good_types.py +0 -475
  1020. package/ref-monty/crates/monty-type-checking/tests/main.rs +0 -205
  1021. package/ref-monty/crates/monty-type-checking/tests/reveal_types.py +0 -56
  1022. package/ref-monty/crates/monty-type-checking/tests/reveal_types_output.txt +0 -41
  1023. package/ref-monty/crates/monty-typeshed/Cargo.toml +0 -29
  1024. package/ref-monty/crates/monty-typeshed/README.md +0 -11
  1025. package/ref-monty/crates/monty-typeshed/build.rs +0 -101
  1026. package/ref-monty/crates/monty-typeshed/custom/README.md +0 -1
  1027. package/ref-monty/crates/monty-typeshed/custom/asyncio.pyi +0 -138
  1028. package/ref-monty/crates/monty-typeshed/custom/os.pyi +0 -87
  1029. package/ref-monty/crates/monty-typeshed/custom/sys.pyi +0 -33
  1030. package/ref-monty/crates/monty-typeshed/src/lib.rs +0 -56
  1031. package/ref-monty/crates/monty-typeshed/update.py +0 -321
  1032. package/ref-monty/crates/monty-typeshed/vendor/typeshed/source_commit.txt +0 -1
  1033. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/VERSIONS +0 -20
  1034. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi +0 -105
  1035. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi +0 -394
  1036. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi +0 -138
  1037. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi +0 -1434
  1038. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi +0 -527
  1039. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/abc.pyi +0 -2
  1040. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/dataclasses.pyi +0 -502
  1041. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/enum.pyi +0 -376
  1042. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/math.pyi +0 -149
  1043. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/os.pyi +0 -87
  1044. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/__init__.pyi +0 -395
  1045. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/types.pyi +0 -8
  1046. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/re.pyi +0 -337
  1047. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/sys.pyi +0 -33
  1048. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/types.pyi +0 -741
  1049. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing.pyi +0 -1217
  1050. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing_extensions.pyi +0 -716
  1051. package/ref-monty/docs/usage-guide.md +0 -117
  1052. package/ref-monty/examples/README.md +0 -3
  1053. package/ref-monty/examples/expense_analysis/README.md +0 -3
  1054. package/ref-monty/examples/expense_analysis/data.py +0 -124
  1055. package/ref-monty/examples/expense_analysis/main.py +0 -115
  1056. package/ref-monty/examples/sql_playground/README.md +0 -20
  1057. package/ref-monty/examples/sql_playground/external_functions.py +0 -129
  1058. package/ref-monty/examples/sql_playground/main.py +0 -81
  1059. package/ref-monty/examples/sql_playground/sandbox_code.py +0 -82
  1060. package/ref-monty/examples/sql_playground/type_stubs.pyi +0 -14
  1061. package/ref-monty/examples/web_scraper/README.md +0 -15
  1062. package/ref-monty/examples/web_scraper/browser.py +0 -56
  1063. package/ref-monty/examples/web_scraper/example_code.py +0 -59
  1064. package/ref-monty/examples/web_scraper/external_functions.py +0 -324
  1065. package/ref-monty/examples/web_scraper/main.py +0 -193
  1066. package/ref-monty/examples/web_scraper/sub_agent.py +0 -79
  1067. package/ref-monty/monty-npm.md +0 -235
  1068. package/ref-monty/pyproject.toml +0 -162
  1069. package/ref-monty/scripts/check_imports.py +0 -91
  1070. package/ref-monty/scripts/codecov_diff.py +0 -412
  1071. package/ref-monty/scripts/complete_tests.py +0 -146
  1072. package/ref-monty/scripts/flamegraph_to_text.py +0 -208
  1073. package/ref-monty/scripts/iter_test_methods.py +0 -540
  1074. package/ref-monty/scripts/run_traceback.py +0 -180
  1075. package/ref-monty/scripts/startup_performance.py +0 -130
  1076. package/ref-monty/uv.lock +0 -1779
  1077. package/temp_resend_cli/repo/.github/scripts/pr-title-check.js +0 -34
  1078. package/temp_resend_cli/repo/.github/workflows/ci.yml +0 -67
  1079. package/temp_resend_cli/repo/.github/workflows/post-release.yml +0 -51
  1080. package/temp_resend_cli/repo/.github/workflows/pr-title-check.yml +0 -13
  1081. package/temp_resend_cli/repo/.github/workflows/release.yml +0 -175
  1082. package/temp_resend_cli/repo/.github/workflows/test-install-unix.yml +0 -34
  1083. package/temp_resend_cli/repo/.github/workflows/test-install-windows.yml +0 -48
  1084. package/temp_resend_cli/repo/CHANGELOG.md +0 -31
  1085. package/temp_resend_cli/repo/LICENSE +0 -21
  1086. package/temp_resend_cli/repo/README.md +0 -450
  1087. package/temp_resend_cli/repo/biome.json +0 -36
  1088. package/temp_resend_cli/repo/install.ps1 +0 -141
  1089. package/temp_resend_cli/repo/install.sh +0 -301
  1090. package/temp_resend_cli/repo/package.json +0 -61
  1091. package/temp_resend_cli/repo/pnpm-lock.yaml +0 -2439
  1092. package/temp_resend_cli/repo/renovate.json +0 -4
  1093. package/temp_resend_cli/repo/src/cli.ts +0 -98
  1094. package/temp_resend_cli/repo/src/commands/api-keys/create.ts +0 -114
  1095. package/temp_resend_cli/repo/src/commands/api-keys/delete.ts +0 -47
  1096. package/temp_resend_cli/repo/src/commands/api-keys/index.ts +0 -26
  1097. package/temp_resend_cli/repo/src/commands/api-keys/list.ts +0 -35
  1098. package/temp_resend_cli/repo/src/commands/api-keys/utils.ts +0 -8
  1099. package/temp_resend_cli/repo/src/commands/auth/index.ts +0 -20
  1100. package/temp_resend_cli/repo/src/commands/auth/login.ts +0 -234
  1101. package/temp_resend_cli/repo/src/commands/auth/logout.ts +0 -105
  1102. package/temp_resend_cli/repo/src/commands/broadcasts/create.ts +0 -196
  1103. package/temp_resend_cli/repo/src/commands/broadcasts/delete.ts +0 -46
  1104. package/temp_resend_cli/repo/src/commands/broadcasts/get.ts +0 -59
  1105. package/temp_resend_cli/repo/src/commands/broadcasts/index.ts +0 -43
  1106. package/temp_resend_cli/repo/src/commands/broadcasts/list.ts +0 -60
  1107. package/temp_resend_cli/repo/src/commands/broadcasts/send.ts +0 -56
  1108. package/temp_resend_cli/repo/src/commands/broadcasts/update.ts +0 -95
  1109. package/temp_resend_cli/repo/src/commands/broadcasts/utils.ts +0 -35
  1110. package/temp_resend_cli/repo/src/commands/contact-properties/create.ts +0 -118
  1111. package/temp_resend_cli/repo/src/commands/contact-properties/delete.ts +0 -48
  1112. package/temp_resend_cli/repo/src/commands/contact-properties/get.ts +0 -46
  1113. package/temp_resend_cli/repo/src/commands/contact-properties/index.ts +0 -48
  1114. package/temp_resend_cli/repo/src/commands/contact-properties/list.ts +0 -68
  1115. package/temp_resend_cli/repo/src/commands/contact-properties/update.ts +0 -88
  1116. package/temp_resend_cli/repo/src/commands/contact-properties/utils.ts +0 -17
  1117. package/temp_resend_cli/repo/src/commands/contacts/add-segment.ts +0 -78
  1118. package/temp_resend_cli/repo/src/commands/contacts/create.ts +0 -122
  1119. package/temp_resend_cli/repo/src/commands/contacts/delete.ts +0 -49
  1120. package/temp_resend_cli/repo/src/commands/contacts/get.ts +0 -53
  1121. package/temp_resend_cli/repo/src/commands/contacts/index.ts +0 -58
  1122. package/temp_resend_cli/repo/src/commands/contacts/list.ts +0 -57
  1123. package/temp_resend_cli/repo/src/commands/contacts/remove-segment.ts +0 -48
  1124. package/temp_resend_cli/repo/src/commands/contacts/segments.ts +0 -39
  1125. package/temp_resend_cli/repo/src/commands/contacts/topics.ts +0 -45
  1126. package/temp_resend_cli/repo/src/commands/contacts/update-topics.ts +0 -90
  1127. package/temp_resend_cli/repo/src/commands/contacts/update.ts +0 -77
  1128. package/temp_resend_cli/repo/src/commands/contacts/utils.ts +0 -119
  1129. package/temp_resend_cli/repo/src/commands/doctor.ts +0 -216
  1130. package/temp_resend_cli/repo/src/commands/domains/create.ts +0 -83
  1131. package/temp_resend_cli/repo/src/commands/domains/delete.ts +0 -42
  1132. package/temp_resend_cli/repo/src/commands/domains/get.ts +0 -47
  1133. package/temp_resend_cli/repo/src/commands/domains/index.ts +0 -35
  1134. package/temp_resend_cli/repo/src/commands/domains/list.ts +0 -53
  1135. package/temp_resend_cli/repo/src/commands/domains/update.ts +0 -75
  1136. package/temp_resend_cli/repo/src/commands/domains/utils.ts +0 -44
  1137. package/temp_resend_cli/repo/src/commands/domains/verify.ts +0 -38
  1138. package/temp_resend_cli/repo/src/commands/emails/batch.ts +0 -140
  1139. package/temp_resend_cli/repo/src/commands/emails/get.ts +0 -44
  1140. package/temp_resend_cli/repo/src/commands/emails/index.ts +0 -30
  1141. package/temp_resend_cli/repo/src/commands/emails/list.ts +0 -84
  1142. package/temp_resend_cli/repo/src/commands/emails/receiving/attachment.ts +0 -55
  1143. package/temp_resend_cli/repo/src/commands/emails/receiving/attachments.ts +0 -68
  1144. package/temp_resend_cli/repo/src/commands/emails/receiving/get.ts +0 -58
  1145. package/temp_resend_cli/repo/src/commands/emails/receiving/index.ts +0 -28
  1146. package/temp_resend_cli/repo/src/commands/emails/receiving/list.ts +0 -59
  1147. package/temp_resend_cli/repo/src/commands/emails/receiving/utils.ts +0 -38
  1148. package/temp_resend_cli/repo/src/commands/emails/send.ts +0 -189
  1149. package/temp_resend_cli/repo/src/commands/open.ts +0 -27
  1150. package/temp_resend_cli/repo/src/commands/segments/create.ts +0 -50
  1151. package/temp_resend_cli/repo/src/commands/segments/delete.ts +0 -47
  1152. package/temp_resend_cli/repo/src/commands/segments/get.ts +0 -38
  1153. package/temp_resend_cli/repo/src/commands/segments/index.ts +0 -36
  1154. package/temp_resend_cli/repo/src/commands/segments/list.ts +0 -58
  1155. package/temp_resend_cli/repo/src/commands/segments/utils.ts +0 -7
  1156. package/temp_resend_cli/repo/src/commands/teams/index.ts +0 -10
  1157. package/temp_resend_cli/repo/src/commands/teams/list.ts +0 -35
  1158. package/temp_resend_cli/repo/src/commands/teams/remove.ts +0 -86
  1159. package/temp_resend_cli/repo/src/commands/teams/switch.ts +0 -76
  1160. package/temp_resend_cli/repo/src/commands/topics/create.ts +0 -73
  1161. package/temp_resend_cli/repo/src/commands/topics/delete.ts +0 -47
  1162. package/temp_resend_cli/repo/src/commands/topics/get.ts +0 -42
  1163. package/temp_resend_cli/repo/src/commands/topics/index.ts +0 -42
  1164. package/temp_resend_cli/repo/src/commands/topics/list.ts +0 -34
  1165. package/temp_resend_cli/repo/src/commands/topics/update.ts +0 -59
  1166. package/temp_resend_cli/repo/src/commands/topics/utils.ts +0 -16
  1167. package/temp_resend_cli/repo/src/commands/webhooks/create.ts +0 -128
  1168. package/temp_resend_cli/repo/src/commands/webhooks/delete.ts +0 -49
  1169. package/temp_resend_cli/repo/src/commands/webhooks/get.ts +0 -42
  1170. package/temp_resend_cli/repo/src/commands/webhooks/index.ts +0 -42
  1171. package/temp_resend_cli/repo/src/commands/webhooks/list.ts +0 -55
  1172. package/temp_resend_cli/repo/src/commands/webhooks/listen.ts +0 -379
  1173. package/temp_resend_cli/repo/src/commands/webhooks/update.ts +0 -83
  1174. package/temp_resend_cli/repo/src/commands/webhooks/utils.ts +0 -36
  1175. package/temp_resend_cli/repo/src/commands/whoami.ts +0 -71
  1176. package/temp_resend_cli/repo/src/lib/actions.ts +0 -157
  1177. package/temp_resend_cli/repo/src/lib/client.ts +0 -37
  1178. package/temp_resend_cli/repo/src/lib/config.ts +0 -217
  1179. package/temp_resend_cli/repo/src/lib/files.ts +0 -15
  1180. package/temp_resend_cli/repo/src/lib/help-text.ts +0 -38
  1181. package/temp_resend_cli/repo/src/lib/output.ts +0 -56
  1182. package/temp_resend_cli/repo/src/lib/pagination.ts +0 -36
  1183. package/temp_resend_cli/repo/src/lib/prompts.ts +0 -149
  1184. package/temp_resend_cli/repo/src/lib/spinner.ts +0 -100
  1185. package/temp_resend_cli/repo/src/lib/table.ts +0 -57
  1186. package/temp_resend_cli/repo/src/lib/tty.ts +0 -28
  1187. package/temp_resend_cli/repo/src/lib/update-check.ts +0 -169
  1188. package/temp_resend_cli/repo/src/lib/version.ts +0 -4
  1189. package/temp_resend_cli/repo/tests/commands/api-keys/create.test.ts +0 -196
  1190. package/temp_resend_cli/repo/tests/commands/api-keys/delete.test.ts +0 -157
  1191. package/temp_resend_cli/repo/tests/commands/api-keys/list.test.ts +0 -134
  1192. package/temp_resend_cli/repo/tests/commands/auth/login.test.ts +0 -153
  1193. package/temp_resend_cli/repo/tests/commands/auth/logout.test.ts +0 -153
  1194. package/temp_resend_cli/repo/tests/commands/broadcasts/create.test.ts +0 -454
  1195. package/temp_resend_cli/repo/tests/commands/broadcasts/delete.test.ts +0 -183
  1196. package/temp_resend_cli/repo/tests/commands/broadcasts/get.test.ts +0 -147
  1197. package/temp_resend_cli/repo/tests/commands/broadcasts/list.test.ts +0 -199
  1198. package/temp_resend_cli/repo/tests/commands/broadcasts/send.test.ts +0 -162
  1199. package/temp_resend_cli/repo/tests/commands/broadcasts/update.test.ts +0 -288
  1200. package/temp_resend_cli/repo/tests/commands/contact-properties/create.test.ts +0 -251
  1201. package/temp_resend_cli/repo/tests/commands/contact-properties/delete.test.ts +0 -184
  1202. package/temp_resend_cli/repo/tests/commands/contact-properties/get.test.ts +0 -145
  1203. package/temp_resend_cli/repo/tests/commands/contact-properties/list.test.ts +0 -181
  1204. package/temp_resend_cli/repo/tests/commands/contact-properties/update.test.ts +0 -217
  1205. package/temp_resend_cli/repo/tests/commands/contacts/add-segment.test.ts +0 -189
  1206. package/temp_resend_cli/repo/tests/commands/contacts/create.test.ts +0 -271
  1207. package/temp_resend_cli/repo/tests/commands/contacts/delete.test.ts +0 -193
  1208. package/temp_resend_cli/repo/tests/commands/contacts/get.test.ts +0 -149
  1209. package/temp_resend_cli/repo/tests/commands/contacts/list.test.ts +0 -176
  1210. package/temp_resend_cli/repo/tests/commands/contacts/remove-segment.test.ts +0 -167
  1211. package/temp_resend_cli/repo/tests/commands/contacts/segments.test.ts +0 -168
  1212. package/temp_resend_cli/repo/tests/commands/contacts/topics.test.ts +0 -164
  1213. package/temp_resend_cli/repo/tests/commands/contacts/update-topics.test.ts +0 -248
  1214. package/temp_resend_cli/repo/tests/commands/contacts/update.test.ts +0 -206
  1215. package/temp_resend_cli/repo/tests/commands/doctor.test.ts +0 -164
  1216. package/temp_resend_cli/repo/tests/commands/domains/create.test.ts +0 -193
  1217. package/temp_resend_cli/repo/tests/commands/domains/delete.test.ts +0 -157
  1218. package/temp_resend_cli/repo/tests/commands/domains/get.test.ts +0 -138
  1219. package/temp_resend_cli/repo/tests/commands/domains/list.test.ts +0 -165
  1220. package/temp_resend_cli/repo/tests/commands/domains/update.test.ts +0 -224
  1221. package/temp_resend_cli/repo/tests/commands/domains/verify.test.ts +0 -118
  1222. package/temp_resend_cli/repo/tests/commands/emails/batch.test.ts +0 -324
  1223. package/temp_resend_cli/repo/tests/commands/emails/get.test.ts +0 -132
  1224. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachment.test.ts +0 -141
  1225. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachments.test.ts +0 -169
  1226. package/temp_resend_cli/repo/tests/commands/emails/receiving/get.test.ts +0 -141
  1227. package/temp_resend_cli/repo/tests/commands/emails/receiving/list.test.ts +0 -182
  1228. package/temp_resend_cli/repo/tests/commands/emails/send.test.ts +0 -312
  1229. package/temp_resend_cli/repo/tests/commands/segments/create.test.ts +0 -164
  1230. package/temp_resend_cli/repo/tests/commands/segments/delete.test.ts +0 -183
  1231. package/temp_resend_cli/repo/tests/commands/segments/get.test.ts +0 -138
  1232. package/temp_resend_cli/repo/tests/commands/segments/list.test.ts +0 -174
  1233. package/temp_resend_cli/repo/tests/commands/teams/list.test.ts +0 -62
  1234. package/temp_resend_cli/repo/tests/commands/teams/remove.test.ts +0 -110
  1235. package/temp_resend_cli/repo/tests/commands/teams/switch.test.ts +0 -103
  1236. package/temp_resend_cli/repo/tests/commands/topics/create.test.ts +0 -192
  1237. package/temp_resend_cli/repo/tests/commands/topics/delete.test.ts +0 -157
  1238. package/temp_resend_cli/repo/tests/commands/topics/get.test.ts +0 -126
  1239. package/temp_resend_cli/repo/tests/commands/topics/list.test.ts +0 -125
  1240. package/temp_resend_cli/repo/tests/commands/topics/update.test.ts +0 -178
  1241. package/temp_resend_cli/repo/tests/commands/webhooks/create.test.ts +0 -225
  1242. package/temp_resend_cli/repo/tests/commands/webhooks/delete.test.ts +0 -157
  1243. package/temp_resend_cli/repo/tests/commands/webhooks/get.test.ts +0 -126
  1244. package/temp_resend_cli/repo/tests/commands/webhooks/list.test.ts +0 -178
  1245. package/temp_resend_cli/repo/tests/commands/webhooks/update.test.ts +0 -207
  1246. package/temp_resend_cli/repo/tests/commands/whoami.test.ts +0 -98
  1247. package/temp_resend_cli/repo/tests/e2e/smoke.test.ts +0 -93
  1248. package/temp_resend_cli/repo/tests/helpers.ts +0 -86
  1249. package/temp_resend_cli/repo/tests/lib/client.test.ts +0 -71
  1250. package/temp_resend_cli/repo/tests/lib/config.test.ts +0 -451
  1251. package/temp_resend_cli/repo/tests/lib/files.test.ts +0 -73
  1252. package/temp_resend_cli/repo/tests/lib/help-text.test.ts +0 -97
  1253. package/temp_resend_cli/repo/tests/lib/output.test.ts +0 -136
  1254. package/temp_resend_cli/repo/tests/lib/prompts.test.ts +0 -185
  1255. package/temp_resend_cli/repo/tests/lib/spinner.test.ts +0 -166
  1256. package/temp_resend_cli/repo/tests/lib/table.test.ts +0 -63
  1257. package/temp_resend_cli/repo/tests/lib/tty.test.ts +0 -89
  1258. package/temp_resend_cli/repo/tests/lib/update-check.test.ts +0 -179
  1259. package/temp_resend_cli/repo/tsconfig.json +0 -14
  1260. package/temp_resend_cli/repo/vitest.config.e2e.ts +0 -8
  1261. package/temp_resend_cli/repo/vitest.config.ts +0 -10
  1262. /package/docs/{plugin-examples.md → plugins-examples.md} +0 -0
@@ -1,3206 +0,0 @@
1
- //! Bytecode compiler for transforming AST to bytecode.
2
- //!
3
- //! The compiler traverses the prepared AST (`PreparedNode` and `Expr` types from `expressions.rs`)
4
- //! and emits bytecode instructions using `CodeBuilder`. It handles variable scoping,
5
- //! control flow, and expression evaluation order following Python semantics.
6
- //!
7
- //! Functions are compiled recursively: when a `PreparedFunctionDef` is encountered,
8
- //! its body is compiled to bytecode and a `Function` struct is created. All compiled
9
- //! functions are collected and returned along with the module code.
10
-
11
- use std::borrow::Cow;
12
-
13
- use super::{
14
- builder::{CodeBuilder, JumpLabel},
15
- code::{Code, ExceptionEntry},
16
- op::Opcode,
17
- };
18
- use crate::{
19
- args::{ArgExprs, CallArg, CallKwarg, Kwarg},
20
- builtins::Builtins,
21
- exception_private::ExcType,
22
- exception_public::{MontyException, StackFrame},
23
- expressions::{
24
- Callable, CmpOperator, Comprehension, DictItem, Expr, ExprLoc, Identifier, Literal, NameScope, Node, Operator,
25
- PreparedFunctionDef, PreparedNode, SequenceItem, UnpackTarget,
26
- },
27
- fstring::{ConversionFlag, FStringPart, FormatSpec, ParsedFormatSpec, encode_format_spec},
28
- function::Function,
29
- intern::{Interns, StringId},
30
- modules::BuiltinModule,
31
- parse::{CodeRange, ExceptHandler, Try},
32
- value::{EitherStr, Value},
33
- };
34
-
35
- /// Maximum number of arguments allowed in a function call.
36
- ///
37
- /// This limit comes from the bytecode format: `CallFunction` and `CallAttr`
38
- /// use a u8 operand for the argument count, so max 255. Python itself has no
39
- /// such limit but we need one for our bytecode encoding.
40
- const MAX_CALL_ARGS: usize = 255;
41
-
42
- /// Compiles prepared AST nodes to bytecode.
43
- ///
44
- /// The compiler traverses the AST and emits bytecode instructions using
45
- /// `CodeBuilder`. It handles variable scoping, control flow, and expression
46
- /// evaluation order following Python semantics.
47
- ///
48
- /// Functions are compiled recursively and collected in the `functions` vector.
49
- /// When a `PreparedFunctionDef` is encountered, its body is compiled first,
50
- /// creating a `Function` struct that is added to the vector. The index of the
51
- /// function in this vector becomes the operand for MakeFunction/MakeClosure opcodes.
52
- pub struct Compiler<'a> {
53
- /// Current code being built.
54
- code: CodeBuilder,
55
-
56
- /// Reference to interns for string/function lookups.
57
- interns: &'a Interns,
58
-
59
- /// Compiled functions, indexed by their position in this vector.
60
- ///
61
- /// Functions are added in the order they are encountered during compilation.
62
- /// Nested functions are compiled before their containing function's code
63
- /// finishes, so inner functions have lower indices.
64
- functions: Vec<Function>,
65
-
66
- /// Loop stack for break/continue handling.
67
- /// Each entry tracks the loop start offset and pending break jumps.
68
- loop_stack: Vec<LoopInfo>,
69
-
70
- /// Stack of finally targets for handling returns inside try-finally.
71
- ///
72
- /// When a return statement is compiled inside a try-finally block, instead
73
- /// of immediately returning, we store the return value and jump to the
74
- /// finally block. The finally block will then execute the return.
75
- finally_targets: Vec<FinallyTarget>,
76
-
77
- /// Tracks nesting depth inside exception handlers.
78
- ///
79
- /// When break/continue/return is inside an except handler, we need to
80
- /// clear the current exception (`ClearException`) and pop the exception
81
- /// value from the stack before jumping to the finally path or loop target.
82
- except_handler_depth: usize,
83
-
84
- /// Whether the compiler is currently compiling module-level code.
85
- ///
86
- /// At module level, `Local` and `LocalUnassigned` scopes map to global opcodes
87
- /// (`LoadGlobal`/`StoreGlobal`/`DeleteGlobal`) because module locals live in the
88
- /// globals array. In function bodies this is `false` and these scopes use local
89
- /// opcodes that index into the stack.
90
- is_module_scope: bool,
91
- }
92
-
93
- /// Information about a loop for break/continue handling.
94
- ///
95
- /// Tracks the bytecode locations needed for compiling break and continue statements:
96
- /// - `start`: where continue should jump to (the ForIter instruction for `for` loops,
97
- /// or condition evaluation for `while` loops)
98
- /// - `break_jumps`: pending jumps from break statements that need to be patched
99
- /// to jump past the loop's else block
100
- /// - `has_iterator_on_stack`: whether this loop has an iterator on the stack that
101
- /// needs to be popped on break (true for `for` loops, false for `while` loops)
102
- struct LoopInfo {
103
- /// Bytecode offset of loop start (for continue).
104
- start: usize,
105
- /// Jump labels that need patching to loop end (for break).
106
- break_jumps: Vec<JumpLabel>,
107
- /// Whether this loop has an iterator on the stack.
108
- /// True for `for` loops, false for `while` loops.
109
- has_iterator_on_stack: bool,
110
- }
111
-
112
- /// A break or continue that needs to go through a finally block.
113
- ///
114
- /// When break/continue is inside a try-finally, we need to run the finally block
115
- /// before executing the break/continue. This struct tracks the jump and which
116
- /// loop it targets.
117
- struct BreakContinueThruFinally {
118
- /// The jump instruction that needs to be patched.
119
- jump: JumpLabel,
120
- /// The loop depth (index in loop_stack) being targeted.
121
- target_loop_depth: usize,
122
- }
123
-
124
- /// Tracks a finally block for handling returns/break/continue inside try-finally.
125
- ///
126
- /// When compiling a try-finally, we push a `FinallyTarget` to track jumps
127
- /// from return/break/continue statements that need to go through the finally block.
128
- struct FinallyTarget {
129
- /// Jump labels for returns inside the try block that need to go to finally.
130
- return_jumps: Vec<JumpLabel>,
131
- /// Break statements that need to go through this finally block.
132
- break_jumps: Vec<BreakContinueThruFinally>,
133
- /// Continue statements that need to go through this finally block.
134
- continue_jumps: Vec<BreakContinueThruFinally>,
135
- /// The loop depth when this finally was entered.
136
- /// Used to determine if break/continue targets a loop outside this finally.
137
- loop_depth_at_entry: usize,
138
- }
139
-
140
- /// Result of module compilation: the module code and all compiled functions.
141
- pub struct CompileResult {
142
- /// The compiled module code.
143
- pub code: Code,
144
- /// All functions compiled during module compilation, indexed by their function ID.
145
- pub functions: Vec<Function>,
146
- }
147
-
148
- impl<'a> Compiler<'a> {
149
- /// Creates a new compiler with access to the string interner.
150
- fn new(interns: &'a Interns, functions: Vec<Function>) -> Self {
151
- Self {
152
- code: CodeBuilder::new(),
153
- interns,
154
- functions,
155
- loop_stack: Vec::new(),
156
- finally_targets: Vec::new(),
157
- except_handler_depth: 0,
158
- is_module_scope: false,
159
- }
160
- }
161
-
162
- /// Compiles module-level code (a sequence of statements).
163
- ///
164
- /// Returns the compiled module Code and all compiled Functions, or a compile
165
- /// error if limits were exceeded. The module implicitly returns the value
166
- /// of the last expression, or None if empty.
167
- pub fn compile_module(
168
- nodes: &[PreparedNode],
169
- interns: &Interns,
170
- num_locals: u16,
171
- ) -> Result<CompileResult, CompileError> {
172
- Self::compile_module_with_functions(nodes, interns, num_locals, Vec::new())
173
- }
174
-
175
- /// Compiles module-level code while preserving an existing function table prefix.
176
- ///
177
- /// This is used by incremental REPL compilation so previously created
178
- /// `FunctionId`s remain stable: new function IDs are allocated after
179
- /// `existing_functions.len()`.
180
- pub fn compile_module_with_functions(
181
- nodes: &[PreparedNode],
182
- interns: &Interns,
183
- num_locals: u16,
184
- existing_functions: Vec<Function>,
185
- ) -> Result<CompileResult, CompileError> {
186
- let mut compiler = Compiler::new(interns, Vec::new());
187
- compiler.functions = existing_functions;
188
- compiler.is_module_scope = true;
189
- compiler.compile_block(nodes)?;
190
-
191
- // Module returns None if no explicit return
192
- compiler.code.emit(Opcode::LoadNone);
193
- compiler.code.emit(Opcode::ReturnValue);
194
-
195
- Ok(CompileResult {
196
- code: compiler.code.build(num_locals),
197
- functions: compiler.functions,
198
- })
199
- }
200
-
201
- /// Compiles a function body to bytecode, returning the Code and any nested functions.
202
- ///
203
- /// Used internally when compiling function definitions. The function body is
204
- /// compiled to bytecode with an implicit `return None` at the end if there's
205
- /// no explicit return statement.
206
- ///
207
- /// The `functions` parameter receives any previously compiled functions, and
208
- /// any nested functions found in the body will be added to it.
209
- fn compile_function_body(
210
- body: &[PreparedNode],
211
- interns: &Interns,
212
- functions: Vec<Function>,
213
- num_locals: u16,
214
- ) -> Result<(Code, Vec<Function>), CompileError> {
215
- let mut compiler = Compiler::new(interns, functions);
216
- compiler.compile_block(body)?;
217
-
218
- // Implicit return None if no explicit return
219
- compiler.code.emit(Opcode::LoadNone);
220
- compiler.code.emit(Opcode::ReturnValue);
221
-
222
- Ok((compiler.code.build(num_locals), compiler.functions))
223
- }
224
-
225
- /// Compiles a block of statements.
226
- fn compile_block(&mut self, nodes: &[PreparedNode]) -> Result<(), CompileError> {
227
- for node in nodes {
228
- self.compile_stmt(node)?;
229
- }
230
- Ok(())
231
- }
232
-
233
- // ========================================================================
234
- // Statement Compilation
235
- // ========================================================================
236
-
237
- /// Compiles a single statement.
238
- fn compile_stmt(&mut self, node: &PreparedNode) -> Result<(), CompileError> {
239
- // Node is an alias, use qualified path for matching
240
- match node {
241
- Node::Expr(expr) => {
242
- self.compile_expr(expr)?;
243
- self.code.emit(Opcode::Pop); // Discard result
244
- }
245
- Node::Return(expr) => {
246
- self.compile_expr(expr)?;
247
- self.compile_return();
248
- }
249
- Node::ReturnNone => {
250
- self.code.emit(Opcode::LoadNone);
251
- self.compile_return();
252
- }
253
- Node::Assign { target, object } => {
254
- self.compile_expr(object)?;
255
- self.compile_store(target);
256
- }
257
- Node::UnpackAssign {
258
- targets,
259
- targets_position,
260
- object,
261
- } => {
262
- self.compile_expr(object)?;
263
-
264
- // Check if there's a starred target
265
- let star_idx = targets.iter().position(|t| matches!(t, UnpackTarget::Starred(_)));
266
-
267
- // Set location to targets for proper caret in tracebacks
268
- self.code.set_location(*targets_position, None);
269
-
270
- if let Some(star_idx) = star_idx {
271
- // Has starred target - use UnpackEx
272
- let before = u8::try_from(star_idx).expect("too many targets before star");
273
- let after = u8::try_from(targets.len() - star_idx - 1).expect("too many targets after star");
274
- self.code.emit_u8_u8(Opcode::UnpackEx, before, after);
275
- } else {
276
- // No starred target - use UnpackSequence
277
- let count = u8::try_from(targets.len()).expect("too many targets in unpack");
278
- self.code.emit_u8(Opcode::UnpackSequence, count);
279
- }
280
-
281
- // After UnpackSequence/UnpackEx, values are on stack with first item on top
282
- // Store them in order (first target gets first item), handling nesting
283
- for target in targets {
284
- self.compile_unpack_target(target);
285
- }
286
- }
287
- Node::OpAssign { target, op, object } => {
288
- let Some(opcode) = operator_to_inplace_opcode(op) else {
289
- return Err(CompileError::new(
290
- "matrix multiplication augmented assignment (@=) is not yet supported",
291
- target.position,
292
- ));
293
- };
294
- self.compile_name(target);
295
- self.compile_expr(object)?;
296
- self.code.emit(opcode);
297
- self.compile_store(target);
298
- }
299
- Node::SubscriptOpAssign {
300
- target,
301
- index,
302
- op,
303
- object,
304
- target_position,
305
- } => {
306
- let Some(opcode) = operator_to_inplace_opcode(op) else {
307
- return Err(CompileError::new(
308
- "matrix multiplication augmented assignment (@=) is not yet supported",
309
- *target_position,
310
- ));
311
- };
312
- self.compile_name(target);
313
- self.compile_expr(index)?;
314
- self.code.emit(Opcode::Dup2);
315
- self.code.set_location(*target_position, None);
316
- self.code.emit(Opcode::BinarySubscr);
317
- self.compile_expr(object)?;
318
- self.code.emit(opcode);
319
- self.code.emit(Opcode::Rot3);
320
- self.code.set_location(*target_position, None);
321
- self.code.emit(Opcode::StoreSubscr);
322
- }
323
- Node::SubscriptAssign {
324
- target,
325
- index,
326
- value,
327
- target_position,
328
- } => {
329
- // Stack order for StoreSubscr: value, obj, index
330
- self.compile_expr(value)?;
331
- self.compile_name(target);
332
- self.compile_expr(index)?;
333
- // Set location to the target (e.g., `lst[10]`) for proper caret in tracebacks
334
- self.code.set_location(*target_position, None);
335
- self.code.emit(Opcode::StoreSubscr);
336
- }
337
- Node::AttrAssign {
338
- object,
339
- attr,
340
- target_position,
341
- value,
342
- } => {
343
- // Stack order for StoreAttr: value, obj
344
- self.compile_expr(value)?;
345
- self.compile_expr(object)?;
346
- let name_id = attr.string_id().expect("StoreAttr requires interned attr name");
347
- // Set location to the target (e.g., `x.foo`) for proper caret in tracebacks
348
- self.code.set_location(*target_position, None);
349
- self.code.emit_u16(
350
- Opcode::StoreAttr,
351
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
352
- );
353
- }
354
- Node::If { test, body, or_else } => self.compile_if(test, body, or_else)?,
355
- Node::For {
356
- target,
357
- iter,
358
- body,
359
- or_else,
360
- } => self.compile_for(target, iter, body, or_else)?,
361
- Node::While { test, body, or_else } => self.compile_while(test, body, or_else)?,
362
- Node::Assert { test, msg } => self.compile_assert(test, msg.as_ref())?,
363
- Node::Raise(expr) => {
364
- if let Some(exc) = expr {
365
- self.compile_expr(exc)?;
366
- self.code.emit(Opcode::Raise);
367
- } else {
368
- self.code.emit(Opcode::Reraise);
369
- }
370
- }
371
- Node::FunctionDef(func_def) => self.compile_function_def(func_def)?,
372
- Node::Try(try_block) => self.compile_try(try_block)?,
373
- Node::Import { module_name, binding } => self.compile_import(*module_name, binding),
374
- Node::ImportFrom {
375
- module_name,
376
- names,
377
- position,
378
- } => self.compile_import_from(*module_name, names, *position),
379
- Node::Break { position } => self.compile_break(*position)?,
380
- Node::Continue { position } => self.compile_continue(*position)?,
381
- // These are handled during the prepare phase and produce no bytecode
382
- Node::Pass | Node::Global { .. } | Node::Nonlocal { .. } => {}
383
- }
384
- Ok(())
385
- }
386
-
387
- /// Compiles a function definition.
388
- ///
389
- /// This involves:
390
- /// 1. Recursively compiling the function body to bytecode
391
- /// 2. Creating a Function struct with the compiled Code
392
- /// 3. Adding the Function to the compiler's functions vector
393
- /// 4. Emitting bytecode to evaluate defaults and create the function at runtime
394
- fn compile_function_def(&mut self, func_def: &PreparedFunctionDef) -> Result<(), CompileError> {
395
- let func_pos = func_def.name.position;
396
-
397
- // Check bytecode operand limits
398
- if func_def.default_exprs.len() > MAX_CALL_ARGS {
399
- return Err(CompileError::new(
400
- format!("more than {MAX_CALL_ARGS} default parameter values"),
401
- func_pos,
402
- ));
403
- }
404
- if func_def.free_var_enclosing_slots.len() > MAX_CALL_ARGS {
405
- return Err(CompileError::new(
406
- format!("more than {MAX_CALL_ARGS} closure variables"),
407
- func_pos,
408
- ));
409
- }
410
-
411
- // 1. Compile the function body recursively
412
- // Take ownership of functions for the recursive compile, then restore
413
- let functions = std::mem::take(&mut self.functions);
414
- let namespace_size = u16::try_from(func_def.namespace_size).expect("function namespace size exceeds u16");
415
- let (body_code, mut functions) =
416
- Self::compile_function_body(&func_def.body, self.interns, functions, namespace_size)?;
417
-
418
- // 2. Create the compiled Function and add to the vector
419
- let func_id = functions.len();
420
- let function = Function::new(
421
- func_def.name,
422
- func_def.signature.clone(),
423
- func_def.namespace_size,
424
- func_def.free_var_enclosing_slots.clone(),
425
- func_def.cell_var_count,
426
- func_def.cell_param_indices.clone(),
427
- func_def.default_exprs.len(),
428
- func_def.is_async,
429
- body_code,
430
- );
431
- functions.push(function);
432
-
433
- // Restore functions to self
434
- self.functions = functions;
435
-
436
- // 3. Compile and push default values (evaluated at definition time)
437
- for default_expr in &func_def.default_exprs {
438
- self.compile_expr(default_expr)?;
439
- }
440
- let defaults_count =
441
- u8::try_from(func_def.default_exprs.len()).expect("function default argument count exceeds u8");
442
- let func_id_u16 = u16::try_from(func_id).expect("function count exceeds u16");
443
-
444
- // 4. Emit MakeFunction or MakeClosure (if has free vars)
445
- if func_def.free_var_enclosing_slots.is_empty() {
446
- // MakeFunction: func_id (u16) + defaults_count (u8)
447
- self.code.emit_u16_u8(Opcode::MakeFunction, func_id_u16, defaults_count);
448
- } else {
449
- // Push captured cells from enclosing scope
450
- for &slot in &func_def.free_var_enclosing_slots {
451
- // Load the cell reference from the enclosing namespace
452
- let slot_u16 = u16::try_from(slot.index()).expect("closure slot index exceeds u16");
453
- self.code.emit_load_local(slot_u16);
454
- }
455
- let cell_count =
456
- u8::try_from(func_def.free_var_enclosing_slots.len()).expect("closure cell count exceeds u8");
457
- // MakeClosure: func_id (u16) + defaults_count (u8) + cell_count (u8)
458
- self.code
459
- .emit_u16_u8_u8(Opcode::MakeClosure, func_id_u16, defaults_count, cell_count);
460
- }
461
-
462
- // 5. Store the function object to its name slot
463
- self.compile_store(&func_def.name);
464
-
465
- Ok(())
466
- }
467
-
468
- /// Compiles a lambda expression.
469
- ///
470
- /// This is similar to `compile_function_def` but:
471
- /// - Does NOT store the function to a name slot (it stays on the stack as an expression result)
472
- ///
473
- /// The lambda's `PreparedFunctionDef` already has `<lambda>` as its name.
474
- fn compile_lambda(&mut self, func_def: &PreparedFunctionDef) -> Result<(), CompileError> {
475
- let func_pos = func_def.name.position;
476
-
477
- // Check bytecode operand limits
478
- if func_def.default_exprs.len() > MAX_CALL_ARGS {
479
- return Err(CompileError::new(
480
- format!("more than {MAX_CALL_ARGS} default parameter values"),
481
- func_pos,
482
- ));
483
- }
484
- if func_def.free_var_enclosing_slots.len() > MAX_CALL_ARGS {
485
- return Err(CompileError::new(
486
- format!("more than {MAX_CALL_ARGS} closure variables"),
487
- func_pos,
488
- ));
489
- }
490
-
491
- // 1. Compile the function body recursively
492
- let functions = std::mem::take(&mut self.functions);
493
- let namespace_size = u16::try_from(func_def.namespace_size).expect("function namespace size exceeds u16");
494
- let (body_code, mut functions) =
495
- Self::compile_function_body(&func_def.body, self.interns, functions, namespace_size)?;
496
-
497
- // 2. Create the compiled Function and add to the vector
498
- let func_id = functions.len();
499
- let function = Function::new(
500
- func_def.name,
501
- func_def.signature.clone(),
502
- func_def.namespace_size,
503
- func_def.free_var_enclosing_slots.clone(),
504
- func_def.cell_var_count,
505
- func_def.cell_param_indices.clone(),
506
- func_def.default_exprs.len(),
507
- func_def.is_async,
508
- body_code,
509
- );
510
- functions.push(function);
511
-
512
- // Restore functions to self
513
- self.functions = functions;
514
-
515
- // 3. Compile and push default values (evaluated at definition time)
516
- for default_expr in &func_def.default_exprs {
517
- self.compile_expr(default_expr)?;
518
- }
519
- let defaults_count =
520
- u8::try_from(func_def.default_exprs.len()).expect("function default argument count exceeds u8");
521
- let func_id_u16 = u16::try_from(func_id).expect("function count exceeds u16");
522
-
523
- // 4. Emit MakeFunction or MakeClosure (if has free vars)
524
- if func_def.free_var_enclosing_slots.is_empty() {
525
- // MakeFunction: func_id (u16) + defaults_count (u8)
526
- self.code.emit_u16_u8(Opcode::MakeFunction, func_id_u16, defaults_count);
527
- } else {
528
- // Push captured cells from enclosing scope
529
- for &slot in &func_def.free_var_enclosing_slots {
530
- let slot_u16 = u16::try_from(slot.index()).expect("closure slot index exceeds u16");
531
- self.code.emit_load_local(slot_u16);
532
- }
533
- let cell_count =
534
- u8::try_from(func_def.free_var_enclosing_slots.len()).expect("closure cell count exceeds u8");
535
- // MakeClosure: func_id (u16) + defaults_count (u8) + cell_count (u8)
536
- self.code
537
- .emit_u16_u8_u8(Opcode::MakeClosure, func_id_u16, defaults_count, cell_count);
538
- }
539
-
540
- // NOTE: Unlike compile_function_def, we do NOT call compile_store here.
541
- // The function object stays on the stack as an expression result.
542
-
543
- Ok(())
544
- }
545
-
546
- /// Compiles an import statement.
547
- ///
548
- /// Emits `LoadModule` to create the module, then stores it to the binding name.
549
- /// If the module is unknown, emits `RaiseImportError` to defer the error to runtime.
550
- /// This allows imports inside `if TYPE_CHECKING:` blocks to compile successfully.
551
- fn compile_import(&mut self, module_name: StringId, binding: &Identifier) {
552
- let position = binding.position;
553
- self.code.set_location(position, None);
554
-
555
- // Look up the module by name
556
- if let Some(builtin_module) = BuiltinModule::from_string_id(module_name) {
557
- // Known module - emit LoadModule
558
- self.code.emit_u8(Opcode::LoadModule, builtin_module as u8);
559
- // Store to the binding (respects Local/Global/Cell scope)
560
- self.compile_store(binding);
561
- } else {
562
- // Unknown module - defer error to runtime with RaiseImportError
563
- // This allows TYPE_CHECKING imports to compile without error
564
- let name_const = self.code.add_const(Value::InternString(module_name));
565
- self.code.emit_u16(Opcode::RaiseImportError, name_const);
566
- }
567
- }
568
-
569
- /// Compiles a `from module import name, ...` statement.
570
- ///
571
- /// Creates the module once, then loads each attribute and stores to the binding.
572
- /// Invalid attribute names will raise `AttributeError` at runtime.
573
- /// If the module is unknown, emits `RaiseImportError` to defer the error to runtime.
574
- /// This allows imports inside `if TYPE_CHECKING:` blocks to compile successfully.
575
- fn compile_import_from(&mut self, module_name: StringId, names: &[(StringId, Identifier)], position: CodeRange) {
576
- self.code.set_location(position, None);
577
-
578
- // Look up the module
579
- if let Some(builtin_module) = BuiltinModule::from_string_id(module_name) {
580
- // Known module - emit LoadModule
581
- self.code.emit_u8(Opcode::LoadModule, builtin_module as u8);
582
-
583
- // For each name to import
584
- for (i, (import_name, binding)) in names.iter().enumerate() {
585
- // Dup the module if this isn't the last import (last one consumes the module)
586
- if i < names.len() - 1 {
587
- self.code.emit(Opcode::Dup);
588
- }
589
-
590
- // Load the attribute from the module (raises ImportError if not found)
591
- let name_idx = u16::try_from(import_name.index()).expect("name index exceeds u16");
592
- self.code.emit_u16(Opcode::LoadAttrImport, name_idx);
593
-
594
- // Store to the binding
595
- self.compile_store(binding);
596
- }
597
- } else {
598
- // Unknown module - defer error to runtime with RaiseImportError
599
- // This allows TYPE_CHECKING imports to compile without error
600
- let name_const = self.code.add_const(Value::InternString(module_name));
601
- self.code.emit_u16(Opcode::RaiseImportError, name_const);
602
- }
603
- }
604
-
605
- // ========================================================================
606
- // Expression Compilation
607
- // ========================================================================
608
-
609
- /// Compiles an expression, leaving its value on the stack.
610
- fn compile_expr(&mut self, expr_loc: &ExprLoc) -> Result<(), CompileError> {
611
- // Set source location for traceback info
612
- self.code.set_location(expr_loc.position, None);
613
-
614
- match &expr_loc.expr {
615
- Expr::Literal(lit) => self.compile_literal(lit),
616
-
617
- Expr::Name(ident) => self.compile_name(ident),
618
-
619
- Expr::Builtin(builtin) => {
620
- let idx = self.code.add_const(Value::Builtin(*builtin));
621
- self.code.emit_u16(Opcode::LoadConst, idx);
622
- }
623
-
624
- Expr::Op { left, op, right } => {
625
- self.compile_binary_op(left, op, right, expr_loc.position)?;
626
- }
627
-
628
- Expr::CmpOp { left, op, right } => {
629
- self.compile_expr(left)?;
630
- self.compile_expr(right)?;
631
- // Restore the full comparison expression's position for traceback caret range
632
- self.code.set_location(expr_loc.position, None);
633
- // ModEq needs special handling - it has a constant operand
634
- if let CmpOperator::ModEq(value) = op {
635
- let const_idx = self.code.add_const(Value::Int(*value));
636
- self.code.emit_u16(Opcode::CompareModEq, const_idx);
637
- } else {
638
- self.code.emit(cmp_operator_to_opcode(op));
639
- }
640
- }
641
-
642
- Expr::ChainCmp { left, comparisons } => {
643
- self.compile_chain_comparison(left, comparisons, expr_loc.position)?;
644
- }
645
-
646
- Expr::Not(operand) => {
647
- self.compile_expr(operand)?;
648
- // Restore the full expression's position for traceback caret range
649
- self.code.set_location(expr_loc.position, None);
650
- self.code.emit(Opcode::UnaryNot);
651
- }
652
-
653
- Expr::UnaryMinus(operand) => {
654
- self.compile_expr(operand)?;
655
- // Restore the full expression's position for traceback caret range
656
- self.code.set_location(expr_loc.position, None);
657
- self.code.emit(Opcode::UnaryNeg);
658
- }
659
-
660
- Expr::UnaryPlus(operand) => {
661
- self.compile_expr(operand)?;
662
- // Restore the full expression's position for traceback caret range
663
- self.code.set_location(expr_loc.position, None);
664
- self.code.emit(Opcode::UnaryPos);
665
- }
666
-
667
- Expr::UnaryInvert(operand) => {
668
- self.compile_expr(operand)?;
669
- // Restore the full expression's position for traceback caret range
670
- self.code.set_location(expr_loc.position, None);
671
- self.code.emit(Opcode::UnaryInvert);
672
- }
673
-
674
- Expr::List(elements) => {
675
- if has_unpack_seq(elements) {
676
- // Generalized path: build incrementally for PEP 448 *unpacks
677
- self.code.emit_u16(Opcode::BuildList, 0);
678
- for item in elements {
679
- match item {
680
- SequenceItem::Value(e) => {
681
- self.compile_expr(e)?;
682
- self.code.emit_u8(Opcode::ListAppend, 0);
683
- }
684
- SequenceItem::Unpack(e) => {
685
- self.compile_expr(e)?;
686
- self.code.emit(Opcode::ListExtend);
687
- }
688
- }
689
- }
690
- } else {
691
- // Fast path: all values, single BuildList.
692
- // SAFETY: has_unpack_seq(elements) is false, so every item is Value.
693
- for item in elements {
694
- let SequenceItem::Value(e) = item else {
695
- unreachable!("list fast path: only Value items")
696
- };
697
- self.compile_expr(e)?;
698
- }
699
- self.code.emit_u16(
700
- Opcode::BuildList,
701
- u16::try_from(elements.len()).expect("elements count exceeds u16"),
702
- );
703
- }
704
- }
705
-
706
- Expr::Tuple(elements) => {
707
- if has_unpack_seq(elements) {
708
- // Generalized path: build via list then convert for PEP 448 *unpacks
709
- self.code.emit_u16(Opcode::BuildList, 0);
710
- for item in elements {
711
- match item {
712
- SequenceItem::Value(e) => {
713
- self.compile_expr(e)?;
714
- self.code.emit_u8(Opcode::ListAppend, 0);
715
- }
716
- SequenceItem::Unpack(e) => {
717
- self.compile_expr(e)?;
718
- self.code.emit(Opcode::ListExtend);
719
- }
720
- }
721
- }
722
- self.code.emit(Opcode::ListToTuple);
723
- } else {
724
- // Fast path: all values, single BuildTuple.
725
- // SAFETY: has_unpack_seq(elements) is false, so every item is Value.
726
- for item in elements {
727
- let SequenceItem::Value(e) = item else {
728
- unreachable!("tuple fast path: only Value items")
729
- };
730
- self.compile_expr(e)?;
731
- }
732
- self.code.emit_u16(
733
- Opcode::BuildTuple,
734
- u16::try_from(elements.len()).expect("elements count exceeds u16"),
735
- );
736
- }
737
- }
738
-
739
- Expr::Dict(dict_items) => {
740
- if has_unpack_dict(dict_items) {
741
- // Generalized path: build incrementally for PEP 448 **unpacks
742
- self.code.emit_u16(Opcode::BuildDict, 0);
743
- for item in dict_items {
744
- match item {
745
- DictItem::Pair(key, value) => {
746
- self.compile_expr(key)?;
747
- self.compile_expr(value)?;
748
- // depth=0: dict is at TOS after key/value are popped
749
- self.code.emit_u8(Opcode::DictSetItem, 0);
750
- }
751
- DictItem::Unpack(e) => {
752
- self.compile_expr(e)?;
753
- // depth=0: dict is directly below mapping on stack
754
- self.code.emit_u8(Opcode::DictUpdate, 0);
755
- }
756
- }
757
- }
758
- } else {
759
- // Fast path: all pairs, single BuildDict.
760
- // SAFETY: has_unpack_dict(dict_items) is false, so every item is Pair.
761
- for item in dict_items {
762
- let DictItem::Pair(key, value) = item else {
763
- unreachable!("dict fast path: only Pair items")
764
- };
765
- self.compile_expr(key)?;
766
- self.compile_expr(value)?;
767
- }
768
- self.code.emit_u16(
769
- Opcode::BuildDict,
770
- u16::try_from(dict_items.len()).expect("pairs count exceeds u16"),
771
- );
772
- }
773
- }
774
-
775
- Expr::Set(elements) => {
776
- if has_unpack_seq(elements) {
777
- // Generalized path: build incrementally for PEP 448 *unpacks
778
- self.code.emit_u16(Opcode::BuildSet, 0);
779
- for item in elements {
780
- match item {
781
- SequenceItem::Value(e) => {
782
- self.compile_expr(e)?;
783
- self.code.emit_u8(Opcode::SetAdd, 0);
784
- }
785
- SequenceItem::Unpack(e) => {
786
- self.compile_expr(e)?;
787
- self.code.emit_u8(Opcode::SetExtend, 0);
788
- }
789
- }
790
- }
791
- } else {
792
- // Fast path: all values, single BuildSet.
793
- // SAFETY: has_unpack_seq(elements) is false, so every item is Value.
794
- for item in elements {
795
- let SequenceItem::Value(e) = item else {
796
- unreachable!("set fast path: only Value items")
797
- };
798
- self.compile_expr(e)?;
799
- }
800
- self.code.emit_u16(
801
- Opcode::BuildSet,
802
- u16::try_from(elements.len()).expect("elements count exceeds u16"),
803
- );
804
- }
805
- }
806
-
807
- Expr::Subscript { object, index } => {
808
- self.compile_expr(object)?;
809
- self.compile_expr(index)?;
810
- // Restore the full subscript expression's position for traceback
811
- self.code.set_location(expr_loc.position, None);
812
- self.code.emit(Opcode::BinarySubscr);
813
- }
814
-
815
- Expr::IfElse { test, body, orelse } => {
816
- self.compile_if_else_expr(test, body, orelse)?;
817
- }
818
-
819
- Expr::AttrGet { object, attr } => {
820
- self.compile_expr(object)?;
821
- // Restore the full expression's position for traceback caret range
822
- self.code.set_location(expr_loc.position, None);
823
- let name_id = attr.string_id().expect("LoadAttr requires interned attr name");
824
- self.code.emit_u16(
825
- Opcode::LoadAttr,
826
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
827
- );
828
- }
829
-
830
- Expr::Call { callable, args } => {
831
- self.compile_call(callable, args, expr_loc.position)?;
832
- }
833
-
834
- Expr::AttrCall { object, attr, args } => {
835
- // Compile the object (will be on the stack)
836
- self.compile_expr(object)?;
837
-
838
- // Compile the attribute call arguments and emit CallAttr
839
- self.compile_method_call(attr, args, expr_loc.position)?;
840
- }
841
-
842
- Expr::IndirectCall { callable, args } => {
843
- // Compile the callable expression (e.g., a lambda)
844
- self.compile_expr(callable)?;
845
-
846
- // Compile arguments and emit the call
847
- self.compile_call_args(args, expr_loc.position)?;
848
- }
849
-
850
- Expr::FString(parts) => {
851
- // Compile each part and build the f-string
852
- let part_count = self.compile_fstring_parts(parts)?;
853
- self.code.emit_u16(Opcode::BuildFString, part_count);
854
- }
855
-
856
- Expr::ListComp { elt, generators } => {
857
- self.compile_list_comp(elt, generators)?;
858
- }
859
-
860
- Expr::SetComp { elt, generators } => {
861
- self.compile_set_comp(elt, generators)?;
862
- }
863
-
864
- Expr::DictComp { key, value, generators } => {
865
- self.compile_dict_comp(key, value, generators)?;
866
- }
867
-
868
- Expr::Lambda { func_def } => {
869
- self.compile_lambda(func_def)?;
870
- }
871
-
872
- Expr::LambdaRaw { .. } => {
873
- // LambdaRaw should be converted to Lambda during prepare phase
874
- unreachable!("Expr::LambdaRaw should not exist after prepare phase")
875
- }
876
-
877
- Expr::Await(value) => {
878
- // Await expressions: compile the inner expression, then emit Await
879
- // Await handles ExternalFuture, Coroutine, and GatherFuture
880
- self.compile_expr(value)?;
881
- // Restore the full expression's position for traceback caret range
882
- self.code.set_location(expr_loc.position, None);
883
- self.code.emit(Opcode::Await);
884
- }
885
-
886
- Expr::Slice { lower, upper, step } => {
887
- // Compile slice components: start, stop, step (push None for missing)
888
- if let Some(lower) = lower {
889
- self.compile_expr(lower)?;
890
- } else {
891
- self.code.emit(Opcode::LoadNone);
892
- }
893
- if let Some(upper) = upper {
894
- self.compile_expr(upper)?;
895
- } else {
896
- self.code.emit(Opcode::LoadNone);
897
- }
898
- if let Some(step) = step {
899
- self.compile_expr(step)?;
900
- } else {
901
- self.code.emit(Opcode::LoadNone);
902
- }
903
- self.code.emit(Opcode::BuildSlice);
904
- }
905
-
906
- Expr::Named { target, value } => {
907
- // Compile the value expression (leaves result on stack)
908
- self.compile_expr(value)?;
909
- // Duplicate so value remains after store
910
- self.code.emit(Opcode::Dup);
911
- // Store to target (pops one copy)
912
- self.compile_store(target);
913
- }
914
- }
915
- Ok(())
916
- }
917
-
918
- // ========================================================================
919
- // Literal Compilation
920
- // ========================================================================
921
-
922
- /// Compiles a literal value.
923
- fn compile_literal(&mut self, literal: &Literal) {
924
- match literal {
925
- Literal::None => {
926
- self.code.emit(Opcode::LoadNone);
927
- }
928
-
929
- Literal::Bool(true) => {
930
- self.code.emit(Opcode::LoadTrue);
931
- }
932
-
933
- Literal::Bool(false) => {
934
- self.code.emit(Opcode::LoadFalse);
935
- }
936
-
937
- Literal::Int(n) => {
938
- // Use LoadSmallInt for values that fit in i8
939
- if let Ok(small) = i8::try_from(*n) {
940
- self.code.emit_i8(Opcode::LoadSmallInt, small);
941
- } else {
942
- let idx = self.code.add_const(Value::from(*literal));
943
- self.code.emit_u16(Opcode::LoadConst, idx);
944
- }
945
- }
946
-
947
- // For Float, Str, Bytes, Ellipsis - use LoadConst with Value::from
948
- _ => {
949
- let idx = self.code.add_const(Value::from(*literal));
950
- self.code.emit_u16(Opcode::LoadConst, idx);
951
- }
952
- }
953
- }
954
-
955
- // ========================================================================
956
- // Variable Operations
957
- // ========================================================================
958
-
959
- /// Compiles loading a variable onto the stack.
960
- ///
961
- /// At module level, `Local` and `LocalUnassigned` scopes emit global opcodes
962
- /// because module-level locals live in the globals array.
963
- fn compile_name(&mut self, ident: &Identifier) {
964
- let slot = u16::try_from(ident.namespace_id().index()).expect("local slot exceeds u16");
965
- match ident.scope {
966
- NameScope::Local => {
967
- // True local - register name and mark as assigned for UnboundLocalError
968
- self.code.register_local_name(slot, ident.name_id);
969
- self.code.register_assigned_local(slot);
970
- if self.is_module_scope {
971
- self.code.emit_u16(Opcode::LoadGlobal, slot);
972
- } else {
973
- self.code.emit_load_local(slot);
974
- }
975
- }
976
- NameScope::LocalUnassigned => {
977
- // Undefined reference - register name but NOT as assigned for NameError
978
- self.code.register_local_name(slot, ident.name_id);
979
- if self.is_module_scope {
980
- self.code.emit_u16(Opcode::LoadGlobal, slot);
981
- } else {
982
- self.code.emit_load_local(slot);
983
- }
984
- }
985
- NameScope::Global => {
986
- // Register the name for NameError/NameLookup messages
987
- self.code.register_local_name(slot, ident.name_id);
988
- self.code.emit_u16(Opcode::LoadGlobal, slot);
989
- }
990
- NameScope::Cell => {
991
- // Register the name for NameError messages (unbound free variable)
992
- self.code.register_local_name(slot, ident.name_id);
993
- // Emit local slot index — the VM reads the cell HeapId from the stack
994
- self.code.emit_u16(Opcode::LoadCell, slot);
995
- }
996
- }
997
- }
998
-
999
- /// Compiles loading a variable in call context (e.g., `foo()` loads `foo`).
1000
- ///
1001
- /// For `LocalUnassigned` and `Global` scopes, emits callable-aware load opcodes
1002
- /// that push `ExtFunction(name_id)` for undefined names instead of yielding
1003
- /// `NameLookup`. This allows execution to reach `CallFunction`, which naturally
1004
- /// yields `FunctionCall` — giving the host a chance to handle external function calls.
1005
- ///
1006
- /// For `Local` and `Cell` scopes, delegates to `compile_name` since those can't
1007
- /// be external functions (they're always defined locally or captured).
1008
- fn compile_name_callable(&mut self, ident: &Identifier) {
1009
- let slot = u16::try_from(ident.namespace_id().index()).expect("local slot exceeds u16");
1010
- match ident.scope {
1011
- NameScope::LocalUnassigned => {
1012
- // Undefined reference in call context - use callable-aware load.
1013
- // At module level, use global callable since locals are in the globals array.
1014
- self.code.register_local_name(slot, ident.name_id);
1015
- if self.is_module_scope {
1016
- self.code.emit_load_global_callable(slot, ident.name_id);
1017
- } else {
1018
- self.code.emit_load_local_callable(slot, ident.name_id);
1019
- }
1020
- }
1021
- NameScope::Global => {
1022
- // Global scope - name_id is encoded in the operand because global slot
1023
- // indices are in a different namespace from local slots, so looking up
1024
- // the name from the current frame's local_names would be incorrect
1025
- self.code.emit_load_global_callable(slot, ident.name_id);
1026
- }
1027
- // Local and Cell can't be external functions - use regular load
1028
- NameScope::Local | NameScope::Cell => self.compile_name(ident),
1029
- }
1030
- }
1031
-
1032
- /// Compiles storing the top of stack to a variable.
1033
- ///
1034
- /// At module level, `Local` and `LocalUnassigned` scopes emit `StoreGlobal`
1035
- /// because module-level locals live in the globals array.
1036
- fn compile_store(&mut self, target: &Identifier) {
1037
- let slot = u16::try_from(target.namespace_id().index()).expect("local slot exceeds u16");
1038
- match target.scope {
1039
- NameScope::Local | NameScope::LocalUnassigned => {
1040
- self.code.register_local_name(slot, target.name_id);
1041
- if self.is_module_scope {
1042
- self.code.emit_u16(Opcode::StoreGlobal, slot);
1043
- } else {
1044
- self.code.emit_store_local(slot);
1045
- }
1046
- }
1047
- NameScope::Global => {
1048
- self.code.emit_u16(Opcode::StoreGlobal, slot);
1049
- }
1050
- NameScope::Cell => {
1051
- // Emit local slot index — the VM reads the cell HeapId from the stack
1052
- self.code.emit_u16(Opcode::StoreCell, slot);
1053
- }
1054
- }
1055
- }
1056
-
1057
- // ========================================================================
1058
- // Binary Operator Compilation
1059
- // ========================================================================
1060
-
1061
- /// Compiles a binary operation.
1062
- ///
1063
- /// `parent_pos` is the position of the full binary expression (e.g., `1 / 0`),
1064
- /// which we restore before emitting the opcode so tracebacks show the right range.
1065
- fn compile_binary_op(
1066
- &mut self,
1067
- left: &ExprLoc,
1068
- op: &Operator,
1069
- right: &ExprLoc,
1070
- parent_pos: CodeRange,
1071
- ) -> Result<(), CompileError> {
1072
- match op {
1073
- // Short-circuit AND: evaluate left, jump if falsy
1074
- Operator::And => {
1075
- self.compile_expr(left)?;
1076
- let end_jump = self.code.emit_jump(Opcode::JumpIfFalseOrPop);
1077
- self.compile_expr(right)?;
1078
- self.code.patch_jump(end_jump);
1079
- }
1080
-
1081
- // Short-circuit OR: evaluate left, jump if truthy
1082
- Operator::Or => {
1083
- self.compile_expr(left)?;
1084
- let end_jump = self.code.emit_jump(Opcode::JumpIfTrueOrPop);
1085
- self.compile_expr(right)?;
1086
- self.code.patch_jump(end_jump);
1087
- }
1088
-
1089
- // Regular binary operators
1090
- _ => {
1091
- self.compile_expr(left)?;
1092
- self.compile_expr(right)?;
1093
- // Restore the full expression's position for traceback caret range
1094
- self.code.set_location(parent_pos, None);
1095
- self.code.emit(operator_to_opcode(op));
1096
- }
1097
- }
1098
- Ok(())
1099
- }
1100
-
1101
- /// Compiles a chain comparison expression like `a < b < c < d`.
1102
- ///
1103
- /// Chain comparisons evaluate each intermediate value only once and short-circuit
1104
- /// on the first false result. Uses stack manipulation to avoid namespace pollution.
1105
- ///
1106
- /// Bytecode strategy for `a < b < c`:
1107
- /// ```text
1108
- /// eval a # Stack: [a]
1109
- /// eval b # Stack: [a, b]
1110
- /// Dup # Stack: [a, b, b]
1111
- /// Rot3 # Stack: [b, a, b]
1112
- /// CompareLt # Stack: [b, result1]
1113
- /// JumpIfFalseOrPop # if false: jump to cleanup; if true: pop, stack=[b]
1114
- /// eval c # Stack: [b, c]
1115
- /// CompareLt # Stack: [result2]
1116
- /// Jump @end
1117
- /// @cleanup: # Stack: [b, False]
1118
- /// Rot2 # Stack: [False, b]
1119
- /// Pop # Stack: [False]
1120
- /// @end:
1121
- /// ```
1122
- fn compile_chain_comparison(
1123
- &mut self,
1124
- left: &ExprLoc,
1125
- comparisons: &[(CmpOperator, ExprLoc)],
1126
- position: CodeRange,
1127
- ) -> Result<(), CompileError> {
1128
- let n = comparisons.len();
1129
-
1130
- // Remember stack depth before the chain for cleanup calculation
1131
- let base_depth = self.code.stack_depth();
1132
-
1133
- // Compile leftmost operand
1134
- self.compile_expr(left)?;
1135
-
1136
- // Track jump targets for short-circuit cleanup
1137
- let mut cleanup_jumps = Vec::with_capacity(n - 1);
1138
-
1139
- for (i, (op, right)) in comparisons.iter().enumerate() {
1140
- let is_last = i == n - 1;
1141
-
1142
- // Compile the right operand
1143
- self.compile_expr(right)?;
1144
-
1145
- if !is_last {
1146
- // Keep a copy of the intermediate for the next comparison
1147
- self.code.emit(Opcode::Dup);
1148
- // Reorder: [prev, curr, curr] -> [curr, prev, curr]
1149
- self.code.emit(Opcode::Rot3);
1150
- }
1151
-
1152
- // Emit comparison
1153
- self.code.set_location(position, None);
1154
- if let CmpOperator::ModEq(value) = op {
1155
- let const_idx = self.code.add_const(Value::Int(*value));
1156
- self.code.emit_u16(Opcode::CompareModEq, const_idx);
1157
- } else {
1158
- self.code.emit(cmp_operator_to_opcode(op));
1159
- }
1160
-
1161
- if !is_last {
1162
- // Short-circuit: if false, jump to cleanup
1163
- let jump = self.code.emit_jump(Opcode::JumpIfFalseOrPop);
1164
- cleanup_jumps.push(jump);
1165
- }
1166
- }
1167
-
1168
- // Jump past cleanup (result already on stack)
1169
- let end_jump = self.code.emit_jump(Opcode::Jump);
1170
-
1171
- // Cleanup: remove the saved intermediate value, keep False result
1172
- // The cleanup is only reached via JumpIfFalseOrPop which doesn't pop,
1173
- // so the stack has: [intermediate, False] (2 extra items from base)
1174
- for jump in cleanup_jumps {
1175
- self.code.patch_jump(jump);
1176
- }
1177
- self.code.set_stack_depth(base_depth + 2); // [intermediate, False]
1178
- self.code.emit(Opcode::Rot2); // [False, intermediate]
1179
- self.code.emit(Opcode::Pop); // [False]
1180
-
1181
- self.code.patch_jump(end_jump);
1182
- // Final result is on stack: base_depth + 1
1183
- self.code.set_stack_depth(base_depth + 1);
1184
-
1185
- Ok(())
1186
- }
1187
-
1188
- // ========================================================================
1189
- // Control Flow Compilation
1190
- // ========================================================================
1191
-
1192
- /// Compiles an if/else statement.
1193
- fn compile_if(
1194
- &mut self,
1195
- test: &ExprLoc,
1196
- body: &[PreparedNode],
1197
- or_else: &[PreparedNode],
1198
- ) -> Result<(), CompileError> {
1199
- self.compile_expr(test)?;
1200
-
1201
- if or_else.is_empty() {
1202
- // Simple if without else
1203
- let end_jump = self.code.emit_jump(Opcode::JumpIfFalse);
1204
- self.compile_block(body)?;
1205
- self.code.patch_jump(end_jump);
1206
- } else {
1207
- // If with else
1208
- let else_jump = self.code.emit_jump(Opcode::JumpIfFalse);
1209
- self.compile_block(body)?;
1210
- let end_jump = self.code.emit_jump(Opcode::Jump);
1211
- self.code.patch_jump(else_jump);
1212
- self.compile_block(or_else)?;
1213
- self.code.patch_jump(end_jump);
1214
- }
1215
- Ok(())
1216
- }
1217
-
1218
- /// Compiles a ternary conditional expression.
1219
- fn compile_if_else_expr(&mut self, test: &ExprLoc, body: &ExprLoc, orelse: &ExprLoc) -> Result<(), CompileError> {
1220
- self.compile_expr(test)?;
1221
- let else_jump = self.code.emit_jump(Opcode::JumpIfFalse);
1222
- self.compile_expr(body)?;
1223
- let end_jump = self.code.emit_jump(Opcode::Jump);
1224
- self.code.patch_jump(else_jump);
1225
- self.compile_expr(orelse)?;
1226
- self.code.patch_jump(end_jump);
1227
- Ok(())
1228
- }
1229
-
1230
- /// Compiles a function call expression.
1231
- ///
1232
- /// For builtin calls with positional-only arguments, emits the optimized `CallBuiltin`
1233
- /// opcode which avoids pushing/popping the callable on the stack.
1234
- ///
1235
- /// For other calls, pushes the callable onto the stack, then all arguments, then emits
1236
- /// `CallFunction` or `CallFunctionKw`.
1237
- ///
1238
- /// The `call_pos` is the position of the full call expression for proper traceback caret.
1239
- fn compile_call(&mut self, callable: &Callable, args: &ArgExprs, call_pos: CodeRange) -> Result<(), CompileError> {
1240
- // Check if we can use the optimized CallBuiltinFunction path:
1241
- // - Callable must be a builtin function (known at compile time)
1242
- // - Arguments must be positional-only (Empty, One, Two, or Args)
1243
- if let Callable::Builtin(Builtins::Function(builtin_func)) = callable
1244
- && let Some(arg_count) = self.compile_builtin_call(args, call_pos)?
1245
- {
1246
- // Optimization applied - CallBuiltinFunction emitted
1247
- self.code.set_location(call_pos, None);
1248
- self.code.emit_call_builtin_function(*builtin_func as u8, arg_count);
1249
- return Ok(());
1250
- }
1251
- // Fall through to standard path for kwargs/unpacking
1252
-
1253
- // Check if we can use the optimized CallBuiltinType path:
1254
- // - Callable must be a builtin type constructor (known at compile time)
1255
- // - Arguments must be positional-only (Empty, One, Two, or Args)
1256
- if let Callable::Builtin(Builtins::Type(t)) = callable
1257
- && let Some(type_id) = t.callable_to_u8()
1258
- && let Some(arg_count) = self.compile_builtin_call(args, call_pos)?
1259
- {
1260
- // Optimization applied - CallBuiltinType emitted
1261
- self.code.set_location(call_pos, None);
1262
- self.code.emit_call_builtin_type(type_id, arg_count);
1263
- return Ok(());
1264
- }
1265
- // Fall through to standard path for kwargs/unpacking or non-callable types
1266
-
1267
- // Standard path: push callable, compile args, emit CallFunction/CallFunctionKw
1268
- // Push the callable (use name position for NameError caret range)
1269
- match callable {
1270
- Callable::Builtin(builtin) => {
1271
- let idx = self.code.add_const(Value::Builtin(*builtin));
1272
- self.code.emit_u16(Opcode::LoadConst, idx);
1273
- }
1274
- Callable::Name(ident) => {
1275
- // Use callable-aware load opcodes so undefined names produce ExtFunction
1276
- // instead of yielding NameLookup, allowing CallFunction to yield FunctionCall
1277
- self.code.set_location(ident.position, None);
1278
- self.compile_name_callable(ident);
1279
- }
1280
- }
1281
-
1282
- // Compile arguments and emit the call
1283
- // Restore full call position before CallFunction for call-related errors
1284
- match args {
1285
- ArgExprs::Empty => {
1286
- self.code.set_location(call_pos, None);
1287
- self.code.emit_u8(Opcode::CallFunction, 0);
1288
- }
1289
- ArgExprs::One(arg) => {
1290
- self.compile_expr(arg)?;
1291
- self.code.set_location(call_pos, None);
1292
- self.code.emit_u8(Opcode::CallFunction, 1);
1293
- }
1294
- ArgExprs::Two(arg1, arg2) => {
1295
- self.compile_expr(arg1)?;
1296
- self.compile_expr(arg2)?;
1297
- self.code.set_location(call_pos, None);
1298
- self.code.emit_u8(Opcode::CallFunction, 2);
1299
- }
1300
- ArgExprs::Args(args) => {
1301
- // Check argument count limit before compiling
1302
- if args.len() > MAX_CALL_ARGS {
1303
- return Err(CompileError::new(
1304
- format!("more than {MAX_CALL_ARGS} positional arguments in function call"),
1305
- call_pos,
1306
- ));
1307
- }
1308
- for arg in args {
1309
- self.compile_expr(arg)?;
1310
- }
1311
- let arg_count = u8::try_from(args.len()).expect("argument count exceeds u8");
1312
- self.code.set_location(call_pos, None);
1313
- self.code.emit_u8(Opcode::CallFunction, arg_count);
1314
- }
1315
- ArgExprs::Kwargs(kwargs) => {
1316
- // Check keyword argument count limit
1317
- if kwargs.len() > MAX_CALL_ARGS {
1318
- return Err(CompileError::new(
1319
- format!("more than {MAX_CALL_ARGS} keyword arguments in function call"),
1320
- call_pos,
1321
- ));
1322
- }
1323
- // Keyword-only call: compile kwarg values and emit CallFunctionKw
1324
- let mut kwname_ids = Vec::with_capacity(kwargs.len());
1325
- for kwarg in kwargs {
1326
- self.compile_expr(&kwarg.value)?;
1327
- kwname_ids.push(u16::try_from(kwarg.key.name_id.index()).expect("name index exceeds u16"));
1328
- }
1329
- self.code.set_location(call_pos, None);
1330
- self.code.emit_call_function_kw(0, &kwname_ids);
1331
- }
1332
- ArgExprs::ArgsKargs {
1333
- args,
1334
- var_args,
1335
- kwargs,
1336
- var_kwargs,
1337
- } => {
1338
- // Mixed positional and keyword arguments - may include *args or **kwargs unpacking
1339
- if var_args.is_some() || var_kwargs.is_some() {
1340
- // Use CallFunctionEx for unpacking - no limit on this path since
1341
- // args are built into a tuple dynamically at runtime
1342
- self.compile_call_with_unpacking(
1343
- callable,
1344
- args.as_ref(),
1345
- var_args.as_ref(),
1346
- kwargs.as_ref(),
1347
- var_kwargs.as_ref(),
1348
- call_pos,
1349
- )?;
1350
- } else {
1351
- // No unpacking - use CallFunctionKw for efficiency
1352
- // Check limits before compiling
1353
- let pos_count = args.as_ref().map_or(0, Vec::len);
1354
- let kw_count = kwargs.as_ref().map_or(0, Vec::len);
1355
-
1356
- if pos_count > MAX_CALL_ARGS {
1357
- return Err(CompileError::new(
1358
- format!("more than {MAX_CALL_ARGS} positional arguments in function call"),
1359
- call_pos,
1360
- ));
1361
- }
1362
- if kw_count > MAX_CALL_ARGS {
1363
- return Err(CompileError::new(
1364
- format!("more than {MAX_CALL_ARGS} keyword arguments in function call"),
1365
- call_pos,
1366
- ));
1367
- }
1368
-
1369
- // Compile positional args
1370
- if let Some(args) = args {
1371
- for arg in args {
1372
- self.compile_expr(arg)?;
1373
- }
1374
- }
1375
-
1376
- // Compile kwarg values and collect names
1377
- let mut kwname_ids = Vec::new();
1378
- if let Some(kwargs) = kwargs {
1379
- for kwarg in kwargs {
1380
- self.compile_expr(&kwarg.value)?;
1381
- kwname_ids.push(u16::try_from(kwarg.key.name_id.index()).expect("name index exceeds u16"));
1382
- }
1383
- }
1384
-
1385
- self.code.set_location(call_pos, None);
1386
- self.code.emit_call_function_kw(
1387
- u8::try_from(pos_count).expect("positional arg count exceeds u8"),
1388
- &kwname_ids,
1389
- );
1390
- }
1391
- }
1392
- ArgExprs::GeneralizedCall { args, kwargs } => {
1393
- // PEP 448: generalized unpacking — multiple *args or **kwargs.
1394
- // Callable was already pushed above this match; delegate to the helper.
1395
- let func_name_id = match callable {
1396
- Callable::Name(ident) => u16::try_from(ident.name_id.index()).expect("name index exceeds u16"),
1397
- Callable::Builtin(_) => 0xFFFF,
1398
- };
1399
- self.compile_generalized_call_body(args, kwargs, func_name_id, call_pos)?;
1400
- }
1401
- }
1402
- Ok(())
1403
- }
1404
-
1405
- /// Compiles function call arguments and emits the call instruction.
1406
- ///
1407
- /// This is used when the callable is already on the stack (e.g., from compiling an expression).
1408
- /// It compiles the arguments, then emits `CallFunction` or `CallFunctionKw` as appropriate.
1409
- fn compile_call_args(&mut self, args: &ArgExprs, call_pos: CodeRange) -> Result<(), CompileError> {
1410
- match args {
1411
- ArgExprs::Empty => {
1412
- self.code.set_location(call_pos, None);
1413
- self.code.emit_u8(Opcode::CallFunction, 0);
1414
- }
1415
- ArgExprs::One(arg) => {
1416
- self.compile_expr(arg)?;
1417
- self.code.set_location(call_pos, None);
1418
- self.code.emit_u8(Opcode::CallFunction, 1);
1419
- }
1420
- ArgExprs::Two(arg1, arg2) => {
1421
- self.compile_expr(arg1)?;
1422
- self.compile_expr(arg2)?;
1423
- self.code.set_location(call_pos, None);
1424
- self.code.emit_u8(Opcode::CallFunction, 2);
1425
- }
1426
- ArgExprs::Args(args) => {
1427
- if args.len() > MAX_CALL_ARGS {
1428
- return Err(CompileError::new(
1429
- format!("more than {MAX_CALL_ARGS} positional arguments in function call"),
1430
- call_pos,
1431
- ));
1432
- }
1433
- for arg in args {
1434
- self.compile_expr(arg)?;
1435
- }
1436
- let arg_count = u8::try_from(args.len()).expect("argument count exceeds u8");
1437
- self.code.set_location(call_pos, None);
1438
- self.code.emit_u8(Opcode::CallFunction, arg_count);
1439
- }
1440
- ArgExprs::Kwargs(kwargs) => {
1441
- if kwargs.len() > MAX_CALL_ARGS {
1442
- return Err(CompileError::new(
1443
- format!("more than {MAX_CALL_ARGS} keyword arguments in function call"),
1444
- call_pos,
1445
- ));
1446
- }
1447
- let mut kwname_ids = Vec::with_capacity(kwargs.len());
1448
- for kwarg in kwargs {
1449
- self.compile_expr(&kwarg.value)?;
1450
- kwname_ids.push(u16::try_from(kwarg.key.name_id.index()).expect("name index exceeds u16"));
1451
- }
1452
- self.code.set_location(call_pos, None);
1453
- self.code.emit_call_function_kw(0, &kwname_ids);
1454
- }
1455
- ArgExprs::ArgsKargs {
1456
- args,
1457
- kwargs,
1458
- var_args,
1459
- var_kwargs,
1460
- } => {
1461
- // Mixed positional and keyword arguments - may include *args or **kwargs unpacking
1462
- if var_args.is_some() || var_kwargs.is_some() {
1463
- // Use CallFunctionExtended for unpacking - no limit on this path since
1464
- // args are built into a tuple dynamically at runtime.
1465
- // Callable is already on stack, so we just need to build args and kwargs.
1466
- self.compile_call_args_with_unpacking(
1467
- args.as_ref(),
1468
- var_args.as_ref(),
1469
- kwargs.as_ref(),
1470
- var_kwargs.as_ref(),
1471
- call_pos,
1472
- )?;
1473
- } else {
1474
- // No unpacking - use CallFunctionKw for efficiency
1475
- let pos_args = args.as_deref().unwrap_or(&[]);
1476
- let kw_args = kwargs.as_deref().unwrap_or(&[]);
1477
- let pos_count = pos_args.len();
1478
- let kw_count = kw_args.len();
1479
-
1480
- // Check limits separately (same as direct calls)
1481
- if pos_count > MAX_CALL_ARGS {
1482
- return Err(CompileError::new(
1483
- format!("more than {MAX_CALL_ARGS} positional arguments in function call"),
1484
- call_pos,
1485
- ));
1486
- }
1487
- if kw_count > MAX_CALL_ARGS {
1488
- return Err(CompileError::new(
1489
- format!("more than {MAX_CALL_ARGS} keyword arguments in function call"),
1490
- call_pos,
1491
- ));
1492
- }
1493
-
1494
- // Compile positional args
1495
- for arg in pos_args {
1496
- self.compile_expr(arg)?;
1497
- }
1498
-
1499
- // Compile keyword args
1500
- let mut kwname_ids = Vec::with_capacity(kw_count);
1501
- for kwarg in kw_args {
1502
- self.compile_expr(&kwarg.value)?;
1503
- kwname_ids.push(u16::try_from(kwarg.key.name_id.index()).expect("name index exceeds u16"));
1504
- }
1505
-
1506
- self.code.set_location(call_pos, None);
1507
- self.code.emit_call_function_kw(
1508
- u8::try_from(pos_count).expect("positional arg count exceeds u8"),
1509
- &kwname_ids,
1510
- );
1511
- }
1512
- }
1513
- ArgExprs::GeneralizedCall { args, kwargs } => {
1514
- // PEP 448: generalized unpacking — callable is already on the stack.
1515
- // Use 0xFFFF as func_name_id since we don't know the callee name here.
1516
- self.compile_generalized_call_body(args, kwargs, 0xFFFF, call_pos)?;
1517
- }
1518
- }
1519
- Ok(())
1520
- }
1521
-
1522
- /// Compiles arguments with `*args` and/or `**kwargs` unpacking when callable is already on stack.
1523
- ///
1524
- /// This is used for expression calls (e.g., `(lambda *a: a)(*xs)`) where the callable
1525
- /// is compiled as an expression and is already on the stack.
1526
- ///
1527
- /// Stack layout: callable (on stack) -> callable, args_tuple, kwargs_dict?
1528
- fn compile_call_args_with_unpacking(
1529
- &mut self,
1530
- args: Option<&Vec<ExprLoc>>,
1531
- var_args: Option<&ExprLoc>,
1532
- kwargs: Option<&Vec<Kwarg>>,
1533
- var_kwargs: Option<&ExprLoc>,
1534
- call_pos: CodeRange,
1535
- ) -> Result<(), CompileError> {
1536
- // 1. Build args tuple
1537
- // Push regular positional args and build list
1538
- let pos_count = args.map_or(0, Vec::len);
1539
- if let Some(args) = args {
1540
- for arg in args {
1541
- self.compile_expr(arg)?;
1542
- }
1543
- }
1544
- self.code.emit_u16(
1545
- Opcode::BuildList,
1546
- u16::try_from(pos_count).expect("positional arg count exceeds u16"),
1547
- );
1548
-
1549
- // Extend with *args if present
1550
- if let Some(var_args_expr) = var_args {
1551
- self.compile_expr(var_args_expr)?;
1552
- self.code.emit(Opcode::ListExtend);
1553
- }
1554
-
1555
- // Convert list to tuple
1556
- self.code.emit(Opcode::ListToTuple);
1557
-
1558
- // 2. Build kwargs dict (if we have kwargs or var_kwargs)
1559
- let has_kwargs = kwargs.is_some() || var_kwargs.is_some();
1560
- if has_kwargs {
1561
- // Build dict from regular kwargs
1562
- let kw_count = kwargs.map_or(0, Vec::len);
1563
- if let Some(kwargs) = kwargs {
1564
- for kwarg in kwargs {
1565
- // Push key as interned string constant
1566
- let key_const = self.code.add_const(Value::InternString(kwarg.key.name_id));
1567
- self.code.emit_u16(Opcode::LoadConst, key_const);
1568
- // Push value
1569
- self.compile_expr(&kwarg.value)?;
1570
- }
1571
- }
1572
- self.code.emit_u16(
1573
- Opcode::BuildDict,
1574
- u16::try_from(kw_count).expect("keyword count exceeds u16"),
1575
- );
1576
-
1577
- // Merge **kwargs if present
1578
- // Use 0xFFFF for func_name_id (like builtins) since we don't have a name
1579
- if let Some(var_kwargs_expr) = var_kwargs {
1580
- self.compile_expr(var_kwargs_expr)?;
1581
- self.code.emit_u16(Opcode::DictMerge, 0xFFFF);
1582
- }
1583
- }
1584
-
1585
- // 3. Call the function
1586
- self.code.set_location(call_pos, None);
1587
- let flags = u8::from(has_kwargs);
1588
- self.code.emit_u8(Opcode::CallFunctionExtended, flags);
1589
- Ok(())
1590
- }
1591
-
1592
- /// Compiles arguments for a builtin call and returns the arg count if optimization can be used.
1593
- ///
1594
- /// Returns `Some(arg_count)` if the call uses positional-only arguments (CallBuiltinFunction applicable).
1595
- /// Returns `None` if the call uses kwargs or unpacking (must use standard CallFunction path).
1596
- ///
1597
- /// When `Some` is returned, arguments have been compiled onto the stack.
1598
- fn compile_builtin_call(&mut self, args: &ArgExprs, call_pos: CodeRange) -> Result<Option<u8>, CompileError> {
1599
- match args {
1600
- ArgExprs::Empty => Ok(Some(0)),
1601
- ArgExprs::One(arg) => {
1602
- self.compile_expr(arg)?;
1603
- Ok(Some(1))
1604
- }
1605
- ArgExprs::Two(arg1, arg2) => {
1606
- self.compile_expr(arg1)?;
1607
- self.compile_expr(arg2)?;
1608
- Ok(Some(2))
1609
- }
1610
- ArgExprs::Args(args) => {
1611
- if args.len() > MAX_CALL_ARGS {
1612
- return Err(CompileError::new(
1613
- format!("more than {MAX_CALL_ARGS} positional arguments in function call"),
1614
- call_pos,
1615
- ));
1616
- }
1617
- for arg in args {
1618
- self.compile_expr(arg)?;
1619
- }
1620
- Ok(Some(u8::try_from(args.len()).expect("argument count exceeds u8")))
1621
- }
1622
- // Kwargs or unpacking - fall back to standard path
1623
- ArgExprs::Kwargs(_) | ArgExprs::ArgsKargs { .. } | ArgExprs::GeneralizedCall { .. } => Ok(None),
1624
- }
1625
- }
1626
-
1627
- /// Compiles a function call with `*args` and/or `**kwargs` unpacking.
1628
- ///
1629
- /// This generates bytecode to build an args tuple and kwargs dict dynamically,
1630
- /// then calls the function using `CallFunctionEx`.
1631
- ///
1632
- /// Stack layout for call:
1633
- /// - callable (already on stack)
1634
- /// - args tuple
1635
- /// - kwargs dict (if present)
1636
- fn compile_call_with_unpacking(
1637
- &mut self,
1638
- callable: &Callable,
1639
- args: Option<&Vec<ExprLoc>>,
1640
- var_args: Option<&ExprLoc>,
1641
- kwargs: Option<&Vec<Kwarg>>,
1642
- var_kwargs: Option<&ExprLoc>,
1643
- call_pos: CodeRange,
1644
- ) -> Result<(), CompileError> {
1645
- // Get function name for error messages (0xFFFF for builtins)
1646
- let func_name_id = match callable {
1647
- Callable::Name(ident) => u16::try_from(ident.name_id.index()).expect("name index exceeds u16"),
1648
- Callable::Builtin(_) => 0xFFFF,
1649
- };
1650
-
1651
- // 1. Build args tuple
1652
- // Push regular positional args and build list
1653
- let pos_count = args.map_or(0, Vec::len);
1654
- if let Some(args) = args {
1655
- for arg in args {
1656
- self.compile_expr(arg)?;
1657
- }
1658
- }
1659
- self.code.emit_u16(
1660
- Opcode::BuildList,
1661
- u16::try_from(pos_count).expect("positional arg count exceeds u16"),
1662
- );
1663
-
1664
- // Extend with *args if present
1665
- if let Some(var_args_expr) = var_args {
1666
- self.compile_expr(var_args_expr)?;
1667
- self.code.emit(Opcode::ListExtend);
1668
- }
1669
-
1670
- // Convert list to tuple
1671
- self.code.emit(Opcode::ListToTuple);
1672
-
1673
- // 2. Build kwargs dict (if we have kwargs or var_kwargs)
1674
- let has_kwargs = kwargs.is_some() || var_kwargs.is_some();
1675
- if has_kwargs {
1676
- // Build dict from regular kwargs
1677
- let kw_count = kwargs.map_or(0, Vec::len);
1678
- if let Some(kwargs) = kwargs {
1679
- for kwarg in kwargs {
1680
- // Push key as interned string constant
1681
- let key_const = self.code.add_const(Value::InternString(kwarg.key.name_id));
1682
- self.code.emit_u16(Opcode::LoadConst, key_const);
1683
- // Push value
1684
- self.compile_expr(&kwarg.value)?;
1685
- }
1686
- }
1687
- self.code.emit_u16(
1688
- Opcode::BuildDict,
1689
- u16::try_from(kw_count).expect("keyword count exceeds u16"),
1690
- );
1691
-
1692
- // Merge **kwargs if present
1693
- if let Some(var_kwargs_expr) = var_kwargs {
1694
- self.compile_expr(var_kwargs_expr)?;
1695
- self.code.emit_u16(Opcode::DictMerge, func_name_id);
1696
- }
1697
- }
1698
-
1699
- // 3. Call the function
1700
- self.code.set_location(call_pos, None);
1701
- let flags = u8::from(has_kwargs);
1702
- self.code.emit_u8(Opcode::CallFunctionExtended, flags);
1703
- Ok(())
1704
- }
1705
-
1706
- /// Compiles an attribute call on an object.
1707
- ///
1708
- /// The object should already be on the stack. This compiles the arguments
1709
- /// and emits a CallAttr opcode with the attribute name and arg count.
1710
- fn compile_method_call(
1711
- &mut self,
1712
- attr: &EitherStr,
1713
- args: &ArgExprs,
1714
- call_pos: CodeRange,
1715
- ) -> Result<(), CompileError> {
1716
- // Get the interned attribute name
1717
- let name_id = attr.string_id().expect("CallAttr requires interned attr name");
1718
-
1719
- // Compile arguments based on the argument type
1720
- match args {
1721
- ArgExprs::Empty => {
1722
- self.code.set_location(call_pos, None);
1723
- self.code.emit_u16_u8(
1724
- Opcode::CallAttr,
1725
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
1726
- 0,
1727
- );
1728
- }
1729
- ArgExprs::One(arg) => {
1730
- self.compile_expr(arg)?;
1731
- self.code.set_location(call_pos, None);
1732
- self.code.emit_u16_u8(
1733
- Opcode::CallAttr,
1734
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
1735
- 1,
1736
- );
1737
- }
1738
- ArgExprs::Two(arg1, arg2) => {
1739
- self.compile_expr(arg1)?;
1740
- self.compile_expr(arg2)?;
1741
- self.code.set_location(call_pos, None);
1742
- self.code.emit_u16_u8(
1743
- Opcode::CallAttr,
1744
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
1745
- 2,
1746
- );
1747
- }
1748
- ArgExprs::Args(args) => {
1749
- // Check argument count limit
1750
- if args.len() > MAX_CALL_ARGS {
1751
- return Err(CompileError::new(
1752
- format!("more than {MAX_CALL_ARGS} arguments in method call"),
1753
- call_pos,
1754
- ));
1755
- }
1756
- for arg in args {
1757
- self.compile_expr(arg)?;
1758
- }
1759
- let arg_count = u8::try_from(args.len()).expect("argument count exceeds u8");
1760
- self.code.set_location(call_pos, None);
1761
- self.code.emit_u16_u8(
1762
- Opcode::CallAttr,
1763
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
1764
- arg_count,
1765
- );
1766
- }
1767
- ArgExprs::Kwargs(kwargs) => {
1768
- // Keyword-only method call
1769
- if kwargs.len() > MAX_CALL_ARGS {
1770
- return Err(CompileError::new(
1771
- format!("more than {MAX_CALL_ARGS} keyword arguments in method call"),
1772
- call_pos,
1773
- ));
1774
- }
1775
- // Compile kwarg values and collect names
1776
- let mut kwname_ids = Vec::with_capacity(kwargs.len());
1777
- for kwarg in kwargs {
1778
- self.compile_expr(&kwarg.value)?;
1779
- kwname_ids.push(u16::try_from(kwarg.key.name_id.index()).expect("name index exceeds u16"));
1780
- }
1781
- self.code.set_location(call_pos, None);
1782
- self.code.emit_call_attr_kw(
1783
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
1784
- 0, // no positional args
1785
- &kwname_ids,
1786
- );
1787
- }
1788
- ArgExprs::ArgsKargs {
1789
- args,
1790
- kwargs,
1791
- var_args,
1792
- var_kwargs,
1793
- } => {
1794
- // Check if there's unpacking - use CallAttrExtended
1795
- if var_args.is_some() || var_kwargs.is_some() {
1796
- return self.compile_method_call_with_unpacking(
1797
- name_id,
1798
- args.as_ref(),
1799
- var_args.as_ref(),
1800
- kwargs.as_ref(),
1801
- var_kwargs.as_ref(),
1802
- call_pos,
1803
- );
1804
- }
1805
-
1806
- // No unpacking - use CallAttrKw for efficiency
1807
- let pos_count = args.as_ref().map_or(0, Vec::len);
1808
- let kw_count = kwargs.as_ref().map_or(0, Vec::len);
1809
-
1810
- if pos_count > MAX_CALL_ARGS {
1811
- return Err(CompileError::new(
1812
- format!("more than {MAX_CALL_ARGS} positional arguments in method call"),
1813
- call_pos,
1814
- ));
1815
- }
1816
- if kw_count > MAX_CALL_ARGS {
1817
- return Err(CompileError::new(
1818
- format!("more than {MAX_CALL_ARGS} keyword arguments in method call"),
1819
- call_pos,
1820
- ));
1821
- }
1822
-
1823
- // Compile positional args
1824
- if let Some(args) = args {
1825
- for arg in args {
1826
- self.compile_expr(arg)?;
1827
- }
1828
- }
1829
-
1830
- // Compile kwarg values and collect names
1831
- let mut kwname_ids = Vec::new();
1832
- if let Some(kwargs) = kwargs {
1833
- for kwarg in kwargs {
1834
- self.compile_expr(&kwarg.value)?;
1835
- kwname_ids.push(u16::try_from(kwarg.key.name_id.index()).expect("name index exceeds u16"));
1836
- }
1837
- }
1838
-
1839
- self.code.set_location(call_pos, None);
1840
- self.code.emit_call_attr_kw(
1841
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
1842
- u8::try_from(pos_count).expect("positional arg count exceeds u8"),
1843
- &kwname_ids,
1844
- );
1845
- }
1846
- ArgExprs::GeneralizedCall { args, kwargs } => {
1847
- // PEP 448: generalized unpacking on a method call.
1848
- // Receiver is already on the stack; build args tuple and kwargs dict,
1849
- // then emit CallAttrExtended.
1850
- let func_name_id = u16::try_from(name_id.index()).expect("name index exceeds u16");
1851
- let has_kwargs = !kwargs.is_empty();
1852
-
1853
- // 1. Build args tuple
1854
- self.code.emit_u16(Opcode::BuildList, 0);
1855
- for arg in args {
1856
- match arg {
1857
- CallArg::Value(e) => {
1858
- self.compile_expr(e)?;
1859
- self.code.emit_u8(Opcode::ListAppend, 0);
1860
- }
1861
- CallArg::Unpack(e) => {
1862
- self.compile_expr(e)?;
1863
- self.code.emit(Opcode::ListExtend);
1864
- }
1865
- }
1866
- }
1867
- self.code.emit(Opcode::ListToTuple);
1868
-
1869
- // 2. Build kwargs dict (if any)
1870
- if has_kwargs {
1871
- self.code.emit_u16(Opcode::BuildDict, 0);
1872
- for kwarg in kwargs {
1873
- match kwarg {
1874
- CallKwarg::Named(kw) => {
1875
- let key_const = self.code.add_const(Value::InternString(kw.key.name_id));
1876
- self.code.emit_u16(Opcode::LoadConst, key_const);
1877
- self.compile_expr(&kw.value)?;
1878
- self.code.emit_u16(Opcode::BuildDict, 1);
1879
- self.code.emit_u16(Opcode::DictMerge, func_name_id);
1880
- }
1881
- CallKwarg::Unpack(e) => {
1882
- self.compile_expr(e)?;
1883
- self.code.emit_u16(Opcode::DictMerge, func_name_id);
1884
- }
1885
- }
1886
- }
1887
- }
1888
-
1889
- // 3. Emit CallAttrExtended
1890
- self.code.set_location(call_pos, None);
1891
- let flags = u8::from(has_kwargs);
1892
- self.code.emit_u16_u8(Opcode::CallAttrExtended, func_name_id, flags);
1893
- }
1894
- }
1895
- Ok(())
1896
- }
1897
-
1898
- /// Compiles a method call with `*args` and/or `**kwargs` unpacking.
1899
- ///
1900
- /// The receiver object should already be on the stack. This builds the args tuple
1901
- /// and optional kwargs dict, then emits `CallAttrExtended`.
1902
- fn compile_method_call_with_unpacking(
1903
- &mut self,
1904
- name_id: StringId,
1905
- args: Option<&Vec<ExprLoc>>,
1906
- var_args: Option<&ExprLoc>,
1907
- kwargs: Option<&Vec<Kwarg>>,
1908
- var_kwargs: Option<&ExprLoc>,
1909
- call_pos: CodeRange,
1910
- ) -> Result<(), CompileError> {
1911
- // 1. Build args tuple
1912
- // Push regular positional args and build list
1913
- let pos_count = args.map_or(0, Vec::len);
1914
- if let Some(args) = args {
1915
- for arg in args {
1916
- self.compile_expr(arg)?;
1917
- }
1918
- }
1919
- self.code.emit_u16(
1920
- Opcode::BuildList,
1921
- u16::try_from(pos_count).expect("positional arg count exceeds u16"),
1922
- );
1923
-
1924
- // Extend with *args if present
1925
- if let Some(var_args_expr) = var_args {
1926
- self.compile_expr(var_args_expr)?;
1927
- self.code.emit(Opcode::ListExtend);
1928
- }
1929
-
1930
- // Convert list to tuple
1931
- self.code.emit(Opcode::ListToTuple);
1932
-
1933
- // 2. Build kwargs dict (if we have kwargs or var_kwargs)
1934
- let has_kwargs = kwargs.is_some() || var_kwargs.is_some();
1935
- if has_kwargs {
1936
- // Build dict from regular kwargs
1937
- let kw_count = kwargs.map_or(0, Vec::len);
1938
- if let Some(kwargs) = kwargs {
1939
- for kwarg in kwargs {
1940
- // Push key as interned string constant
1941
- let key_const = self.code.add_const(Value::InternString(kwarg.key.name_id));
1942
- self.code.emit_u16(Opcode::LoadConst, key_const);
1943
- // Push value
1944
- self.compile_expr(&kwarg.value)?;
1945
- }
1946
- }
1947
- self.code.emit_u16(
1948
- Opcode::BuildDict,
1949
- u16::try_from(kw_count).expect("keyword count exceeds u16"),
1950
- );
1951
-
1952
- // Merge **kwargs if present
1953
- if let Some(var_kwargs_expr) = var_kwargs {
1954
- self.compile_expr(var_kwargs_expr)?;
1955
- // Use the method name for error messages
1956
- self.code.emit_u16(
1957
- Opcode::DictMerge,
1958
- u16::try_from(name_id.index()).expect("name index exceeds u16"),
1959
- );
1960
- }
1961
- }
1962
-
1963
- // 3. Call the method with CallAttrExtended
1964
- self.code.set_location(call_pos, None);
1965
- let name_idx = u16::try_from(name_id.index()).expect("name index exceeds u16");
1966
- let flags = u8::from(has_kwargs);
1967
- self.code.emit_u16_u8(Opcode::CallAttrExtended, name_idx, flags);
1968
- Ok(())
1969
- }
1970
-
1971
- /// Shared body for PEP 448 generalized calls with multiple `*args` and/or `**kwargs`.
1972
- ///
1973
- /// Assumes the callable is already on the stack (pushed by the caller).
1974
- /// Emits:
1975
- /// 1. `BuildList(0)` + per-item `ListAppend`/`ListExtend` + `ListToTuple` for args.
1976
- /// 2. `BuildDict(0)` + per-item `BuildDict(1)+DictMerge`/`DictMerge` for kwargs (if any).
1977
- /// 3. `CallFunctionExtended(flags)`.
1978
- ///
1979
- /// `func_name_id` is used in `DictMerge` error messages; pass `0xFFFF` when unknown.
1980
- ///
1981
- /// Stack transition (callable already on stack):
1982
- /// `[callable]` → `[callable, args_tuple]` → `[callable, args_tuple, kwargs_dict?]`
1983
- /// → `[result]`
1984
- fn compile_generalized_call_body(
1985
- &mut self,
1986
- args: &[CallArg],
1987
- kwargs: &[CallKwarg],
1988
- func_name_id: u16,
1989
- call_pos: CodeRange,
1990
- ) -> Result<(), CompileError> {
1991
- // 1. Build args tuple
1992
- self.code.emit_u16(Opcode::BuildList, 0);
1993
- for arg in args {
1994
- match arg {
1995
- CallArg::Value(e) => {
1996
- self.compile_expr(e)?;
1997
- self.code.emit_u8(Opcode::ListAppend, 0);
1998
- }
1999
- CallArg::Unpack(e) => {
2000
- self.compile_expr(e)?;
2001
- self.code.emit(Opcode::ListExtend);
2002
- }
2003
- }
2004
- }
2005
- self.code.emit(Opcode::ListToTuple);
2006
-
2007
- // 2. Build kwargs dict (if any)
2008
- let has_kwargs = !kwargs.is_empty();
2009
- if has_kwargs {
2010
- // Start with an empty dict, then merge each kwarg one at a time via DictMerge
2011
- // so that duplicates (including Named+Unpack ordering) raise TypeError correctly.
2012
- self.code.emit_u16(Opcode::BuildDict, 0);
2013
- for kwarg in kwargs {
2014
- match kwarg {
2015
- CallKwarg::Named(kw) => {
2016
- // Wrap key+value in a single-item dict, then merge into kwargs dict.
2017
- let key_const = self.code.add_const(Value::InternString(kw.key.name_id));
2018
- self.code.emit_u16(Opcode::LoadConst, key_const);
2019
- self.compile_expr(&kw.value)?;
2020
- self.code.emit_u16(Opcode::BuildDict, 1);
2021
- self.code.emit_u16(Opcode::DictMerge, func_name_id);
2022
- }
2023
- CallKwarg::Unpack(e) => {
2024
- self.compile_expr(e)?;
2025
- self.code.emit_u16(Opcode::DictMerge, func_name_id);
2026
- }
2027
- }
2028
- }
2029
- }
2030
-
2031
- // 3. Emit the extended call
2032
- self.code.set_location(call_pos, None);
2033
- let flags = u8::from(has_kwargs);
2034
- self.code.emit_u8(Opcode::CallFunctionExtended, flags);
2035
- Ok(())
2036
- }
2037
-
2038
- /// Compiles a for loop.
2039
- fn compile_for(
2040
- &mut self,
2041
- target: &UnpackTarget,
2042
- iter: &ExprLoc,
2043
- body: &[PreparedNode],
2044
- or_else: &[PreparedNode],
2045
- ) -> Result<(), CompileError> {
2046
- // Record stack depth at loop start (before iterator is pushed)
2047
- // This is the depth we return to when the loop finishes (iterator popped)
2048
- let loop_exit_depth = self.code.stack_depth();
2049
-
2050
- // Compile iterator expression
2051
- self.compile_expr(iter)?;
2052
- // Convert to iterator
2053
- self.code.emit(Opcode::GetIter);
2054
-
2055
- // Loop start
2056
- let loop_start = self.code.current_offset();
2057
-
2058
- // Push loop info for break/continue
2059
- self.loop_stack.push(LoopInfo {
2060
- start: loop_start,
2061
- break_jumps: Vec::new(),
2062
- has_iterator_on_stack: true,
2063
- });
2064
-
2065
- // ForIter: advance iterator or jump to end
2066
- let end_jump = self.code.emit_jump(Opcode::ForIter);
2067
-
2068
- // Store current value to target (handles both single identifiers and tuple unpacking)
2069
- self.compile_unpack_target(target);
2070
-
2071
- // Compile body
2072
- self.compile_block(body)?;
2073
-
2074
- // Jump back to loop start
2075
- self.code.emit_jump_to(Opcode::Jump, loop_start);
2076
-
2077
- // End of loop - ForIter jumps here when iterator is exhausted
2078
- self.code.patch_jump(end_jump);
2079
- // Iterator is popped when loop ends normally, so restore depth to before loop
2080
- self.code.set_stack_depth(loop_exit_depth);
2081
-
2082
- // Pop loop info before compiling else block
2083
- let loop_info = self.loop_stack.pop().expect("loop stack underflow");
2084
-
2085
- // Compile else block (runs if loop completed without break)
2086
- if !or_else.is_empty() {
2087
- self.compile_block(or_else)?;
2088
- }
2089
-
2090
- // Patch break jumps to here - AFTER the else block so break skips else
2091
- for break_jump in loop_info.break_jumps {
2092
- self.code.patch_jump(break_jump);
2093
- }
2094
-
2095
- Ok(())
2096
- }
2097
-
2098
- /// Compiles a while loop.
2099
- ///
2100
- /// The bytecode structure:
2101
- /// ```text
2102
- /// loop_start:
2103
- /// [evaluate condition]
2104
- /// JumpIfFalse -> end_jump
2105
- /// [body]
2106
- /// Jump -> loop_start
2107
- /// end_jump:
2108
- /// [else block]
2109
- /// [break patches here]
2110
- /// ```
2111
- ///
2112
- /// Key differences from `for` loops:
2113
- /// - No `GetIter` (no iterator)
2114
- /// - No `ForIter` (use `JumpIfFalse` instead)
2115
- /// - `continue` jumps to condition evaluation
2116
- /// - `break` doesn't need to pop iterator (nothing extra on stack)
2117
- fn compile_while(
2118
- &mut self,
2119
- test: &ExprLoc,
2120
- body: &[PreparedNode],
2121
- or_else: &[PreparedNode],
2122
- ) -> Result<(), CompileError> {
2123
- let loop_start = self.code.current_offset();
2124
-
2125
- self.loop_stack.push(LoopInfo {
2126
- start: loop_start,
2127
- break_jumps: Vec::new(),
2128
- has_iterator_on_stack: false,
2129
- });
2130
-
2131
- self.compile_expr(test)?;
2132
- let end_jump = self.code.emit_jump(Opcode::JumpIfFalse);
2133
-
2134
- self.compile_block(body)?;
2135
- self.code.emit_jump_to(Opcode::Jump, loop_start);
2136
-
2137
- self.code.patch_jump(end_jump);
2138
- let loop_info = self.loop_stack.pop().expect("loop stack underflow");
2139
-
2140
- if !or_else.is_empty() {
2141
- self.compile_block(or_else)?;
2142
- }
2143
-
2144
- for break_jump in loop_info.break_jumps {
2145
- self.code.patch_jump(break_jump);
2146
- }
2147
-
2148
- Ok(())
2149
- }
2150
-
2151
- /// Compiles a break statement.
2152
- ///
2153
- /// Break exits the innermost loop and skips its else block. If inside a
2154
- /// try-finally, the finally block must run first.
2155
- ///
2156
- /// The bytecode without finally:
2157
- /// 1. Clean up exception state if inside except handler
2158
- /// 2. Pop the iterator if in a `for` loop (still on stack during loop body)
2159
- /// 3. Jump to after the else block
2160
- ///
2161
- /// With finally:
2162
- /// 1. Clean up exception state if inside except handler
2163
- /// 2. Pop the iterator if in a `for` loop
2164
- /// 3. Jump to "finally with break" path (patched when try compilation completes)
2165
- /// 4. That path runs finally, then jumps to after the else block
2166
- fn compile_break(&mut self, position: CodeRange) -> Result<(), CompileError> {
2167
- if self.loop_stack.is_empty() {
2168
- return Err(CompileError::new("'break' outside loop", position));
2169
- }
2170
-
2171
- let target_loop_depth = self.loop_stack.len() - 1;
2172
-
2173
- // If inside except handlers, clean up ALL exception states
2174
- // Each nested except handler has pushed an exception onto the stack,
2175
- // so we need to clear/pop each one when breaking out
2176
- for _ in 0..self.except_handler_depth {
2177
- self.code.emit(Opcode::ClearException);
2178
- self.code.emit(Opcode::Pop); // Pop the exception value
2179
- }
2180
-
2181
- // Pop the iterator only for `for` loops (has iterator on stack)
2182
- // `while` loops don't have an iterator to pop
2183
- if self.loop_stack[target_loop_depth].has_iterator_on_stack {
2184
- self.code.emit(Opcode::Pop);
2185
- }
2186
-
2187
- // Check if we need to go through any finally blocks
2188
- // We need to run finally if break crosses the try boundary, i.e., if
2189
- // we're breaking from a loop that existed before the try started.
2190
- if let Some(finally_target) = self.finally_targets.last_mut()
2191
- && target_loop_depth < finally_target.loop_depth_at_entry
2192
- {
2193
- // Breaking from a loop that's outside (or at the start of) this try-finally,
2194
- // so finally must run before the break
2195
- let jump = self.code.emit_jump(Opcode::Jump);
2196
- finally_target.break_jumps.push(BreakContinueThruFinally {
2197
- jump,
2198
- target_loop_depth,
2199
- });
2200
- // Set stack depth for unreachable cleanup code (see comment below)
2201
- if self.except_handler_depth > 0 {
2202
- self.code
2203
- .set_stack_depth(u16::try_from(self.except_handler_depth).unwrap_or(u16::MAX));
2204
- }
2205
- return Ok(());
2206
- }
2207
-
2208
- // No finally to go through, jump directly to loop end
2209
- let jump = self.code.emit_jump(Opcode::Jump);
2210
- self.loop_stack[target_loop_depth].break_jumps.push(jump);
2211
-
2212
- // The code following this break is unreachable at runtime, but the compiler
2213
- // will still emit cleanup code for each enclosing except handler (ClearException + Pop).
2214
- // Set stack depth so those unreachable pops don't cause negative stack tracking.
2215
- if self.except_handler_depth > 0 {
2216
- self.code
2217
- .set_stack_depth(u16::try_from(self.except_handler_depth).unwrap_or(u16::MAX));
2218
- }
2219
-
2220
- Ok(())
2221
- }
2222
-
2223
- /// Compiles a continue statement.
2224
- ///
2225
- /// Continue jumps back to the loop start (the ForIter instruction) which
2226
- /// advances the iterator and either enters the next iteration or exits the loop.
2227
- /// If inside a try-finally, the finally block must run first.
2228
- fn compile_continue(&mut self, position: CodeRange) -> Result<(), CompileError> {
2229
- if self.loop_stack.is_empty() {
2230
- return Err(CompileError::new("'continue' not properly in loop", position));
2231
- }
2232
-
2233
- let target_loop_depth = self.loop_stack.len() - 1;
2234
-
2235
- // If inside except handlers, clean up ALL exception states
2236
- // Each nested except handler has pushed an exception onto the stack,
2237
- // so we need to clear/pop each one when continuing
2238
- for _ in 0..self.except_handler_depth {
2239
- self.code.emit(Opcode::ClearException);
2240
- self.code.emit(Opcode::Pop); // Pop the exception value
2241
- }
2242
-
2243
- // Check if we need to go through any finally blocks
2244
- // We need to run finally if continue crosses the try boundary
2245
- if let Some(finally_target) = self.finally_targets.last_mut()
2246
- && target_loop_depth < finally_target.loop_depth_at_entry
2247
- {
2248
- // Continuing a loop that's outside (or at the start of) this try-finally,
2249
- // so finally must run before the continue
2250
- let jump = self.code.emit_jump(Opcode::Jump);
2251
- finally_target.continue_jumps.push(BreakContinueThruFinally {
2252
- jump,
2253
- target_loop_depth,
2254
- });
2255
- // Set stack depth for unreachable cleanup code (see comment below)
2256
- if self.except_handler_depth > 0 {
2257
- self.code
2258
- .set_stack_depth(u16::try_from(self.except_handler_depth).unwrap_or(u16::MAX));
2259
- }
2260
- return Ok(());
2261
- }
2262
-
2263
- // No finally to go through, jump directly to loop start
2264
- let loop_start = self.loop_stack[target_loop_depth].start;
2265
- self.code.emit_jump_to(Opcode::Jump, loop_start);
2266
-
2267
- // The code following this continue is unreachable at runtime, but the compiler
2268
- // will still emit cleanup code for each enclosing except handler (ClearException + Pop).
2269
- // Set stack depth so those unreachable pops don't cause negative stack tracking.
2270
- if self.except_handler_depth > 0 {
2271
- self.code
2272
- .set_stack_depth(u16::try_from(self.except_handler_depth).unwrap_or(u16::MAX));
2273
- }
2274
-
2275
- Ok(())
2276
- }
2277
-
2278
- /// Compiles break or continue after a finally block has run.
2279
- ///
2280
- /// Called from `compile_try` after the finally block code. Each control flow
2281
- /// statement may target a different loop, so we check if there's another finally
2282
- /// to go through or if we can jump directly to the loop's target.
2283
- ///
2284
- /// Note: All items in the list jumped to the same finally block, so they all
2285
- /// have the same starting point. After finally runs, we need to route each
2286
- /// to its target loop, potentially through more finally blocks.
2287
- fn compile_control_flow_after_finally(&mut self, items: &[BreakContinueThruFinally], is_break: bool) {
2288
- // All items went through the same finally, now we need to dispatch to
2289
- // potentially different loops. For simplicity, we assume all items in
2290
- // a single finally target the same loop (the innermost one at the time).
2291
- // This is always true since break/continue only targets the innermost loop.
2292
- let Some(first) = items.first() else {
2293
- return;
2294
- };
2295
- let target_loop_depth = first.target_loop_depth;
2296
-
2297
- // Check if there's another finally between us and the target loop
2298
- if let Some(finally_target) = self.finally_targets.last_mut()
2299
- && target_loop_depth < finally_target.loop_depth_at_entry
2300
- {
2301
- // Need to go through another finally
2302
- let jump = self.code.emit_jump(Opcode::Jump);
2303
- let jump_info = BreakContinueThruFinally {
2304
- jump,
2305
- target_loop_depth,
2306
- };
2307
- if is_break {
2308
- finally_target.break_jumps.push(jump_info);
2309
- } else {
2310
- // else continue
2311
- finally_target.continue_jumps.push(jump_info);
2312
- }
2313
- return;
2314
- }
2315
-
2316
- // No more finally blocks, jump directly to the loop target
2317
- if is_break {
2318
- let jump = self.code.emit_jump(Opcode::Jump);
2319
- self.loop_stack[target_loop_depth].break_jumps.push(jump);
2320
- } else {
2321
- // else continue
2322
- let loop_start = self.loop_stack[target_loop_depth].start;
2323
- self.code.emit_jump_to(Opcode::Jump, loop_start);
2324
- }
2325
- }
2326
-
2327
- // ========================================================================
2328
- // Comprehension Compilation
2329
- // ========================================================================
2330
-
2331
- /// Compiles a list comprehension: `[elt for target in iter if cond...]`
2332
- ///
2333
- /// Bytecode structure:
2334
- /// ```text
2335
- /// BUILD_LIST 0 ; empty result
2336
- /// <compile first iter>
2337
- /// GET_ITER
2338
- /// loop_start:
2339
- /// FOR_ITER end_loop
2340
- /// STORE_LOCAL target
2341
- /// <compile filters - jump back to loop_start if any fails>
2342
- /// [nested generators...]
2343
- /// <compile elt>
2344
- /// LIST_APPEND depth
2345
- /// JUMP loop_start
2346
- /// end_loop:
2347
- /// ; result list on stack
2348
- /// ```
2349
- fn compile_list_comp(&mut self, elt: &ExprLoc, generators: &[Comprehension]) -> Result<(), CompileError> {
2350
- // Build empty list
2351
- self.code.emit_u16(Opcode::BuildList, 0);
2352
-
2353
- // Compile the nested generators, which will eventually append to the list
2354
- let depth = u8::try_from(generators.len()).expect("too many generators in list comprehension");
2355
- self.compile_comprehension_generators(generators, 0, |compiler| {
2356
- compiler.compile_expr(elt)?;
2357
- compiler.code.emit_u8(Opcode::ListAppend, depth);
2358
- Ok(())
2359
- })?;
2360
-
2361
- Ok(())
2362
- }
2363
-
2364
- /// Compiles a set comprehension: `{elt for target in iter if cond...}`
2365
- fn compile_set_comp(&mut self, elt: &ExprLoc, generators: &[Comprehension]) -> Result<(), CompileError> {
2366
- // Build empty set
2367
- self.code.emit_u16(Opcode::BuildSet, 0);
2368
-
2369
- // Compile the nested generators, which will eventually add to the set
2370
- let depth = u8::try_from(generators.len()).expect("too many generators in set comprehension");
2371
- self.compile_comprehension_generators(generators, 0, |compiler| {
2372
- compiler.compile_expr(elt)?;
2373
- compiler.code.emit_u8(Opcode::SetAdd, depth);
2374
- Ok(())
2375
- })?;
2376
-
2377
- Ok(())
2378
- }
2379
-
2380
- /// Compiles a dict comprehension: `{key: value for target in iter if cond...}`
2381
- fn compile_dict_comp(
2382
- &mut self,
2383
- key: &ExprLoc,
2384
- value: &ExprLoc,
2385
- generators: &[Comprehension],
2386
- ) -> Result<(), CompileError> {
2387
- // Build empty dict
2388
- self.code.emit_u16(Opcode::BuildDict, 0);
2389
-
2390
- // Compile the nested generators, which will eventually set items in the dict
2391
- let depth = u8::try_from(generators.len()).expect("too many generators in dict comprehension");
2392
- self.compile_comprehension_generators(generators, 0, |compiler| {
2393
- compiler.compile_expr(key)?;
2394
- compiler.compile_expr(value)?;
2395
- compiler.code.emit_u8(Opcode::DictSetItem, depth);
2396
- Ok(())
2397
- })?;
2398
-
2399
- Ok(())
2400
- }
2401
-
2402
- /// Recursively compiles comprehension generators (the for/if clauses).
2403
- ///
2404
- /// For each generator:
2405
- /// 1. Compile the iterator expression and get iterator
2406
- /// 2. Start loop: FOR_ITER to get next value or exit
2407
- /// 3. Store to target variable
2408
- /// 4. Compile filter conditions (jump back to loop start if any fails)
2409
- /// 5. Either recurse for inner generator, or call the body callback
2410
- /// 6. Jump back to loop start
2411
- ///
2412
- /// The `body_fn` callback is called at the innermost level to emit the element/key-value code.
2413
- fn compile_comprehension_generators(
2414
- &mut self,
2415
- generators: &[Comprehension],
2416
- index: usize,
2417
- body_fn: impl FnOnce(&mut Self) -> Result<(), CompileError>,
2418
- ) -> Result<(), CompileError> {
2419
- let generator = &generators[index];
2420
-
2421
- // Record stack depth before iterator expression
2422
- // This is the depth we return to when the loop finishes (iterator popped)
2423
- let loop_exit_depth = self.code.stack_depth();
2424
-
2425
- // Compile iterator expression
2426
- self.compile_expr(&generator.iter)?;
2427
- self.code.emit(Opcode::GetIter);
2428
-
2429
- // Loop start
2430
- let loop_start = self.code.current_offset();
2431
-
2432
- // FOR_ITER: advance iterator or jump to end
2433
- let end_jump = self.code.emit_jump(Opcode::ForIter);
2434
-
2435
- // Store current value to target (single variable or tuple unpacking)
2436
- self.compile_unpack_target(&generator.target);
2437
-
2438
- // Compile filter conditions - jump back to loop start if any fails
2439
- for cond in &generator.ifs {
2440
- self.compile_expr(cond)?;
2441
- // If condition is false, skip to next iteration
2442
- self.code.emit_jump_to(Opcode::JumpIfFalse, loop_start);
2443
- }
2444
-
2445
- // Either recurse for inner generator, or emit body
2446
- if index + 1 < generators.len() {
2447
- // Recurse for inner generator
2448
- self.compile_comprehension_generators(generators, index + 1, body_fn)?;
2449
- } else {
2450
- // Innermost level - emit body (the element/key-value expression and append/add/set)
2451
- body_fn(self)?;
2452
- }
2453
-
2454
- // Jump back to loop start
2455
- self.code.emit_jump_to(Opcode::Jump, loop_start);
2456
-
2457
- // End of loop
2458
- self.code.patch_jump(end_jump);
2459
- // Iterator is popped when loop ends normally, so restore depth to before loop
2460
- self.code.set_stack_depth(loop_exit_depth);
2461
-
2462
- Ok(())
2463
- }
2464
-
2465
- /// Compiles storage of an unpack target - either a single identifier, nested tuple, or starred.
2466
- ///
2467
- /// For single identifiers: emits a simple store.
2468
- /// For nested tuples: emits `UnpackSequence` (or `UnpackEx` with starred) and recursively
2469
- /// handles each sub-target.
2470
- fn compile_unpack_target(&mut self, target: &UnpackTarget) {
2471
- match target {
2472
- UnpackTarget::Name(ident) => {
2473
- // Single identifier - just store directly
2474
- self.compile_store(ident);
2475
- }
2476
- UnpackTarget::Starred(ident) => {
2477
- // Starred target by itself (shouldn't happen at top level normally)
2478
- // Just store as if it were a name
2479
- self.compile_store(ident);
2480
- }
2481
- UnpackTarget::Tuple { targets, position } => {
2482
- // Check if there's a starred target
2483
- let star_idx = targets.iter().position(|t| matches!(t, UnpackTarget::Starred(_)));
2484
-
2485
- self.code.set_location(*position, None);
2486
-
2487
- if let Some(star_idx) = star_idx {
2488
- // Has starred target - use UnpackEx
2489
- let before = u8::try_from(star_idx).expect("too many targets before star");
2490
- let after = u8::try_from(targets.len() - star_idx - 1).expect("too many targets after star");
2491
- self.code.emit_u8_u8(Opcode::UnpackEx, before, after);
2492
- } else {
2493
- // No starred target - use UnpackSequence
2494
- let count = u8::try_from(targets.len()).expect("too many targets in nested unpack");
2495
- self.code.emit_u8(Opcode::UnpackSequence, count);
2496
- }
2497
-
2498
- // After UnpackSequence/UnpackEx, values are on stack with first item on top
2499
- // Store them in order, recursively handling further nesting
2500
- for target in targets {
2501
- self.compile_unpack_target(target);
2502
- }
2503
- }
2504
- }
2505
- }
2506
-
2507
- // ========================================================================
2508
- // Statement Helpers
2509
- // ========================================================================
2510
-
2511
- /// Compiles an assert statement.
2512
- fn compile_assert(&mut self, test: &ExprLoc, msg: Option<&ExprLoc>) -> Result<(), CompileError> {
2513
- // Compile test
2514
- self.compile_expr(test)?;
2515
- // Jump over raise if truthy
2516
- let skip_jump = self.code.emit_jump(Opcode::JumpIfTrue);
2517
-
2518
- // Raise AssertionError
2519
- let exc_idx = self
2520
- .code
2521
- .add_const(Value::Builtin(Builtins::ExcType(ExcType::AssertionError)));
2522
- self.code.emit_u16(Opcode::LoadConst, exc_idx);
2523
-
2524
- if let Some(msg_expr) = msg {
2525
- // Call AssertionError(msg)
2526
- self.compile_expr(msg_expr)?;
2527
- self.code.emit_u8(Opcode::CallFunction, 1);
2528
- } else {
2529
- // Call AssertionError()
2530
- self.code.emit_u8(Opcode::CallFunction, 0);
2531
- }
2532
-
2533
- self.code.emit(Opcode::Raise);
2534
- self.code.patch_jump(skip_jump);
2535
- Ok(())
2536
- }
2537
-
2538
- /// Compiles f-string parts, returning the number of string parts to concatenate.
2539
- ///
2540
- /// Each part is compiled to leave a string value on the stack:
2541
- /// - `Literal(StringId)`: Push the interned string directly
2542
- /// - `Interpolation`: Compile expr, emit FormatValue to convert to string
2543
- fn compile_fstring_parts(&mut self, parts: &[FStringPart]) -> Result<u16, CompileError> {
2544
- let mut count = 0u16;
2545
-
2546
- for part in parts {
2547
- match part {
2548
- FStringPart::Literal(string_id) => {
2549
- // Push the interned string as a constant
2550
- let const_idx = self.code.add_const(Value::InternString(*string_id));
2551
- self.code.emit_u16(Opcode::LoadConst, const_idx);
2552
- count += 1;
2553
- }
2554
- FStringPart::Interpolation {
2555
- expr,
2556
- conversion,
2557
- format_spec,
2558
- debug_prefix,
2559
- } => {
2560
- // If debug prefix present, push it first
2561
- if let Some(prefix_id) = debug_prefix {
2562
- let const_idx = self.code.add_const(Value::InternString(*prefix_id));
2563
- self.code.emit_u16(Opcode::LoadConst, const_idx);
2564
- count += 1;
2565
- }
2566
-
2567
- // Compile the expression
2568
- self.compile_expr(expr)?;
2569
-
2570
- // For debug expressions without explicit conversion, Python uses repr by default
2571
- let effective_conversion = if debug_prefix.is_some() && matches!(conversion, ConversionFlag::None) {
2572
- ConversionFlag::Repr
2573
- } else {
2574
- *conversion
2575
- };
2576
-
2577
- // Emit FormatValue with appropriate flags
2578
- let flags = self.compile_format_value(effective_conversion, format_spec.as_ref())?;
2579
- self.code.emit_u8(Opcode::FormatValue, flags);
2580
- count += 1;
2581
- }
2582
- }
2583
- }
2584
-
2585
- Ok(count)
2586
- }
2587
-
2588
- /// Compiles format value flags and optionally pushes format spec to stack.
2589
- ///
2590
- /// Returns the flags byte encoding conversion and format spec presence.
2591
- /// If a format spec is present, it's pushed to the stack before the value.
2592
- fn compile_format_value(
2593
- &mut self,
2594
- conversion: ConversionFlag,
2595
- format_spec: Option<&FormatSpec>,
2596
- ) -> Result<u8, CompileError> {
2597
- // Conversion flag: bits 0-1
2598
- let conv_bits = match conversion {
2599
- ConversionFlag::None => 0,
2600
- ConversionFlag::Str => 1,
2601
- ConversionFlag::Repr => 2,
2602
- ConversionFlag::Ascii => 3,
2603
- };
2604
-
2605
- match format_spec {
2606
- None => Ok(conv_bits),
2607
- Some(FormatSpec::Static(parsed)) => {
2608
- // Static format spec - push a marker constant with the parsed spec info
2609
- // We store this as a special format spec value in the constant pool
2610
- // The VM will recognize this and use the pre-parsed spec
2611
- let const_idx = self.add_format_spec_const(parsed);
2612
- self.code.emit_u16(Opcode::LoadConst, const_idx);
2613
- Ok(conv_bits | 0x04) // has format spec on stack
2614
- }
2615
- Some(FormatSpec::Dynamic(dynamic_parts)) => {
2616
- // Compile dynamic format spec parts to build a format spec string
2617
- // Then parse it at runtime
2618
- let part_count = self.compile_fstring_parts(dynamic_parts)?;
2619
- if part_count > 1 {
2620
- self.code.emit_u16(Opcode::BuildFString, part_count);
2621
- }
2622
- // Format spec string is now on stack
2623
- Ok(conv_bits | 0x04) // has format spec on stack
2624
- }
2625
- }
2626
- }
2627
-
2628
- /// Adds a format spec to the constant pool as an encoded integer.
2629
- ///
2630
- /// Uses the encoding from `fstring::encode_format_spec` and stores it as
2631
- /// a negative integer to distinguish from regular ints.
2632
- fn add_format_spec_const(&mut self, spec: &ParsedFormatSpec) -> u16 {
2633
- let encoded = encode_format_spec(spec);
2634
- // Use negative to distinguish from regular ints (format spec marker)
2635
- // We negate and subtract 1 to ensure it's negative and recoverable
2636
- let encoded_i64 = i64::try_from(encoded).expect("format spec encoding exceeds i64::MAX");
2637
- let marker = -(encoded_i64 + 1);
2638
- self.code.add_const(Value::Int(marker))
2639
- }
2640
-
2641
- // ========================================================================
2642
- // Exception Handling Compilation
2643
- // ========================================================================
2644
-
2645
- /// Compiles a return statement, handling finally blocks properly.
2646
- ///
2647
- /// If we're inside a try-finally block, the return value is kept on the stack
2648
- /// and we jump to a "finally with return" section that runs finally then returns.
2649
- /// Otherwise, we emit a direct `ReturnValue`.
2650
- fn compile_return(&mut self) {
2651
- if let Some(finally_target) = self.finally_targets.last_mut() {
2652
- // Inside a try-finally: jump to finally, then return
2653
- // Return value is already on stack
2654
- let jump = self.code.emit_jump(Opcode::Jump);
2655
- finally_target.return_jumps.push(jump);
2656
- } else {
2657
- // Normal return
2658
- self.code.emit(Opcode::ReturnValue);
2659
- }
2660
- }
2661
-
2662
- /// Compiles a try/except/else/finally block.
2663
- ///
2664
- /// The bytecode structure is:
2665
- /// ```text
2666
- /// <try_body> # protected range
2667
- /// JUMP to_else_or_finally # skip handlers if no exception
2668
- /// handler_dispatch: # exception pushed by VM
2669
- /// # for each handler:
2670
- /// <check exception type>
2671
- /// <handler body>
2672
- /// CLEAR_EXCEPTION
2673
- /// JUMP to_finally
2674
- /// reraise:
2675
- /// RERAISE # no handler matched
2676
- /// else_block:
2677
- /// <else_body>
2678
- /// finally_block:
2679
- /// <finally_body>
2680
- /// end:
2681
- /// ```
2682
- ///
2683
- /// For finally blocks, exceptions that propagate through the handler dispatch
2684
- /// (including RERAISE when no handler matches) are caught by a second exception
2685
- /// entry that ensures finally runs before propagation.
2686
- ///
2687
- /// Returns inside try/except/else jump to a "finally with return" path that
2688
- /// runs the finally code then returns the value.
2689
- ///
2690
- /// **Note:** The finally block code is emitted multiple times (once for each
2691
- /// control flow path: normal, exception, return, break, continue). This is the
2692
- /// same approach CPython uses - each path has different stack state at entry
2693
- /// (e.g., return has a value on stack, break has popped the iterator), so we
2694
- /// can't easily share a single copy. The duplication is intentional.
2695
- fn compile_try(&mut self, try_block: &Try<PreparedNode>) -> Result<(), CompileError> {
2696
- let has_finally = !try_block.finally.is_empty();
2697
- let has_handlers = !try_block.handlers.is_empty();
2698
- let has_else = !try_block.or_else.is_empty();
2699
-
2700
- // Record stack depth at try entry (for unwinding on exception)
2701
- let stack_depth = self.code.stack_depth();
2702
-
2703
- // If there's a finally block, track returns/break/continue inside try/handlers/else
2704
- if has_finally {
2705
- self.finally_targets.push(FinallyTarget {
2706
- return_jumps: Vec::new(),
2707
- break_jumps: Vec::new(),
2708
- continue_jumps: Vec::new(),
2709
- loop_depth_at_entry: self.loop_stack.len(),
2710
- });
2711
- }
2712
-
2713
- // === Compile try body ===
2714
- let try_start = self.code.current_offset();
2715
- self.compile_block(&try_block.body)?;
2716
- let try_end = self.code.current_offset();
2717
-
2718
- // Jump to else/finally if no exception (skip handlers)
2719
- let after_try_jump = self.code.emit_jump(Opcode::Jump);
2720
-
2721
- // === Handler dispatch starts here ===
2722
- let handler_start = self.code.current_offset();
2723
-
2724
- // VM pushes exception onto stack when entering handler.
2725
- // Adjust compiler's stack depth tracking to reflect this.
2726
- self.code.adjust_stack_depth(1);
2727
-
2728
- // Track jumps that go to finally (for patching later)
2729
- let mut finally_jumps: Vec<JumpLabel> = Vec::new();
2730
-
2731
- if has_handlers {
2732
- // Compile exception handlers
2733
- // handler_entry_depth = stack_depth + 1 (exception on stack)
2734
- let handler_entry_depth = stack_depth + 1;
2735
- self.compile_exception_handlers(&try_block.handlers, &mut finally_jumps, handler_entry_depth)?;
2736
- } else {
2737
- // No handlers - just reraise (this only happens with try-finally)
2738
- self.code.emit(Opcode::Reraise);
2739
- }
2740
-
2741
- // After handler dispatch, each handler path either:
2742
- // 1. Matched and popped the exception (via Pop), then jumped to finally
2743
- // 2. Didn't match and reraised (for last handler)
2744
- // The handlers' Pop instructions already account for the exception,
2745
- // so no additional stack depth adjustment is needed here.
2746
-
2747
- // Mark end of handler dispatch (for finally exception entry)
2748
- let handler_dispatch_end = self.code.current_offset();
2749
-
2750
- // === Finally cleanup handler (for exceptions during handler dispatch) ===
2751
- // This catches exceptions from RERAISE (and any other exceptions in handlers)
2752
- // and ensures finally runs before the exception propagates.
2753
- let finally_cleanup_start = if has_finally {
2754
- let cleanup_start = self.code.current_offset();
2755
- // Exception value is on stack (pushed by VM), so stack = stack_depth + 1
2756
- self.code.set_stack_depth(stack_depth + 1);
2757
- // We need to pop it, run finally, then reraise
2758
- // But we can't easily save the exception, so we use a different approach:
2759
- // The exception is already on the exception_stack from handle_exception,
2760
- // so we can just pop from operand stack, run finally, then reraise.
2761
- self.code.emit(Opcode::Pop); // Pop exception from operand stack
2762
- self.compile_block(&try_block.finally)?;
2763
- self.code.emit(Opcode::Reraise); // Re-raise from exception_stack
2764
- Some(cleanup_start)
2765
- } else {
2766
- None
2767
- };
2768
-
2769
- // === Finally with return/break/continue paths ===
2770
- // Pop finally target and get all the jumps that need to go through finally
2771
- let finally_with_return_start = if has_finally {
2772
- let finally_target = self.finally_targets.pop().expect("finally_targets should not be empty");
2773
-
2774
- // === Finally with return path ===
2775
- let return_start = if finally_target.return_jumps.is_empty() {
2776
- None
2777
- } else {
2778
- let start = self.code.current_offset();
2779
- for jump in finally_target.return_jumps {
2780
- self.code.patch_jump(jump);
2781
- }
2782
- // Return value is on stack, stack = stack_depth + 1
2783
- self.code.set_stack_depth(stack_depth + 1);
2784
- self.compile_block(&try_block.finally)?;
2785
- self.compile_return();
2786
- Some(start)
2787
- };
2788
-
2789
- // === Finally with break path ===
2790
- // For each break, run finally then either:
2791
- // - Jump to outer finally's break path (if there's an outer finally between us and the loop)
2792
- // - Jump directly to the loop's break target
2793
- if !finally_target.break_jumps.is_empty() {
2794
- for break_info in &finally_target.break_jumps {
2795
- self.code.patch_jump(break_info.jump);
2796
- }
2797
- // Break already popped the iterator, so stack = stack_depth - 1
2798
- // (the iterator was on stack at try entry, break removed it)
2799
- self.code.set_stack_depth(stack_depth.saturating_sub(1));
2800
- self.compile_block(&try_block.finally)?;
2801
- // After finally, compile the break again (handles nested finally or direct jump)
2802
- self.compile_control_flow_after_finally(&finally_target.break_jumps, true);
2803
- }
2804
-
2805
- // === Finally with continue path ===
2806
- if !finally_target.continue_jumps.is_empty() {
2807
- for continue_info in &finally_target.continue_jumps {
2808
- self.code.patch_jump(continue_info.jump);
2809
- }
2810
- // Continue doesn't pop the iterator, stack = stack_depth
2811
- self.code.set_stack_depth(stack_depth);
2812
- self.compile_block(&try_block.finally)?;
2813
- // After finally, compile the continue again (handles nested finally or direct jump)
2814
- self.compile_control_flow_after_finally(&finally_target.continue_jumps, false);
2815
- }
2816
-
2817
- return_start
2818
- } else {
2819
- None
2820
- };
2821
-
2822
- // === Else block (runs if no exception) ===
2823
- self.code.patch_jump(after_try_jump);
2824
- // Normal path from try body, stack = stack_depth
2825
- self.code.set_stack_depth(stack_depth);
2826
- let else_start = self.code.current_offset();
2827
- if has_else {
2828
- self.compile_block(&try_block.or_else)?;
2829
- }
2830
- let else_end = self.code.current_offset();
2831
-
2832
- // === Normal finally path (no exception pending, no return) ===
2833
- // Patch all jumps from handlers to go here
2834
- for jump in finally_jumps {
2835
- self.code.patch_jump(jump);
2836
- }
2837
-
2838
- if has_finally {
2839
- // Stack = stack_depth (no exception, no return value)
2840
- self.code.set_stack_depth(stack_depth);
2841
- self.compile_block(&try_block.finally)?;
2842
- }
2843
-
2844
- // === Add exception table entries ===
2845
- // Order matters: entries are searched in order, so inner entries must come first.
2846
-
2847
- // Entry 1: Try body -> handler dispatch
2848
- if has_handlers || has_finally {
2849
- self.code.add_exception_entry(ExceptionEntry::new(
2850
- u32::try_from(try_start).expect("bytecode offset exceeds u32"),
2851
- u32::try_from(try_end).expect("bytecode offset exceeds u32") + 3, // +3 to include the JUMP instruction
2852
- u32::try_from(handler_start).expect("bytecode offset exceeds u32"),
2853
- stack_depth,
2854
- ));
2855
- }
2856
-
2857
- // Entry 2: Handler dispatch -> finally cleanup (only if has_finally)
2858
- // This ensures finally runs when RERAISE is executed or any exception occurs in handlers
2859
- if let Some(cleanup_start) = finally_cleanup_start {
2860
- self.code.add_exception_entry(ExceptionEntry::new(
2861
- u32::try_from(handler_start).expect("bytecode offset exceeds u32"),
2862
- u32::try_from(handler_dispatch_end).expect("bytecode offset exceeds u32"),
2863
- u32::try_from(cleanup_start).expect("bytecode offset exceeds u32"),
2864
- stack_depth,
2865
- ));
2866
- }
2867
-
2868
- // Entry 3: Finally with return -> finally cleanup
2869
- // If an exception occurs while running finally (in the return path), catch it
2870
- if let (Some(return_start), Some(cleanup_start)) = (finally_with_return_start, finally_cleanup_start) {
2871
- self.code.add_exception_entry(ExceptionEntry::new(
2872
- u32::try_from(return_start).expect("bytecode offset exceeds u32"),
2873
- u32::try_from(else_start).expect("bytecode offset exceeds u32"), // End at else_start (before else block)
2874
- u32::try_from(cleanup_start).expect("bytecode offset exceeds u32"),
2875
- stack_depth,
2876
- ));
2877
- }
2878
-
2879
- // Entry 4: Else block -> finally cleanup (only if has_finally and has_else)
2880
- // Exceptions in else block should go through finally
2881
- if has_else && let Some(cleanup_start) = finally_cleanup_start {
2882
- self.code.add_exception_entry(ExceptionEntry::new(
2883
- u32::try_from(else_start).expect("bytecode offset exceeds u32"),
2884
- u32::try_from(else_end).expect("bytecode offset exceeds u32"),
2885
- u32::try_from(cleanup_start).expect("bytecode offset exceeds u32"),
2886
- stack_depth,
2887
- ));
2888
- }
2889
-
2890
- Ok(())
2891
- }
2892
-
2893
- /// Compiles the exception handlers for a try block.
2894
- ///
2895
- /// Each handler checks if the exception matches its type, and if so,
2896
- /// executes the handler body. If no handler matches, the exception is re-raised.
2897
- ///
2898
- /// `handler_entry_depth` is the stack depth when entering handler dispatch
2899
- /// (i.e., base stack_depth + 1 for the exception value).
2900
- fn compile_exception_handlers(
2901
- &mut self,
2902
- handlers: &[ExceptHandler<PreparedNode>],
2903
- finally_jumps: &mut Vec<JumpLabel>,
2904
- handler_entry_depth: u16,
2905
- ) -> Result<(), CompileError> {
2906
- // Track jumps from non-matching handlers to next handler
2907
- let mut next_handler_jumps: Vec<JumpLabel> = Vec::new();
2908
-
2909
- for (i, handler) in handlers.iter().enumerate() {
2910
- let is_last = i == handlers.len() - 1;
2911
-
2912
- // Patch jumps from previous handler's non-match to here
2913
- // If jumping from a previous handler's no-match, stack has [exc, exc] (duplicate)
2914
- // We need to pop the duplicate before starting this handler's check
2915
- if !next_handler_jumps.is_empty() {
2916
- for jump in next_handler_jumps.drain(..) {
2917
- self.code.patch_jump(jump);
2918
- }
2919
- // Reset stack depth for jump target: [exc, exc] = handler_entry_depth + 1
2920
- self.code.set_stack_depth(handler_entry_depth + 1);
2921
- // Pop the duplicate from previous handler's check
2922
- self.code.emit(Opcode::Pop);
2923
- }
2924
-
2925
- if let Some(exc_type) = &handler.exc_type {
2926
- // Typed handler: except ExcType: or except ExcType as e:
2927
- // Stack: [exception]
2928
-
2929
- // Duplicate exception for type check
2930
- self.code.emit(Opcode::Dup);
2931
- // Stack: [exception, exception]
2932
-
2933
- // Load the exception type to match against
2934
- self.compile_expr(exc_type)?;
2935
- // Stack: [exception, exception, exc_type]
2936
-
2937
- // Check if exception matches the type
2938
- // This validates exc_type is a valid exception type and performs the match
2939
- // CheckExcMatch pops exc_type, peeks exception, pushes bool
2940
- self.code.emit(Opcode::CheckExcMatch);
2941
- // Stack: [exception, exception, bool]
2942
-
2943
- // Jump to next handler if match returned False
2944
- // JumpIfFalse pops the bool, leaving [exception, exception]
2945
- let no_match_jump = self.code.emit_jump(Opcode::JumpIfFalse);
2946
-
2947
- if is_last {
2948
- // Last handler - if no match, reraise
2949
- // But first we need to handle the exception var cleanup
2950
- } else {
2951
- next_handler_jumps.push(no_match_jump);
2952
- }
2953
-
2954
- // After JumpIfFalse (match succeeded), stack is [exception, exception]
2955
- // Pop the duplicate that was used for the type check
2956
- self.code.emit(Opcode::Pop);
2957
- // Stack: [exception]
2958
-
2959
- // Exception matched! Bind to variable if needed
2960
- if let Some(name) = &handler.name {
2961
- // Stack: [exception]
2962
- // Store to variable (don't pop - we still need it for current_exception)
2963
- self.code.emit(Opcode::Dup);
2964
- self.compile_store(name);
2965
- }
2966
-
2967
- // Track that we're inside an except handler (for break/continue cleanup)
2968
- self.except_handler_depth += 1;
2969
-
2970
- // Compile handler body
2971
- self.compile_block(&handler.body)?;
2972
-
2973
- // Exit except handler context
2974
- self.except_handler_depth -= 1;
2975
-
2976
- // Delete exception variable (Python 3 behavior)
2977
- if let Some(name) = &handler.name {
2978
- self.compile_delete(name);
2979
- }
2980
-
2981
- // Clear current_exception
2982
- self.code.emit(Opcode::ClearException);
2983
-
2984
- // Pop the exception from stack
2985
- self.code.emit(Opcode::Pop);
2986
-
2987
- // Jump to finally
2988
- finally_jumps.push(self.code.emit_jump(Opcode::Jump));
2989
-
2990
- // If this was last handler and no match, we need to reraise
2991
- if is_last {
2992
- self.code.patch_jump(no_match_jump);
2993
- // Coming from JumpIfFalse no-match path, stack has [exception, exception]
2994
- // Reset stack depth for jump target
2995
- self.code.set_stack_depth(handler_entry_depth + 1);
2996
- // We need to pop the duplicate before reraising
2997
- self.code.emit(Opcode::Pop);
2998
- self.code.emit(Opcode::Reraise);
2999
- }
3000
- } else {
3001
- // Bare except: catches everything
3002
- // Stack: [exception]
3003
-
3004
- // Bind to variable if needed
3005
- if let Some(name) = &handler.name {
3006
- self.code.emit(Opcode::Dup);
3007
- self.compile_store(name);
3008
- }
3009
-
3010
- // Track that we're inside an except handler (for break/continue cleanup)
3011
- self.except_handler_depth += 1;
3012
-
3013
- // Compile handler body
3014
- self.compile_block(&handler.body)?;
3015
-
3016
- // Exit except handler context
3017
- self.except_handler_depth -= 1;
3018
-
3019
- // Delete exception variable
3020
- if let Some(name) = &handler.name {
3021
- self.compile_delete(name);
3022
- }
3023
-
3024
- // Clear current_exception
3025
- self.code.emit(Opcode::ClearException);
3026
-
3027
- // Pop the exception from stack
3028
- self.code.emit(Opcode::Pop);
3029
-
3030
- // Jump to finally
3031
- finally_jumps.push(self.code.emit_jump(Opcode::Jump));
3032
- }
3033
- }
3034
-
3035
- Ok(())
3036
- }
3037
-
3038
- /// Compiles deletion of a variable.
3039
- ///
3040
- /// At module level, `Local` and `LocalUnassigned` scopes emit `DeleteGlobal`
3041
- /// because module-level locals live in the globals array.
3042
- fn compile_delete(&mut self, target: &Identifier) {
3043
- let slot = u16::try_from(target.namespace_id().index()).expect("local slot exceeds u16");
3044
- match target.scope {
3045
- NameScope::Local | NameScope::LocalUnassigned => {
3046
- if self.is_module_scope {
3047
- self.code.emit_u16(Opcode::DeleteGlobal, slot);
3048
- } else if let Ok(s) = u8::try_from(slot) {
3049
- self.code.emit_u8(Opcode::DeleteLocal, s);
3050
- } else {
3051
- // Wide variant not implemented yet
3052
- todo!("DeleteLocalW for slot > 255");
3053
- }
3054
- }
3055
- NameScope::Global => {
3056
- self.code.emit_u16(Opcode::DeleteGlobal, slot);
3057
- }
3058
- NameScope::Cell => {
3059
- // Delete cell not commonly needed
3060
- // For now, just store None
3061
- self.code.emit(Opcode::LoadNone);
3062
- self.compile_store(target);
3063
- }
3064
- }
3065
- }
3066
- }
3067
-
3068
- /// Error that can occur during bytecode compilation.
3069
- ///
3070
- /// These are typically limit violations that can't be represented in the bytecode
3071
- /// format (e.g., too many arguments, too many local variables), or import errors
3072
- /// detected at compile time.
3073
- #[derive(Debug, Clone)]
3074
- pub struct CompileError {
3075
- /// Error message describing the issue.
3076
- message: Cow<'static, str>,
3077
- /// Source location where the error occurred.
3078
- position: CodeRange,
3079
- /// Exception type to use (defaults to SyntaxError).
3080
- exc_type: ExcType,
3081
- }
3082
-
3083
- impl CompileError {
3084
- /// Creates a new compile error with the given message and position.
3085
- ///
3086
- /// Defaults to `SyntaxError` exception type.
3087
- fn new(message: impl Into<Cow<'static, str>>, position: CodeRange) -> Self {
3088
- Self {
3089
- message: message.into(),
3090
- position,
3091
- exc_type: ExcType::SyntaxError,
3092
- }
3093
- }
3094
-
3095
- /// Converts this compile error into a Python exception.
3096
- ///
3097
- /// Uses the stored exception type (SyntaxError or ModuleNotFoundError).
3098
- /// - SyntaxError: hides the `, in <module>` part (CPython's format)
3099
- /// - ModuleNotFoundError: hides caret markers (CPython doesn't show them)
3100
- pub fn into_python_exc(self, filename: &str, source: &str) -> MontyException {
3101
- let mut frame = if self.exc_type == ExcType::SyntaxError {
3102
- // SyntaxError uses different format: no `, in <module>`
3103
- StackFrame::from_position_syntax_error(self.position, filename, source)
3104
- } else {
3105
- StackFrame::from_position(self.position, filename, source)
3106
- };
3107
- // CPython doesn't show carets for module not found errors
3108
- if self.exc_type == ExcType::ModuleNotFoundError {
3109
- frame.hide_caret = true;
3110
- }
3111
- MontyException::new_full(self.exc_type, Some(self.message.into_owned()), vec![frame])
3112
- }
3113
- }
3114
-
3115
- // ============================================================================
3116
- // Operator Mapping Functions
3117
- // ============================================================================
3118
-
3119
- /// Maps a binary `Operator` to its corresponding `Opcode`.
3120
- fn operator_to_opcode(op: &Operator) -> Opcode {
3121
- match op {
3122
- Operator::Add => Opcode::BinaryAdd,
3123
- Operator::Sub => Opcode::BinarySub,
3124
- Operator::Mult => Opcode::BinaryMul,
3125
- Operator::Div => Opcode::BinaryDiv,
3126
- Operator::FloorDiv => Opcode::BinaryFloorDiv,
3127
- Operator::Mod => Opcode::BinaryMod,
3128
- Operator::Pow => Opcode::BinaryPow,
3129
- Operator::MatMult => Opcode::BinaryMatMul,
3130
- Operator::LShift => Opcode::BinaryLShift,
3131
- Operator::RShift => Opcode::BinaryRShift,
3132
- Operator::BitOr => Opcode::BinaryOr,
3133
- Operator::BitXor => Opcode::BinaryXor,
3134
- Operator::BitAnd => Opcode::BinaryAnd,
3135
- // And/Or are handled separately for short-circuit evaluation
3136
- Operator::And | Operator::Or => {
3137
- unreachable!("And/Or operators handled in compile_binary_op")
3138
- }
3139
- }
3140
- }
3141
-
3142
- /// Maps an `Operator` to its in-place (augmented assignment) `Opcode`.
3143
- ///
3144
- /// Returns `None` for operators that don't have an in-place opcode (currently `MatMult`,
3145
- /// since matrix multiplication is not yet supported). Returns `Some(opcode)` for all
3146
- /// other valid augmented assignment operators.
3147
- ///
3148
- /// # Panics
3149
- ///
3150
- /// Panics if called with `And` or `Or` operators, which cannot be used in augmented
3151
- /// assignments (this would be a parser bug).
3152
- fn operator_to_inplace_opcode(op: &Operator) -> Option<Opcode> {
3153
- match op {
3154
- Operator::Add => Some(Opcode::InplaceAdd),
3155
- Operator::Sub => Some(Opcode::InplaceSub),
3156
- Operator::Mult => Some(Opcode::InplaceMul),
3157
- Operator::Div => Some(Opcode::InplaceDiv),
3158
- Operator::FloorDiv => Some(Opcode::InplaceFloorDiv),
3159
- Operator::Mod => Some(Opcode::InplaceMod),
3160
- Operator::Pow => Some(Opcode::InplacePow),
3161
- Operator::BitAnd => Some(Opcode::InplaceAnd),
3162
- Operator::BitOr => Some(Opcode::InplaceOr),
3163
- Operator::BitXor => Some(Opcode::InplaceXor),
3164
- Operator::LShift => Some(Opcode::InplaceLShift),
3165
- Operator::RShift => Some(Opcode::InplaceRShift),
3166
- Operator::MatMult => None,
3167
- Operator::And | Operator::Or => {
3168
- unreachable!("And/Or operators cannot be used in augmented assignment")
3169
- }
3170
- }
3171
- }
3172
-
3173
- /// Maps a `CmpOperator` to its corresponding `Opcode`.
3174
- fn cmp_operator_to_opcode(op: &CmpOperator) -> Opcode {
3175
- match op {
3176
- CmpOperator::Eq => Opcode::CompareEq,
3177
- CmpOperator::NotEq => Opcode::CompareNe,
3178
- CmpOperator::Lt => Opcode::CompareLt,
3179
- CmpOperator::LtE => Opcode::CompareLe,
3180
- CmpOperator::Gt => Opcode::CompareGt,
3181
- CmpOperator::GtE => Opcode::CompareGe,
3182
- CmpOperator::Is => Opcode::CompareIs,
3183
- CmpOperator::IsNot => Opcode::CompareIsNot,
3184
- CmpOperator::In => Opcode::CompareIn,
3185
- CmpOperator::NotIn => Opcode::CompareNotIn,
3186
- // ModEq is handled specially at the call site (needs constant operand)
3187
- CmpOperator::ModEq(_) => unreachable!("ModEq handled at call site"),
3188
- }
3189
- }
3190
-
3191
- /// Returns `true` if any item in the sequence is a PEP 448 unpack (`*expr`).
3192
- ///
3193
- /// Used to choose between the fast single-`Build*(N)` path and the generalized
3194
- /// incremental `Build*(0)` + `ListAppend`/`ListExtend` (or `SetAdd`/`SetExtend`) path.
3195
- /// Only the generalized path is needed when at least one `Unpack` variant is present.
3196
- fn has_unpack_seq(items: &[SequenceItem]) -> bool {
3197
- items.iter().any(|i| matches!(i, SequenceItem::Unpack(_)))
3198
- }
3199
-
3200
- /// Returns `true` if any item in the dict literal is a PEP 448 `**expr` unpack.
3201
- ///
3202
- /// Used to choose between the fast single-`BuildDict(N)` path and the generalized
3203
- /// incremental `BuildDict(0)` + `DictSetItem`/`DictUpdate` path.
3204
- fn has_unpack_dict(items: &[DictItem]) -> bool {
3205
- items.iter().any(|i| matches!(i, DictItem::Unpack(_)))
3206
- }