superacli 1.1.6 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1268) hide show
  1. package/CONTRIBUTING.md +270 -0
  2. package/README.md +141 -54
  3. package/__tests__/adapter-schema.test.js +251 -86
  4. package/__tests__/azd-plugin.test.js +109 -0
  5. package/__tests__/config.test.js +4 -3
  6. package/__tests__/discover.test.js +59 -0
  7. package/__tests__/goose-plugin.test.js +149 -0
  8. package/__tests__/help-json.test.js +2 -0
  9. package/__tests__/openhands-plugin.test.js +106 -0
  10. package/__tests__/plugin-cocoindex-code-uninstall.test.js +19 -0
  11. package/__tests__/plugin-cocoindex-code.test.js +37 -0
  12. package/__tests__/plugin-install-guidance.test.js +81 -0
  13. package/__tests__/plugins-registry.test.js +44 -0
  14. package/__tests__/plugins-store.test.js +40 -5
  15. package/__tests__/process-adapter.test.js +50 -1
  16. package/__tests__/resend-plugin.test.js +109 -82
  17. package/__tests__/server-app.test.js +1 -0
  18. package/__tests__/server-routes-commands.test.js +20 -2
  19. package/__tests__/server-routes-plugins.test.js +130 -0
  20. package/__tests__/skills.test.js +26 -0
  21. package/__tests__/squirrelscan-plugin.test.js +129 -0
  22. package/__tests__/uipath-plugin.test.js +104 -0
  23. package/__tests__/uipathcli-plugin.test.js +95 -0
  24. package/cli/adapters/mcp.js +2 -0
  25. package/cli/adapters/process.js +50 -7
  26. package/cli/config.js +240 -3
  27. package/cli/discover.js +157 -0
  28. package/cli/help-json.js +16 -1
  29. package/cli/plugin-install-guidance.js +92 -37
  30. package/cli/plugins-manager.js +4 -3
  31. package/cli/plugins-registry.js +74 -8
  32. package/cli/plugins-store.js +78 -17
  33. package/cli/skills-mcp.js +1 -1
  34. package/cli/skills.js +39 -2
  35. package/cli/supercli.js +255 -63
  36. package/docs/feature-gaps.md +8 -8
  37. package/docs/features/azd-uipath-plugins.md +43 -0
  38. package/docs/features/server-plugins.md +62 -0
  39. package/docs/features/skills.md +9 -5
  40. package/docs/index.html +183 -123
  41. package/docs/{supported-harnesses.md → plugins-available.md} +4 -3
  42. package/docs/{plugin-harness-guide.md → plugins-how-to.md} +1 -1
  43. package/docs/plugins.md +26 -20
  44. package/docs/server-plugins-usage-guide.md +182 -0
  45. package/docs/skills-catalog.md +12 -10
  46. package/index.html +384 -0
  47. package/package.json +2 -2
  48. package/plugins/agent-browser/README.md +69 -0
  49. package/plugins/agent-browser/plugin.json +111 -0
  50. package/plugins/agent-browser/skills/quickstart/SKILL.md +66 -0
  51. package/plugins/aider/README.md +53 -0
  52. package/plugins/aider/plugin.json +105 -0
  53. package/plugins/aider/scripts/aider-wrapper.js +243 -0
  54. package/plugins/aider/scripts/setup-aider.js +37 -0
  55. package/plugins/aider/skills/dry-run-review.md +24 -0
  56. package/plugins/aider/skills/model-and-provider.md +24 -0
  57. package/plugins/aider/skills/one-shot-edits.md +30 -0
  58. package/plugins/aider/skills/quickstart/SKILL.md +51 -0
  59. package/plugins/azd/README.md +28 -0
  60. package/plugins/azd/plugin.json +87 -0
  61. package/plugins/azd/skills/quickstart/SKILL.md +41 -0
  62. package/plugins/blogwatcher/README.md +3 -3
  63. package/plugins/boxlite/Dockerfile +9 -0
  64. package/plugins/boxlite/README.md +62 -0
  65. package/plugins/boxlite/plugin.json +201 -0
  66. package/plugins/boxlite/scripts/run-boxlite.js +106 -0
  67. package/plugins/boxlite/skills/quickstart/SKILL.md +40 -0
  68. package/plugins/cass/plugin.json +150 -0
  69. package/plugins/cass/scripts/setup-cass.js +47 -0
  70. package/plugins/cass/skills/quickstart/SKILL.md +46 -0
  71. package/plugins/clever/README.md +46 -0
  72. package/plugins/clever/plugin.json +119 -0
  73. package/plugins/clever/scripts/setup-clever.js +28 -0
  74. package/plugins/clever/skills/auth-and-profile.md +29 -0
  75. package/plugins/clever/skills/passthrough-safety.md +21 -0
  76. package/plugins/clever/skills/quickstart/SKILL.md +45 -0
  77. package/plugins/clever/skills/resource-inventory.md +24 -0
  78. package/plugins/clix/README.md +4 -4
  79. package/plugins/cocoindex-code/README.md +64 -0
  80. package/plugins/cocoindex-code/plugin.json +81 -0
  81. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-310.pyc +0 -0
  82. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-311.pyc +0 -0
  83. package/plugins/cocoindex-code/scripts/post-install.js +61 -0
  84. package/plugins/cocoindex-code/scripts/post-uninstall.js +25 -0
  85. package/plugins/cocoindex-code/scripts/query.py +88 -0
  86. package/plugins/cocoindex-code/scripts/run-query.js +50 -0
  87. package/plugins/cocoindex-code/skills/quickstart/SKILL.md +73 -0
  88. package/plugins/copilot/README.md +24 -0
  89. package/plugins/copilot/plugin.json +80 -0
  90. package/plugins/copilot/skills/quickstart/SKILL.md +44 -0
  91. package/plugins/gemini/README.md +24 -0
  92. package/plugins/gemini/plugin.json +98 -0
  93. package/plugins/gemini/skills/quickstart/SKILL.md +44 -0
  94. package/plugins/gifcap/plugin.json +119 -0
  95. package/plugins/gifcap/scripts/setup-gifcap.js +44 -0
  96. package/plugins/gifcap/skills/quickstart/SKILL.md +34 -0
  97. package/plugins/gifcap/test-record-quiet.gif +0 -0
  98. package/plugins/gifcap/test-record.gif +0 -0
  99. package/plugins/goose/README.md +36 -0
  100. package/plugins/goose/plugin.json +183 -0
  101. package/plugins/goose/skills/quickstart/SKILL.md +44 -0
  102. package/plugins/json-server/README.md +58 -0
  103. package/plugins/json-server/plugin.json +113 -0
  104. package/plugins/json-server/skills/quickstart/SKILL.md +57 -0
  105. package/plugins/lightpanda/README.md +145 -0
  106. package/plugins/lightpanda/package-lock.json +1375 -0
  107. package/plugins/lightpanda/package.json +12 -0
  108. package/plugins/lightpanda/plugin.json +116 -0
  109. package/plugins/lightpanda/scripts/lightpanda-contacts.js +494 -0
  110. package/plugins/lightpanda/scripts/lightpanda-generic-extract.js +403 -0
  111. package/plugins/lightpanda/scripts/lightpanda-wrapper.js +480 -0
  112. package/plugins/lightpanda/scripts/setup-lightpanda.js +39 -0
  113. package/plugins/lightpanda/skills/contact-discovery.md +51 -0
  114. package/plugins/lightpanda/skills/generic-extraction.md +66 -0
  115. package/plugins/lightpanda/skills/quickstart/SKILL.md +103 -0
  116. package/plugins/lightpanda/skills/resilient-navigation.md +42 -0
  117. package/plugins/monty/README.md +2 -2
  118. package/plugins/nullclaw/README.md +3 -3
  119. package/plugins/offline-ai/README.md +23 -0
  120. package/plugins/offline-ai/plugin.json +82 -0
  121. package/plugins/offline-ai/skills/quickstart/SKILL.md +43 -0
  122. package/plugins/openhands/README.md +25 -0
  123. package/plugins/openhands/plugin.json +116 -0
  124. package/plugins/openhands/skills/quickstart/SKILL.md +26 -0
  125. package/plugins/plandex/README.md +25 -0
  126. package/plugins/plandex/plugin.json +130 -0
  127. package/plugins/plandex/skills/quickstart/SKILL.md +50 -0
  128. package/plugins/plugins.json +199 -0
  129. package/plugins/squirrelscan/Dockerfile +5 -0
  130. package/plugins/squirrelscan/README.md +47 -0
  131. package/plugins/squirrelscan/plugin.json +493 -0
  132. package/plugins/squirrelscan/scripts/post-install.js +33 -0
  133. package/plugins/squirrelscan/scripts/post-uninstall.js +25 -0
  134. package/plugins/squirrelscan/scripts/run-squirrel.js +73 -0
  135. package/plugins/squirrelscan/skills/audit-workflow/SKILL.md +33 -0
  136. package/plugins/squirrelscan/skills/publish-report/SKILL.md +33 -0
  137. package/plugins/squirrelscan/skills/quickstart/SKILL.md +41 -0
  138. package/plugins/uipath/README.md +27 -0
  139. package/plugins/uipath/plugin.json +86 -0
  140. package/plugins/uipath/skills/quickstart/SKILL.md +47 -0
  141. package/plugins/uipathcli/README.md +28 -0
  142. package/plugins/uipathcli/plugin.json +120 -0
  143. package/plugins/uipathcli/scripts/run-uipath-cli.js +49 -0
  144. package/plugins/uipathcli/skills/quickstart/SKILL.md +22 -0
  145. package/plugins/xurl/README.md +4 -4
  146. package/server/app.js +5 -2
  147. package/server/public/app.js +3 -0
  148. package/server/routes/commands.js +95 -12
  149. package/server/routes/plugins.js +262 -0
  150. package/server/services/pluginsService.js +303 -0
  151. package/server/views/command-edit.ejs +196 -14
  152. package/server/views/partials/head.ejs +1 -0
  153. package/server/views/plugins.ejs +264 -0
  154. package/tests/test-plugins-registry.js +30 -0
  155. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl +0 -20
  156. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl.meta.json +0 -1
  157. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl +0 -21
  158. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl.meta.json +0 -1
  159. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl +0 -22
  160. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl.meta.json +0 -1
  161. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl +0 -23
  162. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl.meta.json +0 -1
  163. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl +0 -24
  164. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl.meta.json +0 -1
  165. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl +0 -24
  166. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl.meta.json +0 -1
  167. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl +0 -24
  168. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl.meta.json +0 -1
  169. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl +0 -24
  170. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl.meta.json +0 -1
  171. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl +0 -24
  172. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl.meta.json +0 -1
  173. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl +0 -24
  174. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl.meta.json +0 -1
  175. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl +0 -24
  176. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl.meta.json +0 -1
  177. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl +0 -24
  178. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl.meta.json +0 -1
  179. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl +0 -24
  180. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl.meta.json +0 -1
  181. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl +0 -25
  182. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl.meta.json +0 -1
  183. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl +0 -25
  184. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl.meta.json +0 -1
  185. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl +0 -25
  186. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl.meta.json +0 -1
  187. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl +0 -26
  188. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl.meta.json +0 -1
  189. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl +0 -27
  190. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl.meta.json +0 -1
  191. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl +0 -28
  192. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl.meta.json +0 -1
  193. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl +0 -29
  194. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl.meta.json +0 -1
  195. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl +0 -30
  196. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl.meta.json +0 -1
  197. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl +0 -31
  198. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl.meta.json +0 -1
  199. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl +0 -32
  200. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl.meta.json +0 -1
  201. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl +0 -32
  202. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl.meta.json +0 -1
  203. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl +0 -32
  204. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl.meta.json +0 -1
  205. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl +0 -32
  206. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl.meta.json +0 -1
  207. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl +0 -32
  208. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl.meta.json +0 -1
  209. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl +0 -32
  210. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl.meta.json +0 -1
  211. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl +0 -32
  212. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl.meta.json +0 -1
  213. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl +0 -32
  214. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl.meta.json +0 -1
  215. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl +0 -32
  216. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl.meta.json +0 -1
  217. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl +0 -32
  218. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl.meta.json +0 -1
  219. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl +0 -32
  220. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl.meta.json +0 -1
  221. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl +0 -32
  222. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl.meta.json +0 -1
  223. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl +0 -32
  224. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl.meta.json +0 -1
  225. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl +0 -32
  226. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl.meta.json +0 -1
  227. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl +0 -33
  228. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl.meta.json +0 -1
  229. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl +0 -33
  230. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl.meta.json +0 -1
  231. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl +0 -34
  232. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl.meta.json +0 -1
  233. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl +0 -34
  234. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl.meta.json +0 -1
  235. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl +0 -35
  236. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl.meta.json +0 -1
  237. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl +0 -36
  238. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl.meta.json +0 -1
  239. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl +0 -37
  240. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl.meta.json +0 -1
  241. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl +0 -38
  242. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl.meta.json +0 -1
  243. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl +0 -39
  244. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl.meta.json +0 -1
  245. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl +0 -40
  246. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl.meta.json +0 -1
  247. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl +0 -41
  248. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl.meta.json +0 -1
  249. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl +0 -42
  250. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl.meta.json +0 -1
  251. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl +0 -43
  252. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl.meta.json +0 -1
  253. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl +0 -44
  254. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl.meta.json +0 -1
  255. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl +0 -45
  256. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl.meta.json +0 -1
  257. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl +0 -46
  258. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl.meta.json +0 -1
  259. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl +0 -47
  260. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl.meta.json +0 -1
  261. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl +0 -48
  262. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl.meta.json +0 -1
  263. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl +0 -49
  264. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl.meta.json +0 -1
  265. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl +0 -50
  266. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl.meta.json +0 -1
  267. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl +0 -51
  268. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl.meta.json +0 -1
  269. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl +0 -52
  270. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl.meta.json +0 -1
  271. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl +0 -53
  272. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl.meta.json +0 -1
  273. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl +0 -54
  274. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl.meta.json +0 -1
  275. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl +0 -55
  276. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl.meta.json +0 -1
  277. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl +0 -56
  278. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl.meta.json +0 -1
  279. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl +0 -57
  280. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl.meta.json +0 -1
  281. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl +0 -57
  282. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl.meta.json +0 -1
  283. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl +0 -57
  284. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl.meta.json +0 -1
  285. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl +0 -57
  286. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl.meta.json +0 -1
  287. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl +0 -57
  288. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl.meta.json +0 -1
  289. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl +0 -57
  290. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl.meta.json +0 -1
  291. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl +0 -57
  292. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl.meta.json +0 -1
  293. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl +0 -57
  294. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl.meta.json +0 -1
  295. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl +0 -57
  296. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl.meta.json +0 -1
  297. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl +0 -57
  298. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl.meta.json +0 -1
  299. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl +0 -57
  300. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl.meta.json +0 -1
  301. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl +0 -57
  302. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl.meta.json +0 -1
  303. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl +0 -57
  304. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl.meta.json +0 -1
  305. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl +0 -57
  306. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl.meta.json +0 -1
  307. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl +0 -57
  308. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl.meta.json +0 -1
  309. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl +0 -57
  310. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl.meta.json +0 -1
  311. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl +0 -57
  312. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl.meta.json +0 -1
  313. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl +0 -57
  314. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl.meta.json +0 -1
  315. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl +0 -57
  316. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl.meta.json +0 -1
  317. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl +0 -57
  318. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl.meta.json +0 -1
  319. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl +0 -57
  320. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl.meta.json +0 -1
  321. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl +0 -57
  322. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl.meta.json +0 -1
  323. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl +0 -57
  324. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl.meta.json +0 -1
  325. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl +0 -57
  326. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl.meta.json +0 -1
  327. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl +0 -57
  328. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl.meta.json +0 -1
  329. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl +0 -57
  330. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl.meta.json +0 -1
  331. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl +0 -57
  332. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl.meta.json +0 -1
  333. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl +0 -57
  334. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl.meta.json +0 -1
  335. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl +0 -57
  336. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl.meta.json +0 -1
  337. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl +0 -57
  338. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl.meta.json +0 -1
  339. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl +0 -58
  340. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl.meta.json +0 -1
  341. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl +0 -59
  342. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl.meta.json +0 -1
  343. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl +0 -60
  344. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl.meta.json +0 -1
  345. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl +0 -60
  346. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl.meta.json +0 -1
  347. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl +0 -60
  348. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl.meta.json +0 -1
  349. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl +0 -60
  350. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl.meta.json +0 -1
  351. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl +0 -60
  352. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl.meta.json +0 -1
  353. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl +0 -60
  354. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl.meta.json +0 -1
  355. package/.beads/config.yaml +0 -4
  356. package/.beads/issues.jsonl +0 -60
  357. package/.beads/metadata.json +0 -4
  358. package/docs/docs.html +0 -224
  359. package/docs/mcp-cheatsheet.md +0 -324
  360. package/docs/visual-overview.md +0 -21
  361. package/ref-monty/.cargo/config.toml +0 -3
  362. package/ref-monty/.claude/settings.json +0 -60
  363. package/ref-monty/.claude/skills/fastmod/SKILL.md +0 -22
  364. package/ref-monty/.claude/skills/python-playground/SKILL.md +0 -47
  365. package/ref-monty/.codecov.yml +0 -12
  366. package/ref-monty/.github/actions/build-pgo-wheel/action.yml +0 -72
  367. package/ref-monty/.github/workflows/ci.yml +0 -776
  368. package/ref-monty/.github/workflows/codspeed.yml +0 -45
  369. package/ref-monty/.github/workflows/init-npm-packages.yml +0 -82
  370. package/ref-monty/.pre-commit-config.yaml +0 -47
  371. package/ref-monty/.python-version +0 -1
  372. package/ref-monty/.rustfmt.toml +0 -4
  373. package/ref-monty/.zed/settings.json +0 -11
  374. package/ref-monty/CLAUDE.md +0 -535
  375. package/ref-monty/Cargo.lock +0 -3798
  376. package/ref-monty/Cargo.toml +0 -87
  377. package/ref-monty/LICENSE +0 -21
  378. package/ref-monty/Makefile +0 -216
  379. package/ref-monty/README.md +0 -430
  380. package/ref-monty/RELEASING.md +0 -47
  381. package/ref-monty/crates/fuzz/Cargo.toml +0 -30
  382. package/ref-monty/crates/fuzz/fuzz_targets/string_input_panic.rs +0 -37
  383. package/ref-monty/crates/fuzz/fuzz_targets/tokens_input_panic.rs +0 -552
  384. package/ref-monty/crates/monty/Cargo.toml +0 -68
  385. package/ref-monty/crates/monty/benches/main.rs +0 -247
  386. package/ref-monty/crates/monty/build.rs +0 -10
  387. package/ref-monty/crates/monty/src/args.rs +0 -733
  388. package/ref-monty/crates/monty/src/asyncio.rs +0 -179
  389. package/ref-monty/crates/monty/src/builtins/abs.rs +0 -55
  390. package/ref-monty/crates/monty/src/builtins/all.rs +0 -30
  391. package/ref-monty/crates/monty/src/builtins/any.rs +0 -30
  392. package/ref-monty/crates/monty/src/builtins/bin.rs +0 -59
  393. package/ref-monty/crates/monty/src/builtins/chr.rs +0 -46
  394. package/ref-monty/crates/monty/src/builtins/divmod.rs +0 -164
  395. package/ref-monty/crates/monty/src/builtins/enumerate.rs +0 -52
  396. package/ref-monty/crates/monty/src/builtins/filter.rs +0 -67
  397. package/ref-monty/crates/monty/src/builtins/getattr.rs +0 -65
  398. package/ref-monty/crates/monty/src/builtins/hash.rs +0 -28
  399. package/ref-monty/crates/monty/src/builtins/hex.rs +0 -58
  400. package/ref-monty/crates/monty/src/builtins/id.rs +0 -24
  401. package/ref-monty/crates/monty/src/builtins/isinstance.rs +0 -68
  402. package/ref-monty/crates/monty/src/builtins/len.rs +0 -25
  403. package/ref-monty/crates/monty/src/builtins/map.rs +0 -98
  404. package/ref-monty/crates/monty/src/builtins/min_max.rs +0 -113
  405. package/ref-monty/crates/monty/src/builtins/mod.rs +0 -246
  406. package/ref-monty/crates/monty/src/builtins/next.rs +0 -21
  407. package/ref-monty/crates/monty/src/builtins/oct.rs +0 -59
  408. package/ref-monty/crates/monty/src/builtins/ord.rs +0 -67
  409. package/ref-monty/crates/monty/src/builtins/pow.rs +0 -365
  410. package/ref-monty/crates/monty/src/builtins/print.rs +0 -141
  411. package/ref-monty/crates/monty/src/builtins/repr.rs +0 -16
  412. package/ref-monty/crates/monty/src/builtins/reversed.rs +0 -28
  413. package/ref-monty/crates/monty/src/builtins/round.rs +0 -174
  414. package/ref-monty/crates/monty/src/builtins/sorted.rs +0 -151
  415. package/ref-monty/crates/monty/src/builtins/sum.rs +0 -66
  416. package/ref-monty/crates/monty/src/builtins/type_.rs +0 -16
  417. package/ref-monty/crates/monty/src/builtins/zip.rs +0 -77
  418. package/ref-monty/crates/monty/src/bytecode/builder.rs +0 -699
  419. package/ref-monty/crates/monty/src/bytecode/code.rs +0 -310
  420. package/ref-monty/crates/monty/src/bytecode/compiler.rs +0 -3206
  421. package/ref-monty/crates/monty/src/bytecode/mod.rs +0 -24
  422. package/ref-monty/crates/monty/src/bytecode/op.rs +0 -617
  423. package/ref-monty/crates/monty/src/bytecode/vm/async_exec.rs +0 -1058
  424. package/ref-monty/crates/monty/src/bytecode/vm/attr.rs +0 -63
  425. package/ref-monty/crates/monty/src/bytecode/vm/binary.rs +0 -487
  426. package/ref-monty/crates/monty/src/bytecode/vm/call.rs +0 -767
  427. package/ref-monty/crates/monty/src/bytecode/vm/collections.rs +0 -741
  428. package/ref-monty/crates/monty/src/bytecode/vm/compare.rs +0 -147
  429. package/ref-monty/crates/monty/src/bytecode/vm/exceptions.rs +0 -297
  430. package/ref-monty/crates/monty/src/bytecode/vm/format.rs +0 -132
  431. package/ref-monty/crates/monty/src/bytecode/vm/mod.rs +0 -1958
  432. package/ref-monty/crates/monty/src/bytecode/vm/scheduler.rs +0 -620
  433. package/ref-monty/crates/monty/src/exception_private.rs +0 -1513
  434. package/ref-monty/crates/monty/src/exception_public.rs +0 -346
  435. package/ref-monty/crates/monty/src/expressions.rs +0 -694
  436. package/ref-monty/crates/monty/src/fstring.rs +0 -854
  437. package/ref-monty/crates/monty/src/function.rs +0 -119
  438. package/ref-monty/crates/monty/src/heap.rs +0 -1073
  439. package/ref-monty/crates/monty/src/heap_data.rs +0 -985
  440. package/ref-monty/crates/monty/src/heap_traits.rs +0 -312
  441. package/ref-monty/crates/monty/src/intern.rs +0 -837
  442. package/ref-monty/crates/monty/src/io.rs +0 -106
  443. package/ref-monty/crates/monty/src/lib.rs +0 -52
  444. package/ref-monty/crates/monty/src/modules/asyncio.rs +0 -144
  445. package/ref-monty/crates/monty/src/modules/math.rs +0 -1453
  446. package/ref-monty/crates/monty/src/modules/mod.rs +0 -120
  447. package/ref-monty/crates/monty/src/modules/os.rs +0 -116
  448. package/ref-monty/crates/monty/src/modules/pathlib.rs +0 -33
  449. package/ref-monty/crates/monty/src/modules/re.rs +0 -606
  450. package/ref-monty/crates/monty/src/modules/sys.rs +0 -60
  451. package/ref-monty/crates/monty/src/modules/typing.rs +0 -70
  452. package/ref-monty/crates/monty/src/namespace.rs +0 -21
  453. package/ref-monty/crates/monty/src/object.rs +0 -1040
  454. package/ref-monty/crates/monty/src/os.rs +0 -215
  455. package/ref-monty/crates/monty/src/parse.rs +0 -1730
  456. package/ref-monty/crates/monty/src/prepare.rs +0 -3015
  457. package/ref-monty/crates/monty/src/repl.rs +0 -1109
  458. package/ref-monty/crates/monty/src/resource.rs +0 -559
  459. package/ref-monty/crates/monty/src/run.rs +0 -457
  460. package/ref-monty/crates/monty/src/run_progress.rs +0 -821
  461. package/ref-monty/crates/monty/src/signature.rs +0 -651
  462. package/ref-monty/crates/monty/src/sorting.rs +0 -100
  463. package/ref-monty/crates/monty/src/types/bytes.rs +0 -2356
  464. package/ref-monty/crates/monty/src/types/dataclass.rs +0 -345
  465. package/ref-monty/crates/monty/src/types/dict.rs +0 -879
  466. package/ref-monty/crates/monty/src/types/dict_view.rs +0 -619
  467. package/ref-monty/crates/monty/src/types/iter.rs +0 -799
  468. package/ref-monty/crates/monty/src/types/list.rs +0 -929
  469. package/ref-monty/crates/monty/src/types/long_int.rs +0 -211
  470. package/ref-monty/crates/monty/src/types/mod.rs +0 -48
  471. package/ref-monty/crates/monty/src/types/module.rs +0 -146
  472. package/ref-monty/crates/monty/src/types/namedtuple.rs +0 -261
  473. package/ref-monty/crates/monty/src/types/path.rs +0 -596
  474. package/ref-monty/crates/monty/src/types/property.rs +0 -35
  475. package/ref-monty/crates/monty/src/types/py_trait.rs +0 -322
  476. package/ref-monty/crates/monty/src/types/range.rs +0 -285
  477. package/ref-monty/crates/monty/src/types/re_match.rs +0 -522
  478. package/ref-monty/crates/monty/src/types/re_pattern.rs +0 -726
  479. package/ref-monty/crates/monty/src/types/set.rs +0 -1373
  480. package/ref-monty/crates/monty/src/types/slice.rs +0 -257
  481. package/ref-monty/crates/monty/src/types/str.rs +0 -2051
  482. package/ref-monty/crates/monty/src/types/tuple.rs +0 -376
  483. package/ref-monty/crates/monty/src/types/type.rs +0 -407
  484. package/ref-monty/crates/monty/src/value.rs +0 -2558
  485. package/ref-monty/crates/monty/test_cases/args__dict_get_no_args.py +0 -3
  486. package/ref-monty/crates/monty/test_cases/args__dict_get_too_many.py +0 -3
  487. package/ref-monty/crates/monty/test_cases/args__dict_items_with_args.py +0 -3
  488. package/ref-monty/crates/monty/test_cases/args__dict_keys_with_args.py +0 -3
  489. package/ref-monty/crates/monty/test_cases/args__dict_pop_no_args.py +0 -3
  490. package/ref-monty/crates/monty/test_cases/args__dict_pop_too_many.py +0 -3
  491. package/ref-monty/crates/monty/test_cases/args__dict_values_with_args.py +0 -3
  492. package/ref-monty/crates/monty/test_cases/args__id_too_many.py +0 -2
  493. package/ref-monty/crates/monty/test_cases/args__len_no_args.py +0 -2
  494. package/ref-monty/crates/monty/test_cases/args__len_too_many.py +0 -2
  495. package/ref-monty/crates/monty/test_cases/args__len_type_error_int.py +0 -9
  496. package/ref-monty/crates/monty/test_cases/args__len_type_error_none.py +0 -9
  497. package/ref-monty/crates/monty/test_cases/args__list_append_no_args.py +0 -3
  498. package/ref-monty/crates/monty/test_cases/args__list_append_too_many.py +0 -3
  499. package/ref-monty/crates/monty/test_cases/args__list_insert_too_few.py +0 -3
  500. package/ref-monty/crates/monty/test_cases/args__list_insert_too_many.py +0 -3
  501. package/ref-monty/crates/monty/test_cases/args__repr_no_args.py +0 -2
  502. package/ref-monty/crates/monty/test_cases/arith__div_zero_float.py +0 -2
  503. package/ref-monty/crates/monty/test_cases/arith__div_zero_int.py +0 -2
  504. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_float.py +0 -2
  505. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_int.py +0 -2
  506. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg.py +0 -2
  507. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg_builtin.py +0 -9
  508. package/ref-monty/crates/monty/test_cases/assert__expr_fail.py +0 -2
  509. package/ref-monty/crates/monty/test_cases/assert__fail.py +0 -2
  510. package/ref-monty/crates/monty/test_cases/assert__fail_msg.py +0 -2
  511. package/ref-monty/crates/monty/test_cases/assert__fn_fail.py +0 -3
  512. package/ref-monty/crates/monty/test_cases/assert__ops.py +0 -11
  513. package/ref-monty/crates/monty/test_cases/async__asyncio_run.py +0 -47
  514. package/ref-monty/crates/monty/test_cases/async__basic.py +0 -10
  515. package/ref-monty/crates/monty/test_cases/async__closure.py +0 -14
  516. package/ref-monty/crates/monty/test_cases/async__double_await_coroutine.py +0 -16
  517. package/ref-monty/crates/monty/test_cases/async__exception.py +0 -10
  518. package/ref-monty/crates/monty/test_cases/async__ext_call.py +0 -73
  519. package/ref-monty/crates/monty/test_cases/async__gather_all.py +0 -85
  520. package/ref-monty/crates/monty/test_cases/async__nested_await.py +0 -15
  521. package/ref-monty/crates/monty/test_cases/async__nested_gather_ext.py +0 -37
  522. package/ref-monty/crates/monty/test_cases/async__not_awaitable.py +0 -10
  523. package/ref-monty/crates/monty/test_cases/async__not_imported.py +0 -14
  524. package/ref-monty/crates/monty/test_cases/async__recursion_depth_isolation.py +0 -27
  525. package/ref-monty/crates/monty/test_cases/async__return_types.py +0 -31
  526. package/ref-monty/crates/monty/test_cases/async__sequential.py +0 -16
  527. package/ref-monty/crates/monty/test_cases/async__traceback.py +0 -19
  528. package/ref-monty/crates/monty/test_cases/async__with_args.py +0 -14
  529. package/ref-monty/crates/monty/test_cases/attr__get_int_error.py +0 -9
  530. package/ref-monty/crates/monty/test_cases/attr__get_list_error.py +0 -9
  531. package/ref-monty/crates/monty/test_cases/attr__set_frozen_nonfield.py +0 -12
  532. package/ref-monty/crates/monty/test_cases/attr__set_int_error.py +0 -10
  533. package/ref-monty/crates/monty/test_cases/attr__set_list_error.py +0 -10
  534. package/ref-monty/crates/monty/test_cases/bench__kitchen_sink.py +0 -68
  535. package/ref-monty/crates/monty/test_cases/bool__ops.py +0 -20
  536. package/ref-monty/crates/monty/test_cases/builtin__add_type_error.py +0 -2
  537. package/ref-monty/crates/monty/test_cases/builtin__filter.py +0 -62
  538. package/ref-monty/crates/monty/test_cases/builtin__filter_not_iterable.py +0 -11
  539. package/ref-monty/crates/monty/test_cases/builtin__getattr.py +0 -84
  540. package/ref-monty/crates/monty/test_cases/builtin__iter_funcs.py +0 -42
  541. package/ref-monty/crates/monty/test_cases/builtin__iter_next.py +0 -66
  542. package/ref-monty/crates/monty/test_cases/builtin__map.py +0 -74
  543. package/ref-monty/crates/monty/test_cases/builtin__map_not_iterable.py +0 -11
  544. package/ref-monty/crates/monty/test_cases/builtin__math_funcs.py +0 -154
  545. package/ref-monty/crates/monty/test_cases/builtin__more_iter_funcs.py +0 -148
  546. package/ref-monty/crates/monty/test_cases/builtin__next_stop_iteration.py +0 -10
  547. package/ref-monty/crates/monty/test_cases/builtin__print_invalid_kwarg.py +0 -9
  548. package/ref-monty/crates/monty/test_cases/builtin__print_kwargs.py +0 -12
  549. package/ref-monty/crates/monty/test_cases/builtin__repr.py +0 -3
  550. package/ref-monty/crates/monty/test_cases/builtin__string_funcs.py +0 -73
  551. package/ref-monty/crates/monty/test_cases/bytes__decode_invalid_utf8.py +0 -18
  552. package/ref-monty/crates/monty/test_cases/bytes__endswith_str_error.py +0 -10
  553. package/ref-monty/crates/monty/test_cases/bytes__getitem_index_error.py +0 -10
  554. package/ref-monty/crates/monty/test_cases/bytes__index_start_gt_end.py +0 -10
  555. package/ref-monty/crates/monty/test_cases/bytes__methods.py +0 -394
  556. package/ref-monty/crates/monty/test_cases/bytes__negative_count.py +0 -9
  557. package/ref-monty/crates/monty/test_cases/bytes__ops.py +0 -90
  558. package/ref-monty/crates/monty/test_cases/bytes__startswith_str_error.py +0 -10
  559. package/ref-monty/crates/monty/test_cases/call_object.py +0 -3
  560. package/ref-monty/crates/monty/test_cases/chain_comparison__all.py +0 -79
  561. package/ref-monty/crates/monty/test_cases/closure__param_shadows_outer.py +0 -81
  562. package/ref-monty/crates/monty/test_cases/closure__pep448.py +0 -203
  563. package/ref-monty/crates/monty/test_cases/closure__undefined_nonlocal.py +0 -13
  564. package/ref-monty/crates/monty/test_cases/compare__mixed_types.py +0 -120
  565. package/ref-monty/crates/monty/test_cases/comprehension__all.py +0 -208
  566. package/ref-monty/crates/monty/test_cases/comprehension__scope.py +0 -7
  567. package/ref-monty/crates/monty/test_cases/comprehension__unbound_local.py +0 -14
  568. package/ref-monty/crates/monty/test_cases/dataclass__basic.py +0 -238
  569. package/ref-monty/crates/monty/test_cases/dataclass__call_field_error.py +0 -12
  570. package/ref-monty/crates/monty/test_cases/dataclass__frozen_set_error.py +0 -12
  571. package/ref-monty/crates/monty/test_cases/dataclass__get_missing_attr_error.py +0 -11
  572. package/ref-monty/crates/monty/test_cases/dict__get_unhashable_key.py +0 -3
  573. package/ref-monty/crates/monty/test_cases/dict__literal_unhashable_key.py +0 -2
  574. package/ref-monty/crates/monty/test_cases/dict__method_pop_missing_error.py +0 -3
  575. package/ref-monty/crates/monty/test_cases/dict__methods.py +0 -151
  576. package/ref-monty/crates/monty/test_cases/dict__ops.py +0 -133
  577. package/ref-monty/crates/monty/test_cases/dict__pop_unhashable_key.py +0 -4
  578. package/ref-monty/crates/monty/test_cases/dict__popitem_empty.py +0 -9
  579. package/ref-monty/crates/monty/test_cases/dict__subscript_missing_key.py +0 -3
  580. package/ref-monty/crates/monty/test_cases/dict__unhashable_dict_key.py +0 -2
  581. package/ref-monty/crates/monty/test_cases/dict__unhashable_list_key.py +0 -2
  582. package/ref-monty/crates/monty/test_cases/dict__unpack_type_error.py +0 -2
  583. package/ref-monty/crates/monty/test_cases/dict__views.py +0 -165
  584. package/ref-monty/crates/monty/test_cases/edge__all.py +0 -26
  585. package/ref-monty/crates/monty/test_cases/edge__float_int_mod.py +0 -2
  586. package/ref-monty/crates/monty/test_cases/edge__int_float_mod.py +0 -2
  587. package/ref-monty/crates/monty/test_cases/exc__args.py +0 -16
  588. package/ref-monty/crates/monty/test_cases/exc__str.py +0 -15
  589. package/ref-monty/crates/monty/test_cases/execute_ok__all.py +0 -54
  590. package/ref-monty/crates/monty/test_cases/execute_raise__error_instance_str.py +0 -2
  591. package/ref-monty/crates/monty/test_cases/execute_raise__error_no_args.py +0 -2
  592. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg.py +0 -2
  593. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg_quotes.py +0 -2
  594. package/ref-monty/crates/monty/test_cases/execute_raise__error_type.py +0 -2
  595. package/ref-monty/crates/monty/test_cases/execute_raise__raise_instance_via_var.py +0 -4
  596. package/ref-monty/crates/monty/test_cases/execute_raise__raise_list.py +0 -2
  597. package/ref-monty/crates/monty/test_cases/execute_raise__raise_number.py +0 -2
  598. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_call_via_var.py +0 -4
  599. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_direct.py +0 -3
  600. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_via_var.py +0 -4
  601. package/ref-monty/crates/monty/test_cases/ext_call__arg_side_effect_bug.py +0 -22
  602. package/ref-monty/crates/monty/test_cases/ext_call__augmented.py +0 -17
  603. package/ref-monty/crates/monty/test_cases/ext_call__augmented_refcount_bug.py +0 -7
  604. package/ref-monty/crates/monty/test_cases/ext_call__bare_raise_after_resume.py +0 -34
  605. package/ref-monty/crates/monty/test_cases/ext_call__basic.py +0 -99
  606. package/ref-monty/crates/monty/test_cases/ext_call__boolean.py +0 -37
  607. package/ref-monty/crates/monty/test_cases/ext_call__boolean_side_effect_hang.py +0 -17
  608. package/ref-monty/crates/monty/test_cases/ext_call__closure_bug.py +0 -16
  609. package/ref-monty/crates/monty/test_cases/ext_call__comparison.py +0 -26
  610. package/ref-monty/crates/monty/test_cases/ext_call__deep_call_stack.py +0 -18
  611. package/ref-monty/crates/monty/test_cases/ext_call__elif.py +0 -171
  612. package/ref-monty/crates/monty/test_cases/ext_call__exc.py +0 -4
  613. package/ref-monty/crates/monty/test_cases/ext_call__exc_deep_stack.py +0 -39
  614. package/ref-monty/crates/monty/test_cases/ext_call__exc_in_function.py +0 -17
  615. package/ref-monty/crates/monty/test_cases/ext_call__exc_nested_functions.py +0 -31
  616. package/ref-monty/crates/monty/test_cases/ext_call__ext_exc.py +0 -171
  617. package/ref-monty/crates/monty/test_cases/ext_call__for.py +0 -114
  618. package/ref-monty/crates/monty/test_cases/ext_call__fstring.py +0 -12
  619. package/ref-monty/crates/monty/test_cases/ext_call__if.py +0 -135
  620. package/ref-monty/crates/monty/test_cases/ext_call__if_condition.py +0 -37
  621. package/ref-monty/crates/monty/test_cases/ext_call__in_closure.py +0 -14
  622. package/ref-monty/crates/monty/test_cases/ext_call__in_function.py +0 -40
  623. package/ref-monty/crates/monty/test_cases/ext_call__in_function_simple.py +0 -7
  624. package/ref-monty/crates/monty/test_cases/ext_call__literals.py +0 -17
  625. package/ref-monty/crates/monty/test_cases/ext_call__multi_in_func.py +0 -32
  626. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup.py +0 -69
  627. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup_undefined.py +0 -4
  628. package/ref-monty/crates/monty/test_cases/ext_call__nested_calls.py +0 -14
  629. package/ref-monty/crates/monty/test_cases/ext_call__recursion_bug.py +0 -19
  630. package/ref-monty/crates/monty/test_cases/ext_call__return.py +0 -28
  631. package/ref-monty/crates/monty/test_cases/ext_call__side_effects.py +0 -25
  632. package/ref-monty/crates/monty/test_cases/ext_call__subscript.py +0 -7
  633. package/ref-monty/crates/monty/test_cases/ext_call__ternary.py +0 -28
  634. package/ref-monty/crates/monty/test_cases/ext_call__try.py +0 -280
  635. package/ref-monty/crates/monty/test_cases/ext_call__try_simple.py +0 -10
  636. package/ref-monty/crates/monty/test_cases/ext_call__unary.py +0 -13
  637. package/ref-monty/crates/monty/test_cases/frozenset__ops.py +0 -178
  638. package/ref-monty/crates/monty/test_cases/fstring__all.py +0 -236
  639. package/ref-monty/crates/monty/test_cases/fstring__error_eq_align_on_str.py +0 -3
  640. package/ref-monty/crates/monty/test_cases/fstring__error_float_f_on_str.py +0 -3
  641. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_float.py +0 -3
  642. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_str.py +0 -3
  643. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec.py +0 -4
  644. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_dynamic.py +0 -4
  645. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_str.py +0 -4
  646. package/ref-monty/crates/monty/test_cases/fstring__error_str_s_on_int.py +0 -3
  647. package/ref-monty/crates/monty/test_cases/function__call_duplicate_kwargs.py +0 -6
  648. package/ref-monty/crates/monty/test_cases/function__call_unpack.py +0 -42
  649. package/ref-monty/crates/monty/test_cases/function__defaults.py +0 -117
  650. package/ref-monty/crates/monty/test_cases/function__err_duplicate_arg.py +0 -7
  651. package/ref-monty/crates/monty/test_cases/function__err_duplicate_first_arg.py +0 -7
  652. package/ref-monty/crates/monty/test_cases/function__err_duplicate_kwarg_cleanup.py +0 -9
  653. package/ref-monty/crates/monty/test_cases/function__err_kwonly_as_positional.py +0 -7
  654. package/ref-monty/crates/monty/test_cases/function__err_missing_all_posonly.py +0 -7
  655. package/ref-monty/crates/monty/test_cases/function__err_missing_heap_cleanup.py +0 -9
  656. package/ref-monty/crates/monty/test_cases/function__err_missing_kwonly.py +0 -7
  657. package/ref-monty/crates/monty/test_cases/function__err_missing_posonly_with_kwarg.py +0 -7
  658. package/ref-monty/crates/monty/test_cases/function__err_missing_with_posonly.py +0 -7
  659. package/ref-monty/crates/monty/test_cases/function__err_posonly_as_kwarg.py +0 -7
  660. package/ref-monty/crates/monty/test_cases/function__err_posonly_first_as_kwarg.py +0 -7
  661. package/ref-monty/crates/monty/test_cases/function__err_too_many_posonly.py +0 -7
  662. package/ref-monty/crates/monty/test_cases/function__err_too_many_with_kwonly.py +0 -7
  663. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg.py +0 -7
  664. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_cleanup.py +0 -9
  665. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_quote.py +0 -13
  666. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_simple.py +0 -7
  667. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_arg.py +0 -6
  668. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_heap.py +0 -8
  669. package/ref-monty/crates/monty/test_cases/function__err_unpack_int.py +0 -6
  670. package/ref-monty/crates/monty/test_cases/function__err_unpack_nonstring_key.py +0 -6
  671. package/ref-monty/crates/monty/test_cases/function__err_unpack_not_mapping.py +0 -6
  672. package/ref-monty/crates/monty/test_cases/function__kwargs_unpacking.py +0 -173
  673. package/ref-monty/crates/monty/test_cases/function__ops.py +0 -294
  674. package/ref-monty/crates/monty/test_cases/function__return_none.py +0 -42
  675. package/ref-monty/crates/monty/test_cases/function__signatures.py +0 -47
  676. package/ref-monty/crates/monty/test_cases/function__too_few_args_all.py +0 -6
  677. package/ref-monty/crates/monty/test_cases/function__too_few_args_one.py +0 -6
  678. package/ref-monty/crates/monty/test_cases/function__too_few_args_two.py +0 -6
  679. package/ref-monty/crates/monty/test_cases/function__too_many_args_one.py +0 -6
  680. package/ref-monty/crates/monty/test_cases/function__too_many_args_two.py +0 -6
  681. package/ref-monty/crates/monty/test_cases/function__too_many_args_zero.py +0 -6
  682. package/ref-monty/crates/monty/test_cases/global__error_assigned_before.py +0 -7
  683. package/ref-monty/crates/monty/test_cases/global__ops.py +0 -163
  684. package/ref-monty/crates/monty/test_cases/hash__dict_unhashable.py +0 -2
  685. package/ref-monty/crates/monty/test_cases/hash__list_unhashable.py +0 -2
  686. package/ref-monty/crates/monty/test_cases/hash__ops.py +0 -153
  687. package/ref-monty/crates/monty/test_cases/id__bytes_literals_distinct.py +0 -3
  688. package/ref-monty/crates/monty/test_cases/id__int_copy_distinct.py +0 -5
  689. package/ref-monty/crates/monty/test_cases/id__is_number_is_number.py +0 -3
  690. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_distinct_types.py +0 -10
  691. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_same_types.py +0 -6
  692. package/ref-monty/crates/monty/test_cases/id__ops.py +0 -97
  693. package/ref-monty/crates/monty/test_cases/id__str_literals_same.py +0 -3
  694. package/ref-monty/crates/monty/test_cases/if__elif_else.py +0 -207
  695. package/ref-monty/crates/monty/test_cases/if__raise_elif.py +0 -11
  696. package/ref-monty/crates/monty/test_cases/if__raise_else.py +0 -13
  697. package/ref-monty/crates/monty/test_cases/if__raise_if.py +0 -9
  698. package/ref-monty/crates/monty/test_cases/if__raise_in_elif_condition.py +0 -18
  699. package/ref-monty/crates/monty/test_cases/if__raise_in_if_condition.py +0 -16
  700. package/ref-monty/crates/monty/test_cases/if_else_expr__all.py +0 -55
  701. package/ref-monty/crates/monty/test_cases/import__error_cannot_import.py +0 -9
  702. package/ref-monty/crates/monty/test_cases/import__error_module_not_found.py +0 -9
  703. package/ref-monty/crates/monty/test_cases/import__local_scope.py +0 -68
  704. package/ref-monty/crates/monty/test_cases/import__os.py +0 -25
  705. package/ref-monty/crates/monty/test_cases/import__relative_error.py +0 -9
  706. package/ref-monty/crates/monty/test_cases/import__relative_no_module_error.py +0 -9
  707. package/ref-monty/crates/monty/test_cases/import__runtime_error_when_executed.py +0 -14
  708. package/ref-monty/crates/monty/test_cases/import__star_error.py +0 -11
  709. package/ref-monty/crates/monty/test_cases/import__sys.py +0 -47
  710. package/ref-monty/crates/monty/test_cases/import__sys_monty.py +0 -28
  711. package/ref-monty/crates/monty/test_cases/import__type_checking_guard.py +0 -37
  712. package/ref-monty/crates/monty/test_cases/import__typing.py +0 -25
  713. package/ref-monty/crates/monty/test_cases/import__typing_type_ignore.py +0 -4
  714. package/ref-monty/crates/monty/test_cases/int__bigint.py +0 -467
  715. package/ref-monty/crates/monty/test_cases/int__bigint_errors.py +0 -260
  716. package/ref-monty/crates/monty/test_cases/int__ops.py +0 -219
  717. package/ref-monty/crates/monty/test_cases/int__overflow_division.py +0 -84
  718. package/ref-monty/crates/monty/test_cases/is_variant__all.py +0 -36
  719. package/ref-monty/crates/monty/test_cases/isinstance__arg2_list_error.py +0 -2
  720. package/ref-monty/crates/monty/test_cases/isinstance__arg2_type_error.py +0 -2
  721. package/ref-monty/crates/monty/test_cases/iter__dict_mutation.py +0 -4
  722. package/ref-monty/crates/monty/test_cases/iter__for.py +0 -243
  723. package/ref-monty/crates/monty/test_cases/iter__for_loop_unpacking.py +0 -66
  724. package/ref-monty/crates/monty/test_cases/iter__generator_expr.py +0 -20
  725. package/ref-monty/crates/monty/test_cases/iter__generator_expr_type.py +0 -7
  726. package/ref-monty/crates/monty/test_cases/iter__not_iterable.py +0 -3
  727. package/ref-monty/crates/monty/test_cases/lambda__all.py +0 -145
  728. package/ref-monty/crates/monty/test_cases/list__extend_not_iterable.py +0 -7
  729. package/ref-monty/crates/monty/test_cases/list__getitem_out_of_bounds.py +0 -3
  730. package/ref-monty/crates/monty/test_cases/list__index_not_found.py +0 -9
  731. package/ref-monty/crates/monty/test_cases/list__index_start_gt_end.py +0 -10
  732. package/ref-monty/crates/monty/test_cases/list__ops.py +0 -473
  733. package/ref-monty/crates/monty/test_cases/list__pop_empty.py +0 -9
  734. package/ref-monty/crates/monty/test_cases/list__pop_out_of_range.py +0 -9
  735. package/ref-monty/crates/monty/test_cases/list__pop_type_error.py +0 -9
  736. package/ref-monty/crates/monty/test_cases/list__remove_not_found.py +0 -9
  737. package/ref-monty/crates/monty/test_cases/list__setitem_dict_index.py +0 -13
  738. package/ref-monty/crates/monty/test_cases/list__setitem_huge_int_index.py +0 -13
  739. package/ref-monty/crates/monty/test_cases/list__setitem_index_error.py +0 -10
  740. package/ref-monty/crates/monty/test_cases/list__setitem_type_error.py +0 -10
  741. package/ref-monty/crates/monty/test_cases/list__unpack_type_error.py +0 -2
  742. package/ref-monty/crates/monty/test_cases/longint__index_error.py +0 -3
  743. package/ref-monty/crates/monty/test_cases/longint__repeat_error.py +0 -3
  744. package/ref-monty/crates/monty/test_cases/loop__break_continue.py +0 -113
  745. package/ref-monty/crates/monty/test_cases/loop__break_finally.py +0 -69
  746. package/ref-monty/crates/monty/test_cases/loop__break_in_function_error.py +0 -13
  747. package/ref-monty/crates/monty/test_cases/loop__break_in_if_error.py +0 -11
  748. package/ref-monty/crates/monty/test_cases/loop__break_nested_except_clears.py +0 -55
  749. package/ref-monty/crates/monty/test_cases/loop__break_outside_error.py +0 -9
  750. package/ref-monty/crates/monty/test_cases/loop__continue_finally.py +0 -81
  751. package/ref-monty/crates/monty/test_cases/loop__continue_in_function_error.py +0 -13
  752. package/ref-monty/crates/monty/test_cases/loop__continue_in_if_error.py +0 -11
  753. package/ref-monty/crates/monty/test_cases/loop__continue_nested_except_clears.py +0 -60
  754. package/ref-monty/crates/monty/test_cases/loop__continue_outside_error.py +0 -9
  755. package/ref-monty/crates/monty/test_cases/math__acos_domain_error.py +0 -11
  756. package/ref-monty/crates/monty/test_cases/math__acosh_domain_error.py +0 -11
  757. package/ref-monty/crates/monty/test_cases/math__asin_domain_error.py +0 -11
  758. package/ref-monty/crates/monty/test_cases/math__atanh_domain_error.py +0 -11
  759. package/ref-monty/crates/monty/test_cases/math__cos_inf_error.py +0 -11
  760. package/ref-monty/crates/monty/test_cases/math__cosh_overflow_error.py +0 -11
  761. package/ref-monty/crates/monty/test_cases/math__exp_overflow_error.py +0 -11
  762. package/ref-monty/crates/monty/test_cases/math__factorial_float_error.py +0 -11
  763. package/ref-monty/crates/monty/test_cases/math__factorial_negative_error.py +0 -11
  764. package/ref-monty/crates/monty/test_cases/math__floor_inf_error.py +0 -11
  765. package/ref-monty/crates/monty/test_cases/math__floor_nan_error.py +0 -11
  766. package/ref-monty/crates/monty/test_cases/math__floor_str_error.py +0 -11
  767. package/ref-monty/crates/monty/test_cases/math__fmod_inf_error.py +0 -11
  768. package/ref-monty/crates/monty/test_cases/math__gamma_neg_int_error.py +0 -11
  769. package/ref-monty/crates/monty/test_cases/math__gcd_float_error.py +0 -11
  770. package/ref-monty/crates/monty/test_cases/math__isqrt_negative_error.py +0 -11
  771. package/ref-monty/crates/monty/test_cases/math__ldexp_overflow_error.py +0 -11
  772. package/ref-monty/crates/monty/test_cases/math__log1p_domain_error.py +0 -11
  773. package/ref-monty/crates/monty/test_cases/math__log_base1_error.py +0 -11
  774. package/ref-monty/crates/monty/test_cases/math__log_zero_error.py +0 -11
  775. package/ref-monty/crates/monty/test_cases/math__module.py +0 -1432
  776. package/ref-monty/crates/monty/test_cases/math__pow_domain_error.py +0 -11
  777. package/ref-monty/crates/monty/test_cases/math__sin_inf_error.py +0 -11
  778. package/ref-monty/crates/monty/test_cases/math__sqrt_negative_error.py +0 -11
  779. package/ref-monty/crates/monty/test_cases/math__tan_inf_error.py +0 -11
  780. package/ref-monty/crates/monty/test_cases/math__trunc_str_error.py +0 -11
  781. package/ref-monty/crates/monty/test_cases/method__args_kwargs_unpacking.py +0 -259
  782. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_func.py +0 -19
  783. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_module.py +0 -12
  784. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_chained.py +0 -9
  785. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_expr.py +0 -9
  786. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_function.py +0 -16
  787. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_with_args.py +0 -9
  788. package/ref-monty/crates/monty/test_cases/name_error__undefined_global.py +0 -10
  789. package/ref-monty/crates/monty/test_cases/namedtuple__missing_attr.py +0 -11
  790. package/ref-monty/crates/monty/test_cases/namedtuple__ops.py +0 -34
  791. package/ref-monty/crates/monty/test_cases/nonlocal__error_module_level.py +0 -3
  792. package/ref-monty/crates/monty/test_cases/nonlocal__ops.py +0 -353
  793. package/ref-monty/crates/monty/test_cases/os__environ.py +0 -40
  794. package/ref-monty/crates/monty/test_cases/os__getenv_key_list_error.py +0 -5
  795. package/ref-monty/crates/monty/test_cases/os__getenv_key_type_error.py +0 -5
  796. package/ref-monty/crates/monty/test_cases/parse_error__complex.py +0 -3
  797. package/ref-monty/crates/monty/test_cases/pathlib__import.py +0 -11
  798. package/ref-monty/crates/monty/test_cases/pathlib__os.py +0 -136
  799. package/ref-monty/crates/monty/test_cases/pathlib__os_read_error.py +0 -12
  800. package/ref-monty/crates/monty/test_cases/pathlib__pure.py +0 -81
  801. package/ref-monty/crates/monty/test_cases/pyobject__cycle_dict_self.py +0 -5
  802. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_dict.py +0 -6
  803. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_self.py +0 -5
  804. package/ref-monty/crates/monty/test_cases/pyobject__cycle_multiple_refs.py +0 -6
  805. package/ref-monty/crates/monty/test_cases/range__error_no_args.py +0 -2
  806. package/ref-monty/crates/monty/test_cases/range__error_step_zero.py +0 -2
  807. package/ref-monty/crates/monty/test_cases/range__error_too_many_args.py +0 -2
  808. package/ref-monty/crates/monty/test_cases/range__getitem_index_error.py +0 -10
  809. package/ref-monty/crates/monty/test_cases/range__ops.py +0 -236
  810. package/ref-monty/crates/monty/test_cases/re__basic.py +0 -756
  811. package/ref-monty/crates/monty/test_cases/re__grouping.py +0 -241
  812. package/ref-monty/crates/monty/test_cases/re__match.py +0 -148
  813. package/ref-monty/crates/monty/test_cases/recursion__deep_drop.py +0 -26
  814. package/ref-monty/crates/monty/test_cases/recursion__deep_eq.py +0 -23
  815. package/ref-monty/crates/monty/test_cases/recursion__deep_hash.py +0 -46
  816. package/ref-monty/crates/monty/test_cases/recursion__deep_repr.py +0 -12
  817. package/ref-monty/crates/monty/test_cases/recursion__function_depth.py +0 -13
  818. package/ref-monty/crates/monty/test_cases/refcount__cycle_mutual_reference.py +0 -18
  819. package/ref-monty/crates/monty/test_cases/refcount__cycle_self_reference.py +0 -12
  820. package/ref-monty/crates/monty/test_cases/refcount__dict_basic.py +0 -5
  821. package/ref-monty/crates/monty/test_cases/refcount__dict_get.py +0 -5
  822. package/ref-monty/crates/monty/test_cases/refcount__dict_keys_and.py +0 -14
  823. package/ref-monty/crates/monty/test_cases/refcount__dict_overwrite.py +0 -6
  824. package/ref-monty/crates/monty/test_cases/refcount__gather_cleanup.py +0 -16
  825. package/ref-monty/crates/monty/test_cases/refcount__gather_exception.py +0 -18
  826. package/ref-monty/crates/monty/test_cases/refcount__gather_nested_cancel.py +0 -25
  827. package/ref-monty/crates/monty/test_cases/refcount__immediate_skipped.py +0 -4
  828. package/ref-monty/crates/monty/test_cases/refcount__kwargs_unpacking.py +0 -27
  829. package/ref-monty/crates/monty/test_cases/refcount__list_append_multiple.py +0 -6
  830. package/ref-monty/crates/monty/test_cases/refcount__list_append_ref.py +0 -5
  831. package/ref-monty/crates/monty/test_cases/refcount__list_concat.py +0 -5
  832. package/ref-monty/crates/monty/test_cases/refcount__list_getitem.py +0 -5
  833. package/ref-monty/crates/monty/test_cases/refcount__list_iadd.py +0 -5
  834. package/ref-monty/crates/monty/test_cases/refcount__nested_list.py +0 -4
  835. package/ref-monty/crates/monty/test_cases/refcount__re_pattern_sub_error_paths.py +0 -37
  836. package/ref-monty/crates/monty/test_cases/refcount__re_search_match.py +0 -34
  837. package/ref-monty/crates/monty/test_cases/refcount__re_sub_error_paths.py +0 -31
  838. package/ref-monty/crates/monty/test_cases/refcount__shared_reference.py +0 -4
  839. package/ref-monty/crates/monty/test_cases/refcount__single_list.py +0 -3
  840. package/ref-monty/crates/monty/test_cases/repr__cycle_detection.py +0 -24
  841. package/ref-monty/crates/monty/test_cases/set__ops.py +0 -191
  842. package/ref-monty/crates/monty/test_cases/set__review_bugs.py +0 -35
  843. package/ref-monty/crates/monty/test_cases/set__unpack_type_error.py +0 -2
  844. package/ref-monty/crates/monty/test_cases/slice__invalid_indices.py +0 -2
  845. package/ref-monty/crates/monty/test_cases/slice__kwargs.py +0 -9
  846. package/ref-monty/crates/monty/test_cases/slice__no_args.py +0 -9
  847. package/ref-monty/crates/monty/test_cases/slice__ops.py +0 -149
  848. package/ref-monty/crates/monty/test_cases/slice__step_zero.py +0 -9
  849. package/ref-monty/crates/monty/test_cases/slice__step_zero_bytes.py +0 -9
  850. package/ref-monty/crates/monty/test_cases/slice__step_zero_range.py +0 -9
  851. package/ref-monty/crates/monty/test_cases/slice__step_zero_str.py +0 -9
  852. package/ref-monty/crates/monty/test_cases/slice__step_zero_tuple.py +0 -9
  853. package/ref-monty/crates/monty/test_cases/slice__too_many_args.py +0 -9
  854. package/ref-monty/crates/monty/test_cases/str__getitem_index_error.py +0 -10
  855. package/ref-monty/crates/monty/test_cases/str__index_not_found.py +0 -9
  856. package/ref-monty/crates/monty/test_cases/str__join_no_args.py +0 -9
  857. package/ref-monty/crates/monty/test_cases/str__join_non_string.py +0 -9
  858. package/ref-monty/crates/monty/test_cases/str__join_not_iterable.py +0 -9
  859. package/ref-monty/crates/monty/test_cases/str__join_too_many_args.py +0 -9
  860. package/ref-monty/crates/monty/test_cases/str__methods.py +0 -327
  861. package/ref-monty/crates/monty/test_cases/str__ops.py +0 -162
  862. package/ref-monty/crates/monty/test_cases/str__partition_empty.py +0 -9
  863. package/ref-monty/crates/monty/test_cases/str__rsplit_empty_sep.py +0 -9
  864. package/ref-monty/crates/monty/test_cases/str__split_empty_sep.py +0 -9
  865. package/ref-monty/crates/monty/test_cases/sys__types.py +0 -7
  866. package/ref-monty/crates/monty/test_cases/traceback__division_error.py +0 -30
  867. package/ref-monty/crates/monty/test_cases/traceback__index_error.py +0 -17
  868. package/ref-monty/crates/monty/test_cases/traceback__insert_as_int.py +0 -10
  869. package/ref-monty/crates/monty/test_cases/traceback__nested_call.py +0 -29
  870. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_module_scope.py +0 -10
  871. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_unbound.py +0 -24
  872. package/ref-monty/crates/monty/test_cases/traceback__range_as_int.py +0 -9
  873. package/ref-monty/crates/monty/test_cases/traceback__recursion_error.py +0 -23
  874. package/ref-monty/crates/monty/test_cases/traceback__set_mutation.py +0 -11
  875. package/ref-monty/crates/monty/test_cases/traceback__undefined_attr_call.py +0 -16
  876. package/ref-monty/crates/monty/test_cases/traceback__undefined_call.py +0 -16
  877. package/ref-monty/crates/monty/test_cases/traceback__undefined_raise.py +0 -16
  878. package/ref-monty/crates/monty/test_cases/try_except__all.py +0 -472
  879. package/ref-monty/crates/monty/test_cases/try_except__bare_raise_no_context.py +0 -2
  880. package/ref-monty/crates/monty/test_cases/try_except__invalid_type.py +0 -5
  881. package/ref-monty/crates/monty/test_cases/tuple__getitem_out_of_bounds.py +0 -3
  882. package/ref-monty/crates/monty/test_cases/tuple__index_not_found.py +0 -9
  883. package/ref-monty/crates/monty/test_cases/tuple__index_start_gt_end.py +0 -10
  884. package/ref-monty/crates/monty/test_cases/tuple__methods.py +0 -19
  885. package/ref-monty/crates/monty/test_cases/tuple__ops.py +0 -133
  886. package/ref-monty/crates/monty/test_cases/tuple__unpack_type_error.py +0 -2
  887. package/ref-monty/crates/monty/test_cases/type__builtin_attr_error.py +0 -9
  888. package/ref-monty/crates/monty/test_cases/type__bytes_negative.py +0 -2
  889. package/ref-monty/crates/monty/test_cases/type__cell_not_builtin.py +0 -9
  890. package/ref-monty/crates/monty/test_cases/type__exception_attr_error.py +0 -11
  891. package/ref-monty/crates/monty/test_cases/type__float_conversion_error.py +0 -2
  892. package/ref-monty/crates/monty/test_cases/type__float_repr_both_quotes.py +0 -9
  893. package/ref-monty/crates/monty/test_cases/type__float_repr_newline.py +0 -9
  894. package/ref-monty/crates/monty/test_cases/type__float_repr_single_quote.py +0 -9
  895. package/ref-monty/crates/monty/test_cases/type__int_conversion_error.py +0 -2
  896. package/ref-monty/crates/monty/test_cases/type__list_not_iterable.py +0 -2
  897. package/ref-monty/crates/monty/test_cases/type__non_builtin_name_error.py +0 -9
  898. package/ref-monty/crates/monty/test_cases/type__ops.py +0 -200
  899. package/ref-monty/crates/monty/test_cases/type__shadow_exc.py +0 -3
  900. package/ref-monty/crates/monty/test_cases/type__shadow_int.py +0 -9
  901. package/ref-monty/crates/monty/test_cases/type__shadow_len.py +0 -3
  902. package/ref-monty/crates/monty/test_cases/type__tuple_not_iterable.py +0 -2
  903. package/ref-monty/crates/monty/test_cases/type_error__int_add_list.py +0 -2
  904. package/ref-monty/crates/monty/test_cases/type_error__int_div_str.py +0 -2
  905. package/ref-monty/crates/monty/test_cases/type_error__int_floordiv_str.py +0 -2
  906. package/ref-monty/crates/monty/test_cases/type_error__int_iadd_str.py +0 -3
  907. package/ref-monty/crates/monty/test_cases/type_error__int_mod_str.py +0 -2
  908. package/ref-monty/crates/monty/test_cases/type_error__int_pow_str.py +0 -2
  909. package/ref-monty/crates/monty/test_cases/type_error__int_sub_str.py +0 -2
  910. package/ref-monty/crates/monty/test_cases/type_error__list_add_int.py +0 -2
  911. package/ref-monty/crates/monty/test_cases/type_error__list_add_str.py +0 -2
  912. package/ref-monty/crates/monty/test_cases/type_error__list_iadd_int.py +0 -6
  913. package/ref-monty/crates/monty/test_cases/type_error__str_add_int.py +0 -2
  914. package/ref-monty/crates/monty/test_cases/type_error__str_iadd_int.py +0 -3
  915. package/ref-monty/crates/monty/test_cases/type_error__unary_invert_str.py +0 -3
  916. package/ref-monty/crates/monty/test_cases/type_error__unary_minus_str.py +0 -4
  917. package/ref-monty/crates/monty/test_cases/type_error__unary_neg_str.py +0 -3
  918. package/ref-monty/crates/monty/test_cases/type_error__unary_plus_str.py +0 -4
  919. package/ref-monty/crates/monty/test_cases/typing__types.py +0 -24
  920. package/ref-monty/crates/monty/test_cases/unpack__nested.py +0 -48
  921. package/ref-monty/crates/monty/test_cases/unpack__non_sequence.py +0 -9
  922. package/ref-monty/crates/monty/test_cases/unpack__not_enough.py +0 -9
  923. package/ref-monty/crates/monty/test_cases/unpack__ops.py +0 -153
  924. package/ref-monty/crates/monty/test_cases/unpack__star_not_enough.py +0 -9
  925. package/ref-monty/crates/monty/test_cases/unpack__too_many.py +0 -9
  926. package/ref-monty/crates/monty/test_cases/version__cpython.py +0 -4
  927. package/ref-monty/crates/monty/test_cases/walrus__all.py +0 -178
  928. package/ref-monty/crates/monty/test_cases/while__all.py +0 -206
  929. package/ref-monty/crates/monty/tests/asyncio.rs +0 -764
  930. package/ref-monty/crates/monty/tests/binary_serde.rs +0 -185
  931. package/ref-monty/crates/monty/tests/bytecode_limits.rs +0 -248
  932. package/ref-monty/crates/monty/tests/datatest_runner.rs +0 -2029
  933. package/ref-monty/crates/monty/tests/inputs.rs +0 -420
  934. package/ref-monty/crates/monty/tests/json_serde.rs +0 -250
  935. package/ref-monty/crates/monty/tests/main.rs +0 -71
  936. package/ref-monty/crates/monty/tests/math_module.rs +0 -114
  937. package/ref-monty/crates/monty/tests/name_lookup.rs +0 -482
  938. package/ref-monty/crates/monty/tests/os_tests.rs +0 -459
  939. package/ref-monty/crates/monty/tests/parse_errors.rs +0 -441
  940. package/ref-monty/crates/monty/tests/print_writer.rs +0 -238
  941. package/ref-monty/crates/monty/tests/py_object.rs +0 -121
  942. package/ref-monty/crates/monty/tests/regex.rs +0 -90
  943. package/ref-monty/crates/monty/tests/repl.rs +0 -344
  944. package/ref-monty/crates/monty/tests/resource_limits.rs +0 -1826
  945. package/ref-monty/crates/monty/tests/try_from.rs +0 -167
  946. package/ref-monty/crates/monty-cli/Cargo.toml +0 -25
  947. package/ref-monty/crates/monty-cli/src/main.rs +0 -541
  948. package/ref-monty/crates/monty-js/.cargo/config.toml +0 -2
  949. package/ref-monty/crates/monty-js/.prettierignore +0 -8
  950. package/ref-monty/crates/monty-js/Cargo.toml +0 -32
  951. package/ref-monty/crates/monty-js/README.md +0 -207
  952. package/ref-monty/crates/monty-js/__test__/async.spec.ts +0 -350
  953. package/ref-monty/crates/monty-js/__test__/basic.spec.ts +0 -114
  954. package/ref-monty/crates/monty-js/__test__/exceptions.spec.ts +0 -427
  955. package/ref-monty/crates/monty-js/__test__/external.spec.ts +0 -354
  956. package/ref-monty/crates/monty-js/__test__/inputs.spec.ts +0 -143
  957. package/ref-monty/crates/monty-js/__test__/limits.spec.ts +0 -162
  958. package/ref-monty/crates/monty-js/__test__/package.json +0 -3
  959. package/ref-monty/crates/monty-js/__test__/print.spec.ts +0 -229
  960. package/ref-monty/crates/monty-js/__test__/repl.spec.ts +0 -34
  961. package/ref-monty/crates/monty-js/__test__/serialize.spec.ts +0 -205
  962. package/ref-monty/crates/monty-js/__test__/start.spec.ts +0 -443
  963. package/ref-monty/crates/monty-js/__test__/type_check.spec.ts +0 -147
  964. package/ref-monty/crates/monty-js/__test__/types.spec.ts +0 -319
  965. package/ref-monty/crates/monty-js/build.rs +0 -61
  966. package/ref-monty/crates/monty-js/index-header.d.ts +0 -3
  967. package/ref-monty/crates/monty-js/package-lock.json +0 -4694
  968. package/ref-monty/crates/monty-js/package.json +0 -100
  969. package/ref-monty/crates/monty-js/scripts/smoke-test.sh +0 -69
  970. package/ref-monty/crates/monty-js/smoke-test/package.json +0 -17
  971. package/ref-monty/crates/monty-js/smoke-test/test.ts +0 -171
  972. package/ref-monty/crates/monty-js/smoke-test/tsconfig.json +0 -11
  973. package/ref-monty/crates/monty-js/src/convert.rs +0 -648
  974. package/ref-monty/crates/monty-js/src/exceptions.rs +0 -293
  975. package/ref-monty/crates/monty-js/src/lib.rs +0 -41
  976. package/ref-monty/crates/monty-js/src/limits.rs +0 -53
  977. package/ref-monty/crates/monty-js/src/monty_cls.rs +0 -1407
  978. package/ref-monty/crates/monty-js/tsconfig.json +0 -17
  979. package/ref-monty/crates/monty-js/wrapper.ts +0 -701
  980. package/ref-monty/crates/monty-python/Cargo.toml +0 -38
  981. package/ref-monty/crates/monty-python/README.md +0 -134
  982. package/ref-monty/crates/monty-python/build.rs +0 -4
  983. package/ref-monty/crates/monty-python/example.py +0 -40
  984. package/ref-monty/crates/monty-python/exercise.py +0 -46
  985. package/ref-monty/crates/monty-python/pyproject.toml +0 -57
  986. package/ref-monty/crates/monty-python/python/pydantic_monty/__init__.py +0 -281
  987. package/ref-monty/crates/monty-python/python/pydantic_monty/_monty.pyi +0 -677
  988. package/ref-monty/crates/monty-python/python/pydantic_monty/os_access.py +0 -933
  989. package/ref-monty/crates/monty-python/python/pydantic_monty/py.typed +0 -0
  990. package/ref-monty/crates/monty-python/src/convert.rs +0 -273
  991. package/ref-monty/crates/monty-python/src/dataclass.rs +0 -461
  992. package/ref-monty/crates/monty-python/src/exceptions.rs +0 -557
  993. package/ref-monty/crates/monty-python/src/external.rs +0 -165
  994. package/ref-monty/crates/monty-python/src/lib.rs +0 -77
  995. package/ref-monty/crates/monty-python/src/limits.rs +0 -142
  996. package/ref-monty/crates/monty-python/src/monty_cls.rs +0 -1650
  997. package/ref-monty/crates/monty-python/src/repl.rs +0 -470
  998. package/ref-monty/crates/monty-python/src/serialization.rs +0 -761
  999. package/ref-monty/crates/monty-python/tests/test_async.py +0 -1201
  1000. package/ref-monty/crates/monty-python/tests/test_basic.py +0 -66
  1001. package/ref-monty/crates/monty-python/tests/test_dataclasses.py +0 -971
  1002. package/ref-monty/crates/monty-python/tests/test_exceptions.py +0 -361
  1003. package/ref-monty/crates/monty-python/tests/test_external.py +0 -367
  1004. package/ref-monty/crates/monty-python/tests/test_inputs.py +0 -126
  1005. package/ref-monty/crates/monty-python/tests/test_limits.py +0 -257
  1006. package/ref-monty/crates/monty-python/tests/test_os_access.py +0 -1286
  1007. package/ref-monty/crates/monty-python/tests/test_os_access_compat.py +0 -731
  1008. package/ref-monty/crates/monty-python/tests/test_os_access_raw.py +0 -483
  1009. package/ref-monty/crates/monty-python/tests/test_os_calls.py +0 -819
  1010. package/ref-monty/crates/monty-python/tests/test_print.py +0 -208
  1011. package/ref-monty/crates/monty-python/tests/test_re.py +0 -170
  1012. package/ref-monty/crates/monty-python/tests/test_readme_examples.py +0 -20
  1013. package/ref-monty/crates/monty-python/tests/test_repl.py +0 -749
  1014. package/ref-monty/crates/monty-python/tests/test_serialize.py +0 -284
  1015. package/ref-monty/crates/monty-python/tests/test_start.py +0 -346
  1016. package/ref-monty/crates/monty-python/tests/test_threading.py +0 -163
  1017. package/ref-monty/crates/monty-python/tests/test_type_check.py +0 -344
  1018. package/ref-monty/crates/monty-python/tests/test_types.py +0 -553
  1019. package/ref-monty/crates/monty-type-checking/Cargo.toml +0 -32
  1020. package/ref-monty/crates/monty-type-checking/src/db.rs +0 -116
  1021. package/ref-monty/crates/monty-type-checking/src/lib.rs +0 -4
  1022. package/ref-monty/crates/monty-type-checking/src/type_check.rs +0 -280
  1023. package/ref-monty/crates/monty-type-checking/tests/bad_types.py +0 -109
  1024. package/ref-monty/crates/monty-type-checking/tests/bad_types_output.txt +0 -21
  1025. package/ref-monty/crates/monty-type-checking/tests/good_types.py +0 -475
  1026. package/ref-monty/crates/monty-type-checking/tests/main.rs +0 -205
  1027. package/ref-monty/crates/monty-type-checking/tests/reveal_types.py +0 -56
  1028. package/ref-monty/crates/monty-type-checking/tests/reveal_types_output.txt +0 -41
  1029. package/ref-monty/crates/monty-typeshed/Cargo.toml +0 -29
  1030. package/ref-monty/crates/monty-typeshed/README.md +0 -11
  1031. package/ref-monty/crates/monty-typeshed/build.rs +0 -101
  1032. package/ref-monty/crates/monty-typeshed/custom/README.md +0 -1
  1033. package/ref-monty/crates/monty-typeshed/custom/asyncio.pyi +0 -138
  1034. package/ref-monty/crates/monty-typeshed/custom/os.pyi +0 -87
  1035. package/ref-monty/crates/monty-typeshed/custom/sys.pyi +0 -33
  1036. package/ref-monty/crates/monty-typeshed/src/lib.rs +0 -56
  1037. package/ref-monty/crates/monty-typeshed/update.py +0 -321
  1038. package/ref-monty/crates/monty-typeshed/vendor/typeshed/source_commit.txt +0 -1
  1039. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/VERSIONS +0 -20
  1040. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi +0 -105
  1041. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi +0 -394
  1042. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi +0 -138
  1043. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi +0 -1434
  1044. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi +0 -527
  1045. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/abc.pyi +0 -2
  1046. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/dataclasses.pyi +0 -502
  1047. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/enum.pyi +0 -376
  1048. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/math.pyi +0 -149
  1049. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/os.pyi +0 -87
  1050. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/__init__.pyi +0 -395
  1051. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/types.pyi +0 -8
  1052. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/re.pyi +0 -337
  1053. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/sys.pyi +0 -33
  1054. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/types.pyi +0 -741
  1055. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing.pyi +0 -1217
  1056. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing_extensions.pyi +0 -716
  1057. package/ref-monty/docs/usage-guide.md +0 -117
  1058. package/ref-monty/examples/README.md +0 -3
  1059. package/ref-monty/examples/expense_analysis/README.md +0 -3
  1060. package/ref-monty/examples/expense_analysis/data.py +0 -124
  1061. package/ref-monty/examples/expense_analysis/main.py +0 -115
  1062. package/ref-monty/examples/sql_playground/README.md +0 -20
  1063. package/ref-monty/examples/sql_playground/external_functions.py +0 -129
  1064. package/ref-monty/examples/sql_playground/main.py +0 -81
  1065. package/ref-monty/examples/sql_playground/sandbox_code.py +0 -82
  1066. package/ref-monty/examples/sql_playground/type_stubs.pyi +0 -14
  1067. package/ref-monty/examples/web_scraper/README.md +0 -15
  1068. package/ref-monty/examples/web_scraper/browser.py +0 -56
  1069. package/ref-monty/examples/web_scraper/example_code.py +0 -59
  1070. package/ref-monty/examples/web_scraper/external_functions.py +0 -324
  1071. package/ref-monty/examples/web_scraper/main.py +0 -193
  1072. package/ref-monty/examples/web_scraper/sub_agent.py +0 -79
  1073. package/ref-monty/monty-npm.md +0 -235
  1074. package/ref-monty/pyproject.toml +0 -162
  1075. package/ref-monty/scripts/check_imports.py +0 -91
  1076. package/ref-monty/scripts/codecov_diff.py +0 -412
  1077. package/ref-monty/scripts/complete_tests.py +0 -146
  1078. package/ref-monty/scripts/flamegraph_to_text.py +0 -208
  1079. package/ref-monty/scripts/iter_test_methods.py +0 -540
  1080. package/ref-monty/scripts/run_traceback.py +0 -180
  1081. package/ref-monty/scripts/startup_performance.py +0 -130
  1082. package/ref-monty/uv.lock +0 -1779
  1083. package/temp_resend_cli/repo/.github/scripts/pr-title-check.js +0 -34
  1084. package/temp_resend_cli/repo/.github/workflows/ci.yml +0 -67
  1085. package/temp_resend_cli/repo/.github/workflows/post-release.yml +0 -51
  1086. package/temp_resend_cli/repo/.github/workflows/pr-title-check.yml +0 -13
  1087. package/temp_resend_cli/repo/.github/workflows/release.yml +0 -175
  1088. package/temp_resend_cli/repo/.github/workflows/test-install-unix.yml +0 -34
  1089. package/temp_resend_cli/repo/.github/workflows/test-install-windows.yml +0 -48
  1090. package/temp_resend_cli/repo/CHANGELOG.md +0 -31
  1091. package/temp_resend_cli/repo/LICENSE +0 -21
  1092. package/temp_resend_cli/repo/README.md +0 -450
  1093. package/temp_resend_cli/repo/biome.json +0 -36
  1094. package/temp_resend_cli/repo/install.ps1 +0 -141
  1095. package/temp_resend_cli/repo/install.sh +0 -301
  1096. package/temp_resend_cli/repo/package.json +0 -61
  1097. package/temp_resend_cli/repo/pnpm-lock.yaml +0 -2439
  1098. package/temp_resend_cli/repo/renovate.json +0 -4
  1099. package/temp_resend_cli/repo/src/cli.ts +0 -98
  1100. package/temp_resend_cli/repo/src/commands/api-keys/create.ts +0 -114
  1101. package/temp_resend_cli/repo/src/commands/api-keys/delete.ts +0 -47
  1102. package/temp_resend_cli/repo/src/commands/api-keys/index.ts +0 -26
  1103. package/temp_resend_cli/repo/src/commands/api-keys/list.ts +0 -35
  1104. package/temp_resend_cli/repo/src/commands/api-keys/utils.ts +0 -8
  1105. package/temp_resend_cli/repo/src/commands/auth/index.ts +0 -20
  1106. package/temp_resend_cli/repo/src/commands/auth/login.ts +0 -234
  1107. package/temp_resend_cli/repo/src/commands/auth/logout.ts +0 -105
  1108. package/temp_resend_cli/repo/src/commands/broadcasts/create.ts +0 -196
  1109. package/temp_resend_cli/repo/src/commands/broadcasts/delete.ts +0 -46
  1110. package/temp_resend_cli/repo/src/commands/broadcasts/get.ts +0 -59
  1111. package/temp_resend_cli/repo/src/commands/broadcasts/index.ts +0 -43
  1112. package/temp_resend_cli/repo/src/commands/broadcasts/list.ts +0 -60
  1113. package/temp_resend_cli/repo/src/commands/broadcasts/send.ts +0 -56
  1114. package/temp_resend_cli/repo/src/commands/broadcasts/update.ts +0 -95
  1115. package/temp_resend_cli/repo/src/commands/broadcasts/utils.ts +0 -35
  1116. package/temp_resend_cli/repo/src/commands/contact-properties/create.ts +0 -118
  1117. package/temp_resend_cli/repo/src/commands/contact-properties/delete.ts +0 -48
  1118. package/temp_resend_cli/repo/src/commands/contact-properties/get.ts +0 -46
  1119. package/temp_resend_cli/repo/src/commands/contact-properties/index.ts +0 -48
  1120. package/temp_resend_cli/repo/src/commands/contact-properties/list.ts +0 -68
  1121. package/temp_resend_cli/repo/src/commands/contact-properties/update.ts +0 -88
  1122. package/temp_resend_cli/repo/src/commands/contact-properties/utils.ts +0 -17
  1123. package/temp_resend_cli/repo/src/commands/contacts/add-segment.ts +0 -78
  1124. package/temp_resend_cli/repo/src/commands/contacts/create.ts +0 -122
  1125. package/temp_resend_cli/repo/src/commands/contacts/delete.ts +0 -49
  1126. package/temp_resend_cli/repo/src/commands/contacts/get.ts +0 -53
  1127. package/temp_resend_cli/repo/src/commands/contacts/index.ts +0 -58
  1128. package/temp_resend_cli/repo/src/commands/contacts/list.ts +0 -57
  1129. package/temp_resend_cli/repo/src/commands/contacts/remove-segment.ts +0 -48
  1130. package/temp_resend_cli/repo/src/commands/contacts/segments.ts +0 -39
  1131. package/temp_resend_cli/repo/src/commands/contacts/topics.ts +0 -45
  1132. package/temp_resend_cli/repo/src/commands/contacts/update-topics.ts +0 -90
  1133. package/temp_resend_cli/repo/src/commands/contacts/update.ts +0 -77
  1134. package/temp_resend_cli/repo/src/commands/contacts/utils.ts +0 -119
  1135. package/temp_resend_cli/repo/src/commands/doctor.ts +0 -216
  1136. package/temp_resend_cli/repo/src/commands/domains/create.ts +0 -83
  1137. package/temp_resend_cli/repo/src/commands/domains/delete.ts +0 -42
  1138. package/temp_resend_cli/repo/src/commands/domains/get.ts +0 -47
  1139. package/temp_resend_cli/repo/src/commands/domains/index.ts +0 -35
  1140. package/temp_resend_cli/repo/src/commands/domains/list.ts +0 -53
  1141. package/temp_resend_cli/repo/src/commands/domains/update.ts +0 -75
  1142. package/temp_resend_cli/repo/src/commands/domains/utils.ts +0 -44
  1143. package/temp_resend_cli/repo/src/commands/domains/verify.ts +0 -38
  1144. package/temp_resend_cli/repo/src/commands/emails/batch.ts +0 -140
  1145. package/temp_resend_cli/repo/src/commands/emails/get.ts +0 -44
  1146. package/temp_resend_cli/repo/src/commands/emails/index.ts +0 -30
  1147. package/temp_resend_cli/repo/src/commands/emails/list.ts +0 -84
  1148. package/temp_resend_cli/repo/src/commands/emails/receiving/attachment.ts +0 -55
  1149. package/temp_resend_cli/repo/src/commands/emails/receiving/attachments.ts +0 -68
  1150. package/temp_resend_cli/repo/src/commands/emails/receiving/get.ts +0 -58
  1151. package/temp_resend_cli/repo/src/commands/emails/receiving/index.ts +0 -28
  1152. package/temp_resend_cli/repo/src/commands/emails/receiving/list.ts +0 -59
  1153. package/temp_resend_cli/repo/src/commands/emails/receiving/utils.ts +0 -38
  1154. package/temp_resend_cli/repo/src/commands/emails/send.ts +0 -189
  1155. package/temp_resend_cli/repo/src/commands/open.ts +0 -27
  1156. package/temp_resend_cli/repo/src/commands/segments/create.ts +0 -50
  1157. package/temp_resend_cli/repo/src/commands/segments/delete.ts +0 -47
  1158. package/temp_resend_cli/repo/src/commands/segments/get.ts +0 -38
  1159. package/temp_resend_cli/repo/src/commands/segments/index.ts +0 -36
  1160. package/temp_resend_cli/repo/src/commands/segments/list.ts +0 -58
  1161. package/temp_resend_cli/repo/src/commands/segments/utils.ts +0 -7
  1162. package/temp_resend_cli/repo/src/commands/teams/index.ts +0 -10
  1163. package/temp_resend_cli/repo/src/commands/teams/list.ts +0 -35
  1164. package/temp_resend_cli/repo/src/commands/teams/remove.ts +0 -86
  1165. package/temp_resend_cli/repo/src/commands/teams/switch.ts +0 -76
  1166. package/temp_resend_cli/repo/src/commands/topics/create.ts +0 -73
  1167. package/temp_resend_cli/repo/src/commands/topics/delete.ts +0 -47
  1168. package/temp_resend_cli/repo/src/commands/topics/get.ts +0 -42
  1169. package/temp_resend_cli/repo/src/commands/topics/index.ts +0 -42
  1170. package/temp_resend_cli/repo/src/commands/topics/list.ts +0 -34
  1171. package/temp_resend_cli/repo/src/commands/topics/update.ts +0 -59
  1172. package/temp_resend_cli/repo/src/commands/topics/utils.ts +0 -16
  1173. package/temp_resend_cli/repo/src/commands/webhooks/create.ts +0 -128
  1174. package/temp_resend_cli/repo/src/commands/webhooks/delete.ts +0 -49
  1175. package/temp_resend_cli/repo/src/commands/webhooks/get.ts +0 -42
  1176. package/temp_resend_cli/repo/src/commands/webhooks/index.ts +0 -42
  1177. package/temp_resend_cli/repo/src/commands/webhooks/list.ts +0 -55
  1178. package/temp_resend_cli/repo/src/commands/webhooks/listen.ts +0 -379
  1179. package/temp_resend_cli/repo/src/commands/webhooks/update.ts +0 -83
  1180. package/temp_resend_cli/repo/src/commands/webhooks/utils.ts +0 -36
  1181. package/temp_resend_cli/repo/src/commands/whoami.ts +0 -71
  1182. package/temp_resend_cli/repo/src/lib/actions.ts +0 -157
  1183. package/temp_resend_cli/repo/src/lib/client.ts +0 -37
  1184. package/temp_resend_cli/repo/src/lib/config.ts +0 -217
  1185. package/temp_resend_cli/repo/src/lib/files.ts +0 -15
  1186. package/temp_resend_cli/repo/src/lib/help-text.ts +0 -38
  1187. package/temp_resend_cli/repo/src/lib/output.ts +0 -56
  1188. package/temp_resend_cli/repo/src/lib/pagination.ts +0 -36
  1189. package/temp_resend_cli/repo/src/lib/prompts.ts +0 -149
  1190. package/temp_resend_cli/repo/src/lib/spinner.ts +0 -100
  1191. package/temp_resend_cli/repo/src/lib/table.ts +0 -57
  1192. package/temp_resend_cli/repo/src/lib/tty.ts +0 -28
  1193. package/temp_resend_cli/repo/src/lib/update-check.ts +0 -169
  1194. package/temp_resend_cli/repo/src/lib/version.ts +0 -4
  1195. package/temp_resend_cli/repo/tests/commands/api-keys/create.test.ts +0 -196
  1196. package/temp_resend_cli/repo/tests/commands/api-keys/delete.test.ts +0 -157
  1197. package/temp_resend_cli/repo/tests/commands/api-keys/list.test.ts +0 -134
  1198. package/temp_resend_cli/repo/tests/commands/auth/login.test.ts +0 -153
  1199. package/temp_resend_cli/repo/tests/commands/auth/logout.test.ts +0 -153
  1200. package/temp_resend_cli/repo/tests/commands/broadcasts/create.test.ts +0 -454
  1201. package/temp_resend_cli/repo/tests/commands/broadcasts/delete.test.ts +0 -183
  1202. package/temp_resend_cli/repo/tests/commands/broadcasts/get.test.ts +0 -147
  1203. package/temp_resend_cli/repo/tests/commands/broadcasts/list.test.ts +0 -199
  1204. package/temp_resend_cli/repo/tests/commands/broadcasts/send.test.ts +0 -162
  1205. package/temp_resend_cli/repo/tests/commands/broadcasts/update.test.ts +0 -288
  1206. package/temp_resend_cli/repo/tests/commands/contact-properties/create.test.ts +0 -251
  1207. package/temp_resend_cli/repo/tests/commands/contact-properties/delete.test.ts +0 -184
  1208. package/temp_resend_cli/repo/tests/commands/contact-properties/get.test.ts +0 -145
  1209. package/temp_resend_cli/repo/tests/commands/contact-properties/list.test.ts +0 -181
  1210. package/temp_resend_cli/repo/tests/commands/contact-properties/update.test.ts +0 -217
  1211. package/temp_resend_cli/repo/tests/commands/contacts/add-segment.test.ts +0 -189
  1212. package/temp_resend_cli/repo/tests/commands/contacts/create.test.ts +0 -271
  1213. package/temp_resend_cli/repo/tests/commands/contacts/delete.test.ts +0 -193
  1214. package/temp_resend_cli/repo/tests/commands/contacts/get.test.ts +0 -149
  1215. package/temp_resend_cli/repo/tests/commands/contacts/list.test.ts +0 -176
  1216. package/temp_resend_cli/repo/tests/commands/contacts/remove-segment.test.ts +0 -167
  1217. package/temp_resend_cli/repo/tests/commands/contacts/segments.test.ts +0 -168
  1218. package/temp_resend_cli/repo/tests/commands/contacts/topics.test.ts +0 -164
  1219. package/temp_resend_cli/repo/tests/commands/contacts/update-topics.test.ts +0 -248
  1220. package/temp_resend_cli/repo/tests/commands/contacts/update.test.ts +0 -206
  1221. package/temp_resend_cli/repo/tests/commands/doctor.test.ts +0 -164
  1222. package/temp_resend_cli/repo/tests/commands/domains/create.test.ts +0 -193
  1223. package/temp_resend_cli/repo/tests/commands/domains/delete.test.ts +0 -157
  1224. package/temp_resend_cli/repo/tests/commands/domains/get.test.ts +0 -138
  1225. package/temp_resend_cli/repo/tests/commands/domains/list.test.ts +0 -165
  1226. package/temp_resend_cli/repo/tests/commands/domains/update.test.ts +0 -224
  1227. package/temp_resend_cli/repo/tests/commands/domains/verify.test.ts +0 -118
  1228. package/temp_resend_cli/repo/tests/commands/emails/batch.test.ts +0 -324
  1229. package/temp_resend_cli/repo/tests/commands/emails/get.test.ts +0 -132
  1230. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachment.test.ts +0 -141
  1231. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachments.test.ts +0 -169
  1232. package/temp_resend_cli/repo/tests/commands/emails/receiving/get.test.ts +0 -141
  1233. package/temp_resend_cli/repo/tests/commands/emails/receiving/list.test.ts +0 -182
  1234. package/temp_resend_cli/repo/tests/commands/emails/send.test.ts +0 -312
  1235. package/temp_resend_cli/repo/tests/commands/segments/create.test.ts +0 -164
  1236. package/temp_resend_cli/repo/tests/commands/segments/delete.test.ts +0 -183
  1237. package/temp_resend_cli/repo/tests/commands/segments/get.test.ts +0 -138
  1238. package/temp_resend_cli/repo/tests/commands/segments/list.test.ts +0 -174
  1239. package/temp_resend_cli/repo/tests/commands/teams/list.test.ts +0 -62
  1240. package/temp_resend_cli/repo/tests/commands/teams/remove.test.ts +0 -110
  1241. package/temp_resend_cli/repo/tests/commands/teams/switch.test.ts +0 -103
  1242. package/temp_resend_cli/repo/tests/commands/topics/create.test.ts +0 -192
  1243. package/temp_resend_cli/repo/tests/commands/topics/delete.test.ts +0 -157
  1244. package/temp_resend_cli/repo/tests/commands/topics/get.test.ts +0 -126
  1245. package/temp_resend_cli/repo/tests/commands/topics/list.test.ts +0 -125
  1246. package/temp_resend_cli/repo/tests/commands/topics/update.test.ts +0 -178
  1247. package/temp_resend_cli/repo/tests/commands/webhooks/create.test.ts +0 -225
  1248. package/temp_resend_cli/repo/tests/commands/webhooks/delete.test.ts +0 -157
  1249. package/temp_resend_cli/repo/tests/commands/webhooks/get.test.ts +0 -126
  1250. package/temp_resend_cli/repo/tests/commands/webhooks/list.test.ts +0 -178
  1251. package/temp_resend_cli/repo/tests/commands/webhooks/update.test.ts +0 -207
  1252. package/temp_resend_cli/repo/tests/commands/whoami.test.ts +0 -98
  1253. package/temp_resend_cli/repo/tests/e2e/smoke.test.ts +0 -93
  1254. package/temp_resend_cli/repo/tests/helpers.ts +0 -86
  1255. package/temp_resend_cli/repo/tests/lib/client.test.ts +0 -71
  1256. package/temp_resend_cli/repo/tests/lib/config.test.ts +0 -451
  1257. package/temp_resend_cli/repo/tests/lib/files.test.ts +0 -73
  1258. package/temp_resend_cli/repo/tests/lib/help-text.test.ts +0 -97
  1259. package/temp_resend_cli/repo/tests/lib/output.test.ts +0 -136
  1260. package/temp_resend_cli/repo/tests/lib/prompts.test.ts +0 -185
  1261. package/temp_resend_cli/repo/tests/lib/spinner.test.ts +0 -166
  1262. package/temp_resend_cli/repo/tests/lib/table.test.ts +0 -63
  1263. package/temp_resend_cli/repo/tests/lib/tty.test.ts +0 -89
  1264. package/temp_resend_cli/repo/tests/lib/update-check.test.ts +0 -179
  1265. package/temp_resend_cli/repo/tsconfig.json +0 -14
  1266. package/temp_resend_cli/repo/vitest.config.e2e.ts +0 -8
  1267. package/temp_resend_cli/repo/vitest.config.ts +0 -10
  1268. /package/docs/{plugin-examples.md → plugins-examples.md} +0 -0
@@ -1,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
- }