@greenpandastudios/aug-cli 0.19.0

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 (414) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/THIRD_PARTY_NOTICES.md +18 -0
  4. package/bin/aug.mjs +3 -0
  5. package/docs/api/crypto.md +351 -0
  6. package/docs/api/io.md +207 -0
  7. package/docs/api/json.md +21 -0
  8. package/docs/api/memory.md +109 -0
  9. package/docs/api/time.md +54 -0
  10. package/docs/api/web.md +184 -0
  11. package/docs/assets/benchmarks/execution.svg +2978 -0
  12. package/docs/assets/benchmarks/http.svg +1674 -0
  13. package/docs/assets/benchmarks/improvements.svg +2315 -0
  14. package/docs/assets/benchmarks/memory.svg +1891 -0
  15. package/docs/benchmark-baseline.json +1087 -0
  16. package/docs/benchmark-results.json +91123 -0
  17. package/docs/benchmarks.json +38 -0
  18. package/docs/compatibility.md +42 -0
  19. package/docs/concurrency-implementation.md +18 -0
  20. package/docs/diagnostics.md +97 -0
  21. package/docs/docker.md +35 -0
  22. package/docs/example-projects.json +26 -0
  23. package/docs/examples/approved-design/counters.md +253 -0
  24. package/docs/examples/approved-design/dependencies/august/0.19.0/io/contracts.md +395 -0
  25. package/docs/examples/approved-design/domain/app.md +165 -0
  26. package/docs/examples/approved-design/domain/export.md +83 -0
  27. package/docs/examples/approved-design/domain/models.md +80 -0
  28. package/docs/examples/approved-design/domain/numbers.md +248 -0
  29. package/docs/examples/approved-design/index.md +39 -0
  30. package/docs/examples/approved-design/main-yaml.md +24 -0
  31. package/docs/examples/approved-design/main.md +215 -0
  32. package/docs/examples/benchmark/index.md +33 -0
  33. package/docs/examples/benchmark/main-yaml.md +17 -0
  34. package/docs/examples/benchmark/main.md +117 -0
  35. package/docs/examples/cli-args/index.md +32 -0
  36. package/docs/examples/cli-args/main.md +107 -0
  37. package/docs/examples/collections/index.md +32 -0
  38. package/docs/examples/collections/main.md +118 -0
  39. package/docs/examples/collections-benchmark/index.md +34 -0
  40. package/docs/examples/collections-benchmark/main.md +115 -0
  41. package/docs/examples/cpu-benchmark/index.md +34 -0
  42. package/docs/examples/cpu-benchmark/main.md +90 -0
  43. package/docs/examples/developer-workflow/calculator.md +357 -0
  44. package/docs/examples/developer-workflow/dependencies/august/0.19.0/io/contracts.md +395 -0
  45. package/docs/examples/developer-workflow/index.md +37 -0
  46. package/docs/examples/developer-workflow/logging/console.md +124 -0
  47. package/docs/examples/developer-workflow/logging/export.md +70 -0
  48. package/docs/examples/developer-workflow/logging/logger.md +111 -0
  49. package/docs/examples/developer-workflow/main.md +172 -0
  50. package/docs/examples/drop/index.md +33 -0
  51. package/docs/examples/drop/main.md +85 -0
  52. package/docs/examples/drop/resource.md +95 -0
  53. package/docs/examples/errors/errors.md +85 -0
  54. package/docs/examples/errors/index.md +33 -0
  55. package/docs/examples/errors/main.md +92 -0
  56. package/docs/examples/ffi/index.md +33 -0
  57. package/docs/examples/ffi/main.md +75 -0
  58. package/docs/examples/ffi/native.md +93 -0
  59. package/docs/examples/generic-di/dependencies/august/0.19.0/io/contracts.md +395 -0
  60. package/docs/examples/generic-di/index.md +33 -0
  61. package/docs/examples/generic-di/main.md +111 -0
  62. package/docs/examples/generic-di/types.md +180 -0
  63. package/docs/examples/generics/index.md +33 -0
  64. package/docs/examples/generics/main.md +120 -0
  65. package/docs/examples/generics/types.md +189 -0
  66. package/docs/examples/hello/app/export.md +67 -0
  67. package/docs/examples/hello/app/greeter.md +190 -0
  68. package/docs/examples/hello/dependencies/august/0.19.0/io/contracts.md +395 -0
  69. package/docs/examples/hello/index.md +37 -0
  70. package/docs/examples/hello/logging/console.md +121 -0
  71. package/docs/examples/hello/logging/export.md +71 -0
  72. package/docs/examples/hello/logging/logger.md +120 -0
  73. package/docs/examples/hello/main.md +115 -0
  74. package/docs/examples/http-benchmark/index.md +35 -0
  75. package/docs/examples/http-benchmark/main.md +79 -0
  76. package/docs/examples/http-benchmark/routes.md +88 -0
  77. package/docs/examples/index.md +60 -0
  78. package/docs/examples/interceptors/app.md +250 -0
  79. package/docs/examples/interceptors/dependencies/august/0.19.0/io/contracts.md +395 -0
  80. package/docs/examples/interceptors/index.md +35 -0
  81. package/docs/examples/interceptors/interceptors.md +284 -0
  82. package/docs/examples/interceptors/logging.md +155 -0
  83. package/docs/examples/interceptors/main.md +162 -0
  84. package/docs/examples/json-benchmark/data.md +71 -0
  85. package/docs/examples/json-benchmark/dependencies/august/0.19.0/json/contracts.md +103 -0
  86. package/docs/examples/json-benchmark/index.md +35 -0
  87. package/docs/examples/json-benchmark/main.md +131 -0
  88. package/docs/examples/new-syntax/console.md +118 -0
  89. package/docs/examples/new-syntax/dependencies/august/0.19.0/io/contracts.md +395 -0
  90. package/docs/examples/new-syntax/greeter.md +145 -0
  91. package/docs/examples/new-syntax/index.md +36 -0
  92. package/docs/examples/new-syntax/logger.md +111 -0
  93. package/docs/examples/new-syntax/main.md +135 -0
  94. package/docs/examples/new-syntax/math.md +79 -0
  95. package/docs/examples/oidc-login/client/contracts.md +151 -0
  96. package/docs/examples/oidc-login/client/endpoints.md +263 -0
  97. package/docs/examples/oidc-login/client/export.md +107 -0
  98. package/docs/examples/oidc-login/client/login.md +515 -0
  99. package/docs/examples/oidc-login/client/logout.md +249 -0
  100. package/docs/examples/oidc-login/client/protocol.md +595 -0
  101. package/docs/examples/oidc-login/client/session.md +297 -0
  102. package/docs/examples/oidc-login/client/views.md +144 -0
  103. package/docs/examples/oidc-login/common/export.md +115 -0
  104. package/docs/examples/oidc-login/common/headers.md +162 -0
  105. package/docs/examples/oidc-login/common/keys.md +336 -0
  106. package/docs/examples/oidc-login/common/settings.md +116 -0
  107. package/docs/examples/oidc-login/common/views.md +103 -0
  108. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/contracts.md +925 -0
  109. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/jose.md +434 -0
  110. package/docs/examples/oidc-login/dependencies/august/0.19.0/json/contracts.md +103 -0
  111. package/docs/examples/oidc-login/dependencies/august/0.19.0/memory/store.md +374 -0
  112. package/docs/examples/oidc-login/dependencies/august/0.19.0/time/contracts.md +150 -0
  113. package/docs/examples/oidc-login/dependencies/august/0.19.0/web/contracts.md +532 -0
  114. package/docs/examples/oidc-login/index.md +57 -0
  115. package/docs/examples/oidc-login/main-yaml.md +28 -0
  116. package/docs/examples/oidc-login/main.md +283 -0
  117. package/docs/examples/oidc-login/provider/authorization.md +457 -0
  118. package/docs/examples/oidc-login/provider/contracts.md +267 -0
  119. package/docs/examples/oidc-login/provider/credentials.md +148 -0
  120. package/docs/examples/oidc-login/provider/discovery.md +215 -0
  121. package/docs/examples/oidc-login/provider/export.md +131 -0
  122. package/docs/examples/oidc-login/provider/token.md +364 -0
  123. package/docs/examples/oidc-login/provider/userinfo.md +228 -0
  124. package/docs/examples/oidc-login/provider/views.md +137 -0
  125. package/docs/examples/ownership/counter.md +140 -0
  126. package/docs/examples/ownership/index.md +33 -0
  127. package/docs/examples/ownership/main.md +90 -0
  128. package/docs/examples/ownership-transfer/dependencies/august/0.19.0/io/contracts.md +395 -0
  129. package/docs/examples/ownership-transfer/index.md +33 -0
  130. package/docs/examples/ownership-transfer/main.md +125 -0
  131. package/docs/examples/ownership-transfer/resource.md +150 -0
  132. package/docs/examples/packages-app/dependencies/packages/@example/aug-math/0.1.0/arithmetic.md +117 -0
  133. package/docs/examples/packages-app/index.md +34 -0
  134. package/docs/examples/packages-app/main-yaml.md +18 -0
  135. package/docs/examples/packages-app/main.md +80 -0
  136. package/docs/examples/packages-math/aug-package-json.md +24 -0
  137. package/docs/examples/packages-math/index.md +36 -0
  138. package/docs/examples/packages-math/package-json.md +25 -0
  139. package/docs/examples/packages-math/src/arithmetic.md +121 -0
  140. package/docs/examples/packages-math/src/export.md +63 -0
  141. package/docs/examples/startup-benchmark/index.md +34 -0
  142. package/docs/examples/startup-benchmark/main.md +68 -0
  143. package/docs/examples/visibility/counter.md +142 -0
  144. package/docs/examples/visibility/index.md +33 -0
  145. package/docs/examples/visibility/main.md +96 -0
  146. package/docs/examples.json +47 -0
  147. package/docs/getting-started.md +5 -0
  148. package/docs/grammar.md +136 -0
  149. package/docs/implementation-map.md +106 -0
  150. package/docs/index.md +46 -0
  151. package/docs/language-conformance.md +30 -0
  152. package/docs/language-constructs.md +1461 -0
  153. package/docs/language-design-audit.md +147 -0
  154. package/docs/maintaining-docs.md +43 -0
  155. package/docs/packages.md +184 -0
  156. package/docs/performance.md +535 -0
  157. package/docs/production-readiness.md +39 -0
  158. package/docs/reference.md +361 -0
  159. package/docs/release-review.md +23 -0
  160. package/docs/releasing.md +79 -0
  161. package/docs/roadmap.md +13 -0
  162. package/docs/specifications.md +86 -0
  163. package/docs/testing.md +120 -0
  164. package/docs/tooling.md +197 -0
  165. package/docs/web-implementation-plan.md +39 -0
  166. package/docs/web-library-gaps.md +27 -0
  167. package/docs/web.md +197 -0
  168. package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  169. package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  170. package/examples/approved-design/.aug-spec/manifest.json +14 -0
  171. package/examples/approved-design/counters.aug +22 -0
  172. package/examples/approved-design/counters.aug.md +177 -0
  173. package/examples/approved-design/domain/app.aug +12 -0
  174. package/examples/approved-design/domain/app.aug.md +97 -0
  175. package/examples/approved-design/domain/export.aug +5 -0
  176. package/examples/approved-design/domain/export.aug.md +25 -0
  177. package/examples/approved-design/domain/models.aug +2 -0
  178. package/examples/approved-design/domain/models.aug.md +30 -0
  179. package/examples/approved-design/domain/numbers.aug +29 -0
  180. package/examples/approved-design/domain/numbers.aug.md +141 -0
  181. package/examples/approved-design/main.aug +26 -0
  182. package/examples/approved-design/main.aug.md +108 -0
  183. package/examples/approved-design/main.yaml +8 -0
  184. package/examples/benchmark/.aug-spec/manifest.json +7 -0
  185. package/examples/benchmark/main.aug +17 -0
  186. package/examples/benchmark/main.aug.md +43 -0
  187. package/examples/benchmark/main.yaml +1 -0
  188. package/examples/cli-args/.aug-spec/manifest.json +7 -0
  189. package/examples/cli-args/main.aug +15 -0
  190. package/examples/cli-args/main.aug.md +38 -0
  191. package/examples/collections/.aug-spec/manifest.json +7 -0
  192. package/examples/collections/main.aug +18 -0
  193. package/examples/collections/main.aug.md +43 -0
  194. package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  195. package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  196. package/examples/developer-workflow/.aug-spec/manifest.json +13 -0
  197. package/examples/developer-workflow/calculator.aug +55 -0
  198. package/examples/developer-workflow/calculator.aug.md +228 -0
  199. package/examples/developer-workflow/logging/console.aug +8 -0
  200. package/examples/developer-workflow/logging/console.aug.md +67 -0
  201. package/examples/developer-workflow/logging/export.aug +2 -0
  202. package/examples/developer-workflow/logging/export.aug.md +19 -0
  203. package/examples/developer-workflow/logging/logger.aug +6 -0
  204. package/examples/developer-workflow/logging/logger.aug.md +57 -0
  205. package/examples/developer-workflow/main.aug +25 -0
  206. package/examples/developer-workflow/main.aug.md +79 -0
  207. package/examples/drop/.aug-spec/manifest.json +8 -0
  208. package/examples/drop/main.aug +3 -0
  209. package/examples/drop/main.aug.md +35 -0
  210. package/examples/drop/resource.aug +8 -0
  211. package/examples/drop/resource.aug.md +44 -0
  212. package/examples/errors/.aug-spec/manifest.json +8 -0
  213. package/examples/errors/errors.aug +6 -0
  214. package/examples/errors/errors.aug.md +33 -0
  215. package/examples/errors/main.aug +7 -0
  216. package/examples/errors/main.aug.md +36 -0
  217. package/examples/ffi/.aug-spec/manifest.json +8 -0
  218. package/examples/ffi/main.aug +2 -0
  219. package/examples/ffi/main.aug.md +27 -0
  220. package/examples/ffi/native.aug +6 -0
  221. package/examples/ffi/native.aug.md +43 -0
  222. package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  223. package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  224. package/examples/generic-di/.aug-spec/manifest.json +10 -0
  225. package/examples/generic-di/main.aug +9 -0
  226. package/examples/generic-di/main.aug.md +49 -0
  227. package/examples/generic-di/types.aug +17 -0
  228. package/examples/generic-di/types.aug.md +124 -0
  229. package/examples/generics/.aug-spec/manifest.json +8 -0
  230. package/examples/generics/main.aug +9 -0
  231. package/examples/generics/main.aug.md +58 -0
  232. package/examples/generics/types.aug +19 -0
  233. package/examples/generics/types.aug.md +132 -0
  234. package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  235. package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  236. package/examples/hello/.aug-spec/manifest.json +14 -0
  237. package/examples/hello/app/export.aug +1 -0
  238. package/examples/hello/app/export.aug.md +17 -0
  239. package/examples/hello/app/greeter.aug +22 -0
  240. package/examples/hello/app/greeter.aug.md +109 -0
  241. package/examples/hello/logging/console.aug +7 -0
  242. package/examples/hello/logging/console.aug.md +65 -0
  243. package/examples/hello/logging/export.aug +2 -0
  244. package/examples/hello/logging/export.aug.md +19 -0
  245. package/examples/hello/logging/logger.aug +9 -0
  246. package/examples/hello/logging/logger.aug.md +59 -0
  247. package/examples/hello/main.aug +9 -0
  248. package/examples/hello/main.aug.md +49 -0
  249. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  250. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  251. package/examples/interceptors/.aug-spec/manifest.json +12 -0
  252. package/examples/interceptors/app.aug +28 -0
  253. package/examples/interceptors/app.aug.md +162 -0
  254. package/examples/interceptors/interceptors.aug +40 -0
  255. package/examples/interceptors/interceptors.aug.md +180 -0
  256. package/examples/interceptors/logging.aug +12 -0
  257. package/examples/interceptors/logging.aug.md +96 -0
  258. package/examples/interceptors/main.aug +22 -0
  259. package/examples/interceptors/main.aug.md +76 -0
  260. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  261. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  262. package/examples/new-syntax/.aug-spec/manifest.json +13 -0
  263. package/examples/new-syntax/console.aug +7 -0
  264. package/examples/new-syntax/console.aug.md +63 -0
  265. package/examples/new-syntax/greeter.aug +10 -0
  266. package/examples/new-syntax/greeter.aug.md +89 -0
  267. package/examples/new-syntax/logger.aug +6 -0
  268. package/examples/new-syntax/logger.aug.md +57 -0
  269. package/examples/new-syntax/main.aug +12 -0
  270. package/examples/new-syntax/main.aug.md +64 -0
  271. package/examples/new-syntax/math.aug +3 -0
  272. package/examples/new-syntax/math.aug.md +29 -0
  273. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug +73 -0
  274. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug.md +791 -0
  275. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug +68 -0
  276. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug.md +266 -0
  277. package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug +6 -0
  278. package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug.md +55 -0
  279. package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug +45 -0
  280. package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug.md +250 -0
  281. package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug +11 -0
  282. package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug.md +96 -0
  283. package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug +58 -0
  284. package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug.md +420 -0
  285. package/examples/oidc-login/.aug-spec/manifest.json +40 -0
  286. package/examples/oidc-login/README.md +29 -0
  287. package/examples/oidc-login/client/contracts.aug +7 -0
  288. package/examples/oidc-login/client/contracts.aug.md +80 -0
  289. package/examples/oidc-login/client/endpoints.aug +21 -0
  290. package/examples/oidc-login/client/endpoints.aug.md +161 -0
  291. package/examples/oidc-login/client/export.aug +7 -0
  292. package/examples/oidc-login/client/export.aug.md +29 -0
  293. package/examples/oidc-login/client/login.aug +58 -0
  294. package/examples/oidc-login/client/login.aug.md +331 -0
  295. package/examples/oidc-login/client/logout.aug +18 -0
  296. package/examples/oidc-login/client/logout.aug.md +150 -0
  297. package/examples/oidc-login/client/protocol.aug +106 -0
  298. package/examples/oidc-login/client/protocol.aug.md +326 -0
  299. package/examples/oidc-login/client/session.aug +34 -0
  300. package/examples/oidc-login/client/session.aug.md +155 -0
  301. package/examples/oidc-login/client/views.aug +21 -0
  302. package/examples/oidc-login/client/views.aug.md +68 -0
  303. package/examples/oidc-login/common/export.aug +9 -0
  304. package/examples/oidc-login/common/export.aug.md +33 -0
  305. package/examples/oidc-login/common/headers.aug +11 -0
  306. package/examples/oidc-login/common/headers.aug.md +79 -0
  307. package/examples/oidc-login/common/keys.aug +37 -0
  308. package/examples/oidc-login/common/keys.aug.md +207 -0
  309. package/examples/oidc-login/common/settings.aug +4 -0
  310. package/examples/oidc-login/common/settings.aug.md +47 -0
  311. package/examples/oidc-login/common/views.aug +16 -0
  312. package/examples/oidc-login/common/views.aug.md +34 -0
  313. package/examples/oidc-login/main.aug +39 -0
  314. package/examples/oidc-login/main.aug.md +166 -0
  315. package/examples/oidc-login/main.yaml +12 -0
  316. package/examples/oidc-login/provider/authorization.aug +59 -0
  317. package/examples/oidc-login/provider/authorization.aug.md +264 -0
  318. package/examples/oidc-login/provider/contracts.aug +15 -0
  319. package/examples/oidc-login/provider/contracts.aug.md +193 -0
  320. package/examples/oidc-login/provider/credentials.aug +10 -0
  321. package/examples/oidc-login/provider/credentials.aug.md +64 -0
  322. package/examples/oidc-login/provider/discovery.aug +13 -0
  323. package/examples/oidc-login/provider/discovery.aug.md +133 -0
  324. package/examples/oidc-login/provider/export.aug +13 -0
  325. package/examples/oidc-login/provider/export.aug.md +41 -0
  326. package/examples/oidc-login/provider/token.aug +37 -0
  327. package/examples/oidc-login/provider/token.aug.md +223 -0
  328. package/examples/oidc-login/provider/userinfo.aug +26 -0
  329. package/examples/oidc-login/provider/userinfo.aug.md +104 -0
  330. package/examples/oidc-login/provider/views.aug +18 -0
  331. package/examples/oidc-login/provider/views.aug.md +63 -0
  332. package/examples/ownership/.aug-spec/manifest.json +8 -0
  333. package/examples/ownership/counter.aug +14 -0
  334. package/examples/ownership/counter.aug.md +85 -0
  335. package/examples/ownership/main.aug +4 -0
  336. package/examples/ownership/main.aug.md +38 -0
  337. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug +36 -0
  338. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug.md +316 -0
  339. package/examples/ownership-transfer/.aug-spec/manifest.json +10 -0
  340. package/examples/ownership-transfer/main.aug +9 -0
  341. package/examples/ownership-transfer/main.aug.md +63 -0
  342. package/examples/ownership-transfer/resource.aug +16 -0
  343. package/examples/ownership-transfer/resource.aug.md +89 -0
  344. package/examples/packages/README.md +15 -0
  345. package/examples/packages/app/.aug-spec/manifest.json +9 -0
  346. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug +9 -0
  347. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug.md +63 -0
  348. package/examples/packages/app/main.aug +2 -0
  349. package/examples/packages/app/main.aug.md +33 -0
  350. package/examples/packages/app/main.yaml +2 -0
  351. package/examples/packages/math/.aug-spec/manifest.json +8 -0
  352. package/examples/packages/math/README.md +3 -0
  353. package/examples/packages/math/aug-package.json +8 -0
  354. package/examples/packages/math/package.json +9 -0
  355. package/examples/packages/math/src/arithmetic.aug +8 -0
  356. package/examples/packages/math/src/arithmetic.aug.md +63 -0
  357. package/examples/packages/math/src/export.aug +1 -0
  358. package/examples/packages/math/src/export.aug.md +17 -0
  359. package/examples/visibility/.aug-spec/manifest.json +8 -0
  360. package/examples/visibility/counter.aug +14 -0
  361. package/examples/visibility/counter.aug.md +87 -0
  362. package/examples/visibility/main.aug +7 -0
  363. package/examples/visibility/main.aug.md +39 -0
  364. package/package.json +50 -0
  365. package/runtime/aug_crypto.c +121 -0
  366. package/runtime/aug_html.c +93 -0
  367. package/runtime/aug_http.c +829 -0
  368. package/runtime/aug_json.c +165 -0
  369. package/runtime/aug_runtime.c +792 -0
  370. package/runtime/aug_runtime.h +245 -0
  371. package/runtime/aug_tasks.c +172 -0
  372. package/runtime/aug_time.c +5 -0
  373. package/runtime/aug_values.c +80 -0
  374. package/scripts/bootstrap-native.mjs +121 -0
  375. package/scripts/native-dependencies.lock.json +65 -0
  376. package/scripts/native-home.mjs +11 -0
  377. package/src/actions.js +109 -0
  378. package/src/ast.js +19 -0
  379. package/src/builtins.js +93 -0
  380. package/src/checker.js +2896 -0
  381. package/src/cli.js +344 -0
  382. package/src/codegen.js +1159 -0
  383. package/src/config.js +149 -0
  384. package/src/continuation.js +110 -0
  385. package/src/di.js +24 -0
  386. package/src/documentation.js +27 -0
  387. package/src/editor.js +782 -0
  388. package/src/effects.js +29 -0
  389. package/src/fixes.js +222 -0
  390. package/src/formatter.js +296 -0
  391. package/src/freshness.js +154 -0
  392. package/src/help.js +212 -0
  393. package/src/html.js +27 -0
  394. package/src/http-policies.js +90 -0
  395. package/src/inference.js +16 -0
  396. package/src/interceptors.js +70 -0
  397. package/src/javadoc.js +67 -0
  398. package/src/lexer.js +199 -0
  399. package/src/libraries.js +31 -0
  400. package/src/lsp.js +180 -0
  401. package/src/native.js +144 -0
  402. package/src/navigation.js +162 -0
  403. package/src/openapi.js +220 -0
  404. package/src/ownership.js +232 -0
  405. package/src/package-manager.js +299 -0
  406. package/src/parser.js +1155 -0
  407. package/src/policies.js +130 -0
  408. package/src/project-init.js +19 -0
  409. package/src/project.js +292 -0
  410. package/src/schemas.js +62 -0
  411. package/src/semantic.js +255 -0
  412. package/src/spec.js +738 -0
  413. package/src/testing.js +186 -0
  414. package/src/types.js +10 -0
package/src/codegen.js ADDED
@@ -0,0 +1,1159 @@
1
+ import { fieldsOf, initializationOf, isStatement, typeName } from "./ast.js";
2
+ import { builtinProperties, collectionOperations, errorNames } from "./builtins.js";
3
+ import { interceptorChain, InterceptorInvocation } from "./interceptors.js";
4
+ import { NativeSchemas, schemaType } from "./schemas.js";
5
+ import { resolve } from 'node:path';
6
+ import { generateOpenApi, apiExplorer, apiExplorerScript } from "./openapi.js";
7
+ import { actionSchema, actionTransport } from "./actions.js";
8
+ import { httpPolicyNativeName } from "./http-policies.js";
9
+ function cString(value) {
10
+ return '"' + [...value].map(char => char === '"' ? '\\"' : char === '\\' ? '\\\\' :
11
+ char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127 ? '\\' + char.charCodeAt(0).toString(8).padStart(3, '0') : char).join('') + '"';
12
+ }
13
+ export function generateC(checked, options = {}) {
14
+ return new CGenerator(checked, options).generate();
15
+ }
16
+ class CGenerator {
17
+ checked;
18
+ names = new Map();
19
+ bindings = new Map();
20
+ classByName = new Map();
21
+ functions = [];
22
+ constructors = [];
23
+ tables = [];
24
+ prototypes = [];
25
+ externs = [];
26
+ taskThunk(emitter, count) {
27
+ const name = `aug_task_entry_${this.sequence++}`;
28
+ this.prototypes.push(`static AugValue ${name}(AugValue self, AugValue *args, int count);`);
29
+ this.functions.push(emitter.finish(name, true, count));
30
+ return name;
31
+ }
32
+ markupCall(expr) { return this.checked.markupCalls.get(expr); }
33
+ actionPlan(expr) { return this.checked.actions.get(expr); }
34
+ actionSchema(type) { return actionSchema(this.checked.project, type); }
35
+ sequence = 0;
36
+ options;
37
+ coverage = new Map();
38
+ activeFiles = new Set();
39
+ schemas;
40
+ constructor(checked, options) {
41
+ this.checked = checked;
42
+ this.options = options;
43
+ this.schemas = new NativeSchemas(checked.project, def => this.constructorName(def));
44
+ const activate = (file) => {
45
+ if (this.activeFiles.has(file))
46
+ return;
47
+ this.activeFiles.add(file);
48
+ for (const item of checked.project.files.get(file)?.items ?? [])
49
+ if (item.kind === 'import')
50
+ for (const def of checked.project.imports.get(item) ?? [])
51
+ activate(def.file);
52
+ };
53
+ for (const file of checked.project.files.values())
54
+ if (!file.builtin)
55
+ activate(file.path);
56
+ for (const def of checked.project.definitions.values()) {
57
+ this.names.set(def.id, `aug_${this.sequence++}_${def.name}`);
58
+ if (def.node.kind === 'class')
59
+ this.classByName.set(def.name, def);
60
+ }
61
+ checked.bindings.forEach((binding, index) => this.bindings.set(binding.key, index));
62
+ }
63
+ name(def) { return this.names.get(def.id); }
64
+ constructorName(def) { return `aug_construct_${this.name(def)}`; }
65
+ initializerName(def) { return `aug_initialize_${this.name(def)}`; }
66
+ methodName(def, method) { return `${this.name(def)}_${method}`; }
67
+ bodyName(node, name) {
68
+ return interceptorChain(name, this.checked.interceptorPlans.get(node) ?? []).body;
69
+ }
70
+ declareCallable(node, name, method) {
71
+ const signature = `${method ? 'AugValue self, ' : ''}AugValue *args, int count`;
72
+ this.prototypes.push(`static AugValue ${name}(${signature});`);
73
+ const chain = interceptorChain(name, this.checked.interceptorPlans.get(node) ?? []);
74
+ if (chain.entries.length) {
75
+ this.prototypes.push(`static AugValue ${chain.body}(${signature});`);
76
+ for (const entry of chain.entries.slice(1))
77
+ this.prototypes.push(`static AugValue ${entry.name}(${signature});`);
78
+ }
79
+ }
80
+ generate() {
81
+ for (const def of this.checked.project.definitions.values()) {
82
+ if (!this.activeFiles.has(def.file))
83
+ continue;
84
+ if (def.node.kind === 'class' || def.node.kind === 'interceptor') {
85
+ for (const method of def.node.methods) {
86
+ if (def.node.kind === 'interceptor' && method.name === 'around')
87
+ continue;
88
+ this.declareCallable(method, this.methodName(def, method.name), true);
89
+ }
90
+ for (const entry of this.checked.defaults.get(def.id)?.values() ?? []) {
91
+ const method = entry.method;
92
+ if (!def.node.methods.some(item => item.name === method.name))
93
+ this.declareCallable(method, this.methodName(def, method.name), true);
94
+ }
95
+ if (def.node.kind === 'class')
96
+ this.declareCallable(def.node, this.constructorName(def), false);
97
+ else
98
+ this.prototypes.push(`static AugValue ${this.constructorName(def)}(AugValue *args, int count);`);
99
+ if (def.node.kind === 'class' && initializationOf(def.node).length)
100
+ this.prototypes.push(`static AugValue ${this.initializerName(def)}(AugValue self, AugValue *args, int count);`);
101
+ }
102
+ else if (def.node.kind === 'function') {
103
+ if (def.node.endpoint)
104
+ this.prototypes.push(`static AugValue ${this.name(def)}_http(AugValue *incoming, int count);`);
105
+ if (def.node.externC)
106
+ this.externs.push(this.externPrototype(def.node));
107
+ if (!def.node.externC || this.checked.interceptorPlans.get(def.node)?.length)
108
+ this.declareCallable(def.node, this.name(def), false);
109
+ }
110
+ }
111
+ for (const def of this.checked.project.definitions.values()) {
112
+ if (!this.activeFiles.has(def.file))
113
+ continue;
114
+ if (def.node.kind === 'class' || def.node.kind === 'interceptor')
115
+ this.emitClass(def);
116
+ else if (def.node.kind === 'function') {
117
+ if (def.node.body)
118
+ this.functions.push(this.emitFunction(def.node, def.file, def));
119
+ else if (def.node.externC && this.checked.interceptorPlans.get(def.node)?.length) {
120
+ const emitter = new BodyEmitter(this, def.file, def);
121
+ def.node.params.forEach((param, index) => emitter.addParameter(param.name, index));
122
+ emitter.emitNativeReturn(def);
123
+ this.functions.push(emitter.finish(this.bodyName(def.node, this.name(def)), false, def.node.params.length));
124
+ }
125
+ this.emitInterceptors(def.node, this.name(def), def.node.params, false);
126
+ if (def.node.endpoint)
127
+ this.emitEndpoint(def);
128
+ }
129
+ }
130
+ const mainBody = this.emitMainBody();
131
+ const bindingCount = this.checked.bindings.length;
132
+ const bindingArray = `static AugValue aug_bindings[${Math.max(1, bindingCount)}];`;
133
+ const initializeBindings = this.checked.bindings.filter(binding => binding.lifetime === 'shared').map(binding => ` aug_resolve_${this.bindingIndex(binding.key)}(); if (aug_has_error) { aug_report_error(); aug_shutdown(); return 1; }`).join('\n');
134
+ return [
135
+ '#include "aug_runtime.h"',
136
+ '#include <stdio.h>',
137
+ '#include <stdbool.h>',
138
+ '#include <string.h>',
139
+ '#include <stdlib.h>',
140
+ '',
141
+ ...new Set(this.externs),
142
+ bindingArray,
143
+ `static const unsigned char aug_scoped[${Math.max(1, bindingCount)}] = { ${this.checked.bindings.map(binding => binding.lifetime === 'scoped' ? '1' : '0').join(', ') || '0'} };`,
144
+ ...this.checked.bindings.map(binding => `static AugValue aug_resolve_${this.bindingIndex(binding.key)}(void);`),
145
+ ...this.prototypes,
146
+ this.schemas.declarations(),
147
+ '',
148
+ ...this.tables,
149
+ ...this.constructors,
150
+ ...this.functions,
151
+ ...this.checked.bindings.map(binding => this.emitBinding(binding)),
152
+ mainBody,
153
+ `int main(int argc, char **argv) {`,
154
+ ` aug_register_globals(aug_bindings, ${bindingCount});`,
155
+ ` aug_set_cli_args(argc, argv);`,
156
+ ...([...this.activeFiles].some(file => this.checked.project.files.get(file)?.items.some(item => item.kind === 'function' && !!item.endpoint) ||
157
+ [...this.checked.project.definitions.values()].some(def => def.file === file && def.id.startsWith('august/web/'))) ? [this.httpConfiguration()] : []),
158
+ ...[...this.coverage.values()].map(point => ` aug_coverage_register(${cString(point.file)}, ${point.line});`),
159
+ initializeBindings,
160
+ ` AugValue result = aug_main_body(NULL, 0);`,
161
+ ` (void)result;`,
162
+ ` if (aug_has_error) { aug_report_error(); aug_shutdown(); return 1; }`,
163
+ ` int status = aug_test_failed ? 1 : 0;`,
164
+ ...(this.checked.project.testMode ? [
165
+ ` if (aug_test_assertions == 0) { fprintf(stderr, "Test executed no assertions\\n"); status = 1; }`,
166
+ ] : []),
167
+ ` aug_shutdown();`,
168
+ ` return status;`,
169
+ `}`,
170
+ '',
171
+ ].join('\n');
172
+ }
173
+ externPrototype(method) {
174
+ if (method.valueAbi)
175
+ return `extern AugValue ${method.name}(${method.params.length ? method.params.map(() => 'AugValue').join(', ') : 'void'});`;
176
+ const toC = (name) => name === 'string' ? 'const char *' :
177
+ name === 'int' ? 'int64_t' : name === 'c_int' ? 'int' : name === 'float' ? 'double' : name === 'bool' ? 'bool' : 'void';
178
+ return `#line ${method.span.line} ${cString(method.span.file)}\nextern ${toC(method.returns.name)} ${method.name}(${method.params.length ?
179
+ method.params.map(param => toC(param.type.name)).join(', ') : 'void'});`;
180
+ }
181
+ emitClass(def) {
182
+ const cls = def.node;
183
+ const methods = cls.methods.filter(method => cls.kind !== 'interceptor' || method.name !== 'around');
184
+ for (const entry of this.checked.defaults.get(def.id)?.values() ?? []) {
185
+ const method = entry.method;
186
+ if (!methods.some(own => own.name === method.name))
187
+ methods.push(method);
188
+ }
189
+ const tableName = `${this.name(def)}_methods`;
190
+ const ownTableName = `${this.name(def)}_owned_fields`;
191
+ this.tables.push(`static const AugMethodEntry ${tableName}[] = {`);
192
+ for (const method of methods)
193
+ this.tables.push(` {${cString(method.name)}, ${this.methodName(def, method.name)}},`);
194
+ this.tables.push('};');
195
+ this.tables.push(`static const char *const ${this.name(def)}_field_names[] = {${fieldsOf(cls).map(field => cString(field.name)).join(', ') || 'NULL'}};`);
196
+ this.tables.push(`static const unsigned char ${ownTableName}[] = { ${fieldsOf(cls).map(field => field.ownership === 'own' ? '1' : '0').join(', ') || '0'} };`);
197
+ this.constructors.push([
198
+ `static AugValue ${cls.kind === 'class' ? this.bodyName(cls, this.constructorName(def)) : this.constructorName(def)}(AugValue *args, int count) {`,
199
+ ` if (count != ${cls.fields.length}) { fprintf(stderr, "${cls.name} constructor argument mismatch\\n"); return aug_scalar_null(); }`,
200
+ ` AugValue roots[${cls.fields.length + 1}] = {0};`,
201
+ ` AugFrame frame; aug_frame_enter(&frame, roots, ${cls.fields.length + 1});`,
202
+ ...cls.fields.map((_, index) => ` roots[${index}] = args[${index}];`),
203
+ ` roots[${cls.fields.length}] = aug_new_object(${cString(cls.kind === 'class' && cls.record ? def.id : cls.name)}, ${fieldsOf(cls).length}, ${ownTableName}, ${tableName}, ${methods.length});`,
204
+ ...cls.fields.map((_, index) => ` aug_set_field(roots[${cls.fields.length}], ${index}, roots[${index}]);`),
205
+ ...(cls.kind === 'class' && cls.record ? [` roots[${cls.fields.length}].as.object->kind = AUG_RECORD_KIND;`] : []),
206
+ ` AugValue value = roots[${cls.fields.length}];`,
207
+ ` value.as.object->field_names = ${this.name(def)}_field_names;`,
208
+ ...(cls.kind === 'class' && initializationOf(cls).length ? [` ${this.initializerName(def)}(value, NULL, 0);`] : []),
209
+ ...(cls.kind === 'class' && cls.record ? [' aug_freeze(value);'] : []),
210
+ ` aug_frame_leave(&frame);`,
211
+ ` return value;`,
212
+ `}`,
213
+ ].join('\n'));
214
+ if (cls.kind === 'class' && initializationOf(cls).length) {
215
+ const initializer = new BodyEmitter(this, def.file, def, cls);
216
+ initializer.addParameter('self', 0);
217
+ for (const statement of initializationOf(cls))
218
+ initializer.emitStatement(statement);
219
+ this.functions.push(initializer.finish(this.initializerName(def), true, 0));
220
+ }
221
+ for (const method of methods) {
222
+ this.functions.push(this.emitFunction(method, method.span.file, def, cls));
223
+ this.emitInterceptors(method, this.methodName(def, method.name), method.params, true);
224
+ }
225
+ if (cls.kind === 'class')
226
+ this.emitInterceptors(cls, this.constructorName(def), cls.fields, false);
227
+ }
228
+ emitInterceptors(node, name, params, method) {
229
+ for (const { layer, name: entry, next } of interceptorChain(name, this.checked.interceptorPlans.get(node) ?? []).entries) {
230
+ const owner = layer.definition.node;
231
+ const emitter = new BodyEmitter(this, layer.definition.file, layer.definition, owner);
232
+ emitter.initializeInterceptor(layer, params, next, method);
233
+ for (const stmt of layer.around.body ?? [])
234
+ emitter.emitStatement(stmt);
235
+ this.functions.push(emitter.finish(entry, method, params.length));
236
+ }
237
+ }
238
+ emitBinding(binding) {
239
+ const index = this.bindings.get(binding.key);
240
+ const count = binding.constructorKeys.length;
241
+ return [
242
+ `static AugValue aug_resolve_${index}(void) {`,
243
+ ...(binding.lifetime !== 'fresh' ? [` if (aug_binding_get(${index}).tag != AUG_NULL) return aug_binding_get(${index});`] : []),
244
+ ` AugValue roots[${count + 1}] = {0}; AugFrame frame; aug_frame_enter(&frame, roots, ${count + 1});`,
245
+ ...binding.constructorKeys.flatMap((key, input) => [` roots[${input}] = aug_resolve_${this.bindings.get(key)}();`,
246
+ ` if (aug_has_error) goto done;`]),
247
+ ` roots[${count}] = ${this.constructorName(binding.target)}(roots, ${count});`,
248
+ ...(binding.lifetime !== 'fresh' ? [` if (!aug_has_error) aug_binding_set(${index}, roots[${count}]);`] : []),
249
+ `done:; AugValue result = roots[${count}]; aug_frame_leave(&frame); return result;`,
250
+ `}`,
251
+ ].join('\n');
252
+ }
253
+ emitEndpoint(def) {
254
+ const fn = def.node, endpoint = fn.endpoint, count = fn.params.length;
255
+ const policies = this.checked.httpPolicies.get(fn) ?? [];
256
+ const policyTable = `${this.name(def)}_policies`;
257
+ this.tables.push(`static const AugHttpPolicy ${policyTable}[] = {`);
258
+ for (const policy of policies) {
259
+ const option = policy.options;
260
+ this.tables.push(` {${httpPolicyNativeName(policy.name)}, ${cString(String(option.permission ?? ''))}, ${Number(option.requests ?? option.milliseconds ?? 0)}, ${Number(option.seconds ?? 0)}, ${option.credentials ? 'true' : 'false'}, ${cString((option.origins ?? []).join('\n'))}, ${cString((option.headers ?? []).map(header => header.toLowerCase()).join(', '))}},`);
261
+ }
262
+ if (!policies.length)
263
+ this.tables.push(' {0},');
264
+ this.tables.push('};');
265
+ const statements = fn.params.map((param, index) => {
266
+ if (param.injected) {
267
+ const type = schemaType(this.checked.project, param.type, def.file);
268
+ const key = type.name + (type.args.length ? `<${type.args.map(arg => arg.name).join(',')}>` : '');
269
+ return ` roots[${index}] = aug_resolve_${this.bindingIndex(key)}(); if (aug_has_error) goto failed;`;
270
+ }
271
+ const schema = param.source?.kind === 'request' ? 'NULL' : '&' + this.schema(schemaType(this.checked.project, param.type, def.file));
272
+ return ` roots[${index}] = aug_http_bind(roots[${count + 1}], ${cString(param.source.kind)}, ${cString(param.source.name ?? param.name)}, ${schema}); if (aug_has_error) goto failed;`;
273
+ });
274
+ this.functions.push([
275
+ `static AugValue ${this.name(def)}_http(AugValue *incoming, int count) {`,
276
+ ` (void)count; AugValue roots[${count + 2}] = {0}; AugFrame frame; aug_frame_enter(&frame, roots, ${count + 2});`,
277
+ ` roots[${count + 1}] = incoming[0]; size_t scope_depth = aug_scope_depth(); aug_scope_enter(aug_scoped);`,
278
+ ...statements.filter((_, index) => fn.params[index].injected),
279
+ ...policies.map((policy, index) => ` aug_http_policy(&${policyTable}[${index}], roots[${count + 1}], ${policy.dependencies[0] === undefined ? 'aug_scalar_null()' : `roots[${policy.dependencies[0]}]`}, ${policy.dependencies[1] === undefined ? 'aug_scalar_null()' : `roots[${policy.dependencies[1]}]`}); if (aug_has_error) goto failed;`),
280
+ ...statements.filter((_, index) => !fn.params[index].injected),
281
+ ` roots[${count}] = ${this.name(def)}(roots, ${count}); if (aug_has_error) goto failed;`,
282
+ ` roots[${count}] = aug_http_response(roots[${count}], ${endpoint.status}); goto finished;`,
283
+ 'failed:',
284
+ ` { int status = aug_http_error_status();`,
285
+ ...endpoint.errors.map(error => ` if (aug_error_is(${cString(error.type.name)})) status = ${error.status};`),
286
+ ' if (status == 500) aug_report_error(); aug_take_error();',
287
+ ` roots[${count}] = aug_http_problem(status); }`,
288
+ 'finished:',
289
+ ` roots[${count}] = aug_http_finish(roots[${count}]);`,
290
+ ' aug_scope_restore(scope_depth);',
291
+ ` AugValue result = roots[${count}]; aug_frame_leave(&frame); return result;`,
292
+ '}',
293
+ ].join('\n'));
294
+ }
295
+ serveRoutes(file, names) {
296
+ const name = `aug_routes_${this.tables.length}`;
297
+ const config = this.checked.project.config.openapi;
298
+ if (config.enabled) {
299
+ const assets = [JSON.stringify(generateOpenApi(this.checked).document), apiExplorer(config.path, config.docs + '/client.js'), apiExplorerScript];
300
+ ['application/json', 'text/html; charset=utf-8', 'application/javascript; charset=utf-8'].forEach((type, index) => {
301
+ const fn = `${name}_docs_${index}`;
302
+ this.tables.push(`static AugValue ${fn}(AugValue *args, int count) { (void)args; (void)count; AugValue roots[3] = {0}; AugFrame frame; aug_frame_enter(&frame, roots, 3);` +
303
+ ` roots[0] = aug_bytes(${cString(assets[index])}, ${Buffer.byteLength(assets[index])}, AUG_BYTES_KIND); roots[1] = aug_headers_new(); roots[2] = aug_string(${cString(type)});` +
304
+ ` roots[1] = aug_headers_with(roots[1], aug_string("content-type"), roots[2]); roots[0] = aug_http_response_full(roots[0], aug_int(200), roots[1]); AugValue result = roots[0]; aug_frame_leave(&frame); return result; }`);
305
+ });
306
+ }
307
+ if (this.checked.actions.size)
308
+ this.tables.push(`static AugValue ${name}_actions(AugValue *args, int count) { (void)args; (void)count; AugValue roots[2] = {0}; AugFrame frame; aug_frame_enter(&frame, roots, 2); roots[0] = aug_bytes(${cString(actionTransport)}, ${Buffer.byteLength(actionTransport)}, AUG_BYTES_KIND); roots[1] = aug_headers_new(); roots[1] = aug_headers_with(roots[1], aug_string("content-type"), aug_string("application/javascript; charset=utf-8")); roots[0] = aug_http_response_full(roots[0], aug_int(200), roots[1]); AugValue result = roots[0]; aug_frame_leave(&frame); return result; }`);
309
+ this.tables.push(`static const AugRoute ${name}[] = {`);
310
+ for (const symbol of names) {
311
+ const def = this.definition(file, symbol);
312
+ const endpoint = def.node.endpoint;
313
+ const item = def.node.returns.name;
314
+ this.tables.push(` {${cString(endpoint.method)}, ${cString(endpoint.path)}, ${this.name(def)}_http, ${endpoint.streams ? item === 'ServerEvent' ? 1 : item === 'Bytes' ? 2 : 3 : 0}, ${endpoint.status}, ${this.name(def)}_policies, ${(this.checked.httpPolicies.get(def.node) ?? []).length}},`);
315
+ }
316
+ if (config.enabled)
317
+ [config.path, config.docs, config.docs + '/client.js'].forEach((path, index) => this.tables.push(` {"GET", ${cString(path)}, ${name}_docs_${index}},`));
318
+ if (this.checked.actions.size)
319
+ this.tables.push(` {"GET", "/__aug/actions.js", ${name}_actions},`);
320
+ this.tables.push('};');
321
+ return name;
322
+ }
323
+ serveRouteCount(count) { return count + (this.checked.project.config.openapi.enabled ? 3 : 0) + (this.checked.actions.size ? 1 : 0); }
324
+ testEndpoint() { return this.checked.project.testEndpoint; }
325
+ httpConfiguration() {
326
+ const config = this.checked.project.config.web, root = this.checked.project.root;
327
+ const path = (value) => cString(value ? resolve(root, value) : '');
328
+ return ` aug_http_configure(${cString(config.host)}, ${path(config.tls.certificate)}, ${path(config.tls.private_key)}, ${path(config.tls.ca)}, ${config.body_limit}, ${config.response_limit}, ${config.http3 ? 'true' : 'false'});`;
329
+ }
330
+ emitMainBody() {
331
+ const emitter = new BodyEmitter(this, this.checked.project.main?.path ?? '', undefined, undefined);
332
+ const items = this.checked.project.main?.items ?? [];
333
+ for (let index = 0; index <= items.length; index++) {
334
+ if (this.checked.project.testBodyStart === index)
335
+ emitter.beginTestCase();
336
+ const item = items[index];
337
+ if (item && isStatement(item))
338
+ emitter.emitStatement(item);
339
+ }
340
+ return emitter.finish('aug_main_body', false, 0);
341
+ }
342
+ emitFunction(method, file, def, owner) {
343
+ const emitter = new BodyEmitter(this, file, def, owner);
344
+ if (owner)
345
+ emitter.addParameter('self', 0);
346
+ method.params.forEach((param, index) => emitter.addParameter(param.name, index, param.ownership === 'own'));
347
+ for (const stmt of method.body ?? [])
348
+ emitter.emitStatement(stmt);
349
+ return emitter.finish(this.bodyName(method, owner ? this.methodName(def, method.name) : this.name(def)), !!owner, method.params.length);
350
+ }
351
+ definition(file, name) {
352
+ return this.checked.project.scopes.get(file)?.get(name);
353
+ }
354
+ bindingIndex(name) { return this.bindings.get(name) ?? -1; }
355
+ coveragePoint(stmt) {
356
+ if (!this.options.coverage || this.checked.project.files.get(stmt.span.file)?.builtin)
357
+ return false;
358
+ this.coverage.set(`${stmt.span.file}:${stmt.span.line}`, { file: stmt.span.file, line: stmt.span.line });
359
+ return true;
360
+ }
361
+ expressionType(expr) { return this.checked.expressionTypes.get(expr); }
362
+ schema(type) { return this.schemas.request(type); }
363
+ expressionSource(expr) {
364
+ return this.checked.project.files.get(expr.span.file)?.source.slice(expr.span.start, expr.span.end) ?? 'condition';
365
+ }
366
+ callPlan(expr) { return this.checked.callPlans.get(expr); }
367
+ cName(def) { return this.name(def); }
368
+ cConstructor(def) { return this.constructorName(def); }
369
+ cMethod(def, method) { return this.methodName(def, method); }
370
+ hasInterceptors(node) { return !!this.checked.interceptorPlans.get(node)?.length; }
371
+ }
372
+ class BodyEmitter {
373
+ generator;
374
+ file;
375
+ def;
376
+ lines = [];
377
+ locals = new Map();
378
+ owned = new Set();
379
+ classFields = new Map();
380
+ scalarSlots = new Set();
381
+ slots = 1;
382
+ labelCounter = 0;
383
+ errorTarget = 'aug_cleanup';
384
+ returnTarget = 'aug_cleanup';
385
+ continuation;
386
+ constructor(generator, file, def, owner) {
387
+ this.generator = generator;
388
+ this.file = file;
389
+ this.def = def;
390
+ if (owner)
391
+ fieldsOf(owner).forEach((field, index) => this.classFields.set(field.name, index));
392
+ }
393
+ addParameter(name, index, owned = false) {
394
+ const slot = this.newSlot();
395
+ this.locals.set(name, slot);
396
+ this.lines.push(`roots[${slot}] = ${name === 'self' ? 'self' : `args[${index}]`};`);
397
+ if (owned)
398
+ this.owned.add(slot);
399
+ }
400
+ initializeInterceptor(layer, params, name, method) {
401
+ const receiver = method ? this.newSlot() : undefined;
402
+ if (receiver !== undefined)
403
+ this.line(`${this.slot(receiver)} = self;`);
404
+ const original = params.map((param, index) => {
405
+ const slot = this.newSlot();
406
+ this.line(`${this.slot(slot)} = args[${index}];`);
407
+ if (param.ownership === 'own')
408
+ this.owned.add(slot);
409
+ return slot;
410
+ });
411
+ this.continuation = new InterceptorInvocation(layer, params, original, name, receiver);
412
+ const array = this.label('interceptor_dependencies');
413
+ const dependencies = this.continuation.dependencies();
414
+ this.line(`AugValue ${array}[] = { ${dependencies.map(slot => slot === undefined ? 'aug_scalar_null()' : this.slot(slot)).join(', ') || 'aug_scalar_null()'} };`);
415
+ const self = this.newSlot();
416
+ this.locals.set('self', self);
417
+ this.line(`${this.slot(self)} = ${this.generator.cConstructor(layer.definition)}(${array}, ${dependencies.length});`);
418
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
419
+ for (const input of this.continuation.inputs()) {
420
+ if (input.reuseOwnedSlot) {
421
+ this.locals.set(input.name, input.slot);
422
+ continue;
423
+ }
424
+ const slot = this.newSlot();
425
+ this.locals.set(input.name, slot);
426
+ this.line(`${this.slot(slot)} = ${input.slot === undefined ? 'aug_scalar_null()' : this.slot(input.slot)};`);
427
+ }
428
+ }
429
+ emitNativeReturn(def) {
430
+ const fn = def.node;
431
+ this.emitExternCall(def, fn.params.map(param => this.locals.get(param.name)), 0);
432
+ this.line('goto aug_cleanup;');
433
+ }
434
+ emitNext(expr) {
435
+ const next = this.continuation;
436
+ const values = expr.args.map(arg => this.emitExpr(arg));
437
+ const plan = this.generator.callPlan(expr);
438
+ const { args, transfers } = next.forward(plan.sourceIndices, values);
439
+ const array = this.label('next_args');
440
+ this.line(`AugValue ${array}[] = { ${args.map(slot => this.slot(slot)).join(', ') || 'aug_scalar_null()'} };`);
441
+ for (const { original, replacement } of transfers) {
442
+ if (replacement !== original)
443
+ this.line(`if (${this.slot(original)}.tag != AUG_NULL) aug_drop(${this.slot(original)});`);
444
+ this.line(`${this.slot(original)} = aug_scalar_null();`);
445
+ if (this.owned.has(replacement) && replacement !== original)
446
+ this.line(`${this.slot(replacement)} = aug_scalar_null();`);
447
+ }
448
+ const slot = this.newSlot();
449
+ this.line(`${this.slot(slot)} = ${next.target}(${next.receiver === undefined ? '' :
450
+ `${this.slot(next.receiver)}, `}${array}, ${args.length});`);
451
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
452
+ return slot;
453
+ }
454
+ newSlot() { return this.slots++; }
455
+ slot(index) { return `roots[${index}]`; }
456
+ line(text) { this.lines.push(text); }
457
+ label(prefix) { return `${prefix}_${this.labelCounter++}`; }
458
+ memberIndex(expr, name) {
459
+ const type = this.generator.expressionType(expr);
460
+ if (type?.kind === 'builtin')
461
+ return builtinProperties[type.name]?.findIndex(field => field.name === name) ?? -1;
462
+ const node = type?.def?.node;
463
+ return node?.kind === 'class' || node?.kind === 'interceptor' ? fieldsOf(node).findIndex(field => field.name === name) : -1;
464
+ }
465
+ isScalar(type) {
466
+ return !!type && type.kind === 'builtin' && ['int', 'c_int', 'float', 'bool'].includes(type.name);
467
+ }
468
+ emitExpr(expr) {
469
+ const firstNewSlot = this.slots;
470
+ const slot = this.emitValueExpr(expr);
471
+ // Scalar temporaries never contain a GC pointer. Keeping them outside the
472
+ // escaped root array lets the C optimizer keep arithmetic in registers.
473
+ if (slot >= firstNewSlot && this.isScalar(this.generator.expressionType(expr)))
474
+ this.scalarSlots.add(slot);
475
+ return slot;
476
+ }
477
+ emitValueExpr(expr) {
478
+ if (expr.kind === 'handle' && expr.call.kind === 'call') {
479
+ const plan = this.generator.actionPlan(expr), endpoint = plan.endpoint.node.endpoint;
480
+ const metadata = { method: endpoint.method, path: endpoint.path, parameters: plan.parameters.map(({ param, type, form }) => ({ name: param.source?.name ?? param.name, source: param.source?.kind, form, schema: this.generator.actionSchema(type) })) };
481
+ const args = plan.parameters.map(parameter => parameter.form || parameter.source === undefined ? undefined : this.emitExpr(expr.call.args[parameter.source]));
482
+ const array = this.label('action_values'), slot = this.newSlot();
483
+ this.line(`AugValue ${array}[] = {${args.map(arg => arg === undefined ? 'aug_null()' : this.slot(arg)).join(', ') || 'aug_scalar_null()'}};`);
484
+ this.line(`${this.slot(slot)} = aug_http_action(${cString(JSON.stringify(metadata))}, ${array}, ${args.length});`);
485
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
486
+ return slot;
487
+ }
488
+ if (expr.kind === 'markupText') {
489
+ const slot = this.newSlot();
490
+ this.line(`${this.slot(slot)} = aug_string(${cString(expr.text)});`);
491
+ return slot;
492
+ }
493
+ if (expr.kind === 'markup') {
494
+ const component = this.generator.markupCall(expr);
495
+ if (component)
496
+ return this.emitExpr(component);
497
+ const names = expr.attributes.map(attribute => this.emitExpr({ kind: 'literal', value: attribute.name, span: attribute.span }));
498
+ const attrs = expr.attributes.map(attribute => this.emitExpr(attribute.value)), children = expr.children.map(child => this.emitExpr(child));
499
+ const array = this.label('html_attributes'), body = this.label('html_children'), slot = this.newSlot();
500
+ this.line(`AugValue ${array}[] = {${expr.attributes.flatMap((_, index) => [this.slot(names[index]), this.slot(attrs[index])]).join(', ') || 'aug_scalar_null()'}};`);
501
+ this.line(`AugValue ${body}[] = {${children.map(child => this.slot(child)).join(', ') || 'aug_scalar_null()'}};`);
502
+ this.line(`${this.slot(slot)} = aug_html_element(${cString(expr.tag)}, ${array}, ${attrs.length}, ${body}, ${children.length});`);
503
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
504
+ return slot;
505
+ }
506
+ if (expr.kind === 'start' && expr.call.kind === 'call') {
507
+ const call = expr.call;
508
+ const { receiver, args } = this.emitArguments(call);
509
+ const thunk = new BodyEmitter(this.generator, this.file, this.def);
510
+ thunk.addParameter('self', 0);
511
+ args.forEach((_, index) => thunk.addParameter(`argument_${index}`, index));
512
+ const result = thunk.emitInvoke(call, receiver === undefined ? undefined : thunk.locals.get('self'), args.map((_, index) => thunk.locals.get(`argument_${index}`)));
513
+ thunk.line(`${thunk.slot(0)} = ${thunk.slot(result)};`);
514
+ const name = this.generator.taskThunk(thunk, args.length), array = this.label('task_args'), slot = this.newSlot();
515
+ this.line(`AugValue ${array}[] = {${args.map(arg => this.slot(arg)).join(', ') || 'aug_scalar_null()'}};`);
516
+ this.line(`${this.slot(slot)} = aug_task_start(${name}, ${receiver === undefined ? 'aug_scalar_null()' : this.slot(receiver)}, ${array}, ${args.length});`);
517
+ this.clearMovedArgs(call, (this.generator.callPlan(call)?.ownerships ?? []).map(ownership => ({ ownership: ownership ?? 'managed' })));
518
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
519
+ return slot;
520
+ }
521
+ if (expr.kind === 'wait') {
522
+ const values = expr.tasks.map(task => this.emitExpr(task)), slot = this.newSlot(), array = this.label('wait_tasks');
523
+ this.line(`AugValue ${array}[] = {${values.map(value => this.slot(value)).join(', ')}};`);
524
+ this.line(`${this.slot(slot)} = aug_task_wait(${array}, ${values.length});`);
525
+ this.line(`if (aug_cancelled) goto ${this.returnTarget};`);
526
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
527
+ return slot;
528
+ }
529
+ if (expr.kind === 'name') {
530
+ const local = this.locals.get(expr.name);
531
+ if (local !== undefined)
532
+ return local;
533
+ const field = this.classFields.get(expr.name);
534
+ if (field !== undefined) {
535
+ const slot = this.newSlot();
536
+ this.line(`${this.slot(slot)} = aug_field(${this.slot(this.locals.get('self'))}, ${field});`);
537
+ return slot;
538
+ }
539
+ const slot = this.newSlot();
540
+ this.line(`${this.slot(slot)} = aug_scalar_null();`);
541
+ return slot;
542
+ }
543
+ if (expr.kind === 'literal') {
544
+ const slot = this.newSlot();
545
+ const value = expr.value === null ? 'aug_scalar_null()' : typeof expr.value === 'string' ?
546
+ `aug_string(${cString(expr.value)})` : typeof expr.value === 'boolean' ?
547
+ `aug_scalar_bool(${expr.value})` : expr.numericType !== 'float' && Number.isInteger(expr.value) ?
548
+ `aug_scalar_int(${expr.numericText === '-9223372036854775808' ? 'INT64_MIN' : `INT64_C(${expr.numericText ?? expr.value})`})` : `aug_scalar_float(${expr.value})`;
549
+ this.line(`${this.slot(slot)} = ${value};`);
550
+ return slot;
551
+ }
552
+ if (expr.kind === 'collection') {
553
+ const args = expr.items.map(item => this.emitExpr(item));
554
+ const slot = this.newSlot();
555
+ const name = this.generator.expressionType(expr)?.name ?? expr.collection;
556
+ if (name === 'Map') {
557
+ this.line(`${this.slot(slot)} = aug_map_new();`);
558
+ for (let index = 0; index < args.length; index += 2)
559
+ this.line(`aug_map_set(${this.slot(slot)}, ${this.slot(args[index])}, ${this.slot(args[index + 1])});`);
560
+ }
561
+ else {
562
+ const array = this.label('items');
563
+ this.line(`AugValue ${array}[] = { ${args.map(index => this.slot(index)).join(', ') || 'aug_scalar_null()'} };`);
564
+ this.line(`${this.slot(slot)} = aug_${name.toLowerCase()}_new(${array}, ${args.length});`);
565
+ }
566
+ return slot;
567
+ }
568
+ if (expr.kind === 'resolve') {
569
+ const slot = this.newSlot();
570
+ const key = expr.name + (expr.typeArgs.length ? `<${expr.typeArgs.map(typeName).join(',')}>` : '');
571
+ this.line(`${this.slot(slot)} = aug_resolve_${this.generator.bindingIndex(key)}();`);
572
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
573
+ return slot;
574
+ }
575
+ if (expr.kind === 'member') {
576
+ const object = this.emitExpr(expr.object);
577
+ const slot = this.newSlot();
578
+ this.line(`${this.slot(slot)} = aug_field(${this.slot(object)}, ${this.memberIndex(expr.object, expr.name)});`);
579
+ return slot;
580
+ }
581
+ if (expr.kind === 'unary') {
582
+ const value = this.emitExpr(expr.value);
583
+ const slot = this.newSlot();
584
+ const type = this.generator.expressionType(expr.value);
585
+ const scalar = type && this.isScalar(type) && !type.nullable && !type.optional;
586
+ const operand = this.slot(value);
587
+ const fast = scalar && expr.op === '!' && type.name === 'bool' ? `aug_scalar_bool(!${operand}.as.boolean)` :
588
+ scalar && expr.op === '-' && ['int', 'c_int'].includes(type.name) ? `aug_scalar_int(aug_signed_bits(UINT64_C(0) - (uint64_t)${operand}.as.integer))` :
589
+ scalar && expr.op === '-' && type.name === 'float' ? `(${operand}.tag == AUG_FLOAT ? aug_scalar_float(-${operand}.as.floating) : aug_unary("-", ${operand}))` : undefined;
590
+ this.line(`${this.slot(slot)} = ${fast ?? `aug_unary(${cString(expr.op)}, ${operand})`};`);
591
+ return slot;
592
+ }
593
+ if (expr.kind === 'binary') {
594
+ const left = this.emitExpr(expr.left);
595
+ if (expr.op === '&&' || expr.op === '||') {
596
+ const slot = this.newSlot();
597
+ this.line(`${this.slot(slot)} = aug_scalar_bool(${this.slot(left)}.as.boolean);`);
598
+ this.line(`if (${expr.op === '||' ? '!' : ''}${this.slot(slot)}.as.boolean) {`);
599
+ const right = this.emitExpr(expr.right);
600
+ this.line(`${this.slot(slot)} = aug_scalar_bool(${this.slot(right)}.as.boolean);`);
601
+ this.line('}');
602
+ return slot;
603
+ }
604
+ const right = this.emitExpr(expr.right);
605
+ const slot = this.newSlot();
606
+ this.line(`${this.slot(slot)} = ${this.scalarBinary(expr, left, right) ?? `aug_binary(${cString(expr.op)}, ${this.slot(left)}, ${this.slot(right)})`};`);
607
+ if (expr.op === '/')
608
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
609
+ return slot;
610
+ }
611
+ if (expr.kind !== 'call')
612
+ throw new Error(`Cannot emit ${expr.kind}`);
613
+ if (expr.callee.kind === 'name' && expr.callee.name === 'next')
614
+ return this.emitNext(expr);
615
+ const { receiver, args } = this.emitArguments(expr);
616
+ return this.emitInvoke(expr, receiver, args);
617
+ }
618
+ scalarBinary(expr, left, right) {
619
+ const a = this.generator.expressionType(expr.left), b = this.generator.expressionType(expr.right);
620
+ if (!a || !b || !this.isScalar(a) || !this.isScalar(b) || a.nullable || b.nullable || a.optional || b.optional)
621
+ return;
622
+ if (a.name === 'bool' && b.name === 'bool' && ['==', '!='].includes(expr.op))
623
+ return `aug_scalar_bool(${this.slot(left)}.as.boolean ${expr.op} ${this.slot(right)}.as.boolean)`;
624
+ const numeric = (type) => ['int', 'c_int', 'float'].includes(type.name);
625
+ if (!numeric(a) || !numeric(b))
626
+ return;
627
+ const integer = a.name !== 'float' && b.name !== 'float';
628
+ const operand = (slot, type) => `${integer || type.name === 'float' ? '' : '(double)'}${this.slot(slot)}.as.${type.name === 'float' ? 'floating' : 'integer'}`;
629
+ const x = operand(left, a), y = operand(right, b);
630
+ let fast;
631
+ if (['==', '!=', '<', '>', '<=', '>='].includes(expr.op))
632
+ fast = `aug_scalar_bool(${x} ${expr.op} ${y})`;
633
+ else if (expr.op === '/')
634
+ fast = `aug_scalar_${integer ? 'int' : 'float'}_divide(${x}, ${y})`;
635
+ else if (['+', '-', '*'].includes(expr.op))
636
+ fast = integer ?
637
+ `aug_scalar_int(aug_signed_bits((uint64_t)${x} ${expr.op} (uint64_t)${y}))` : `aug_scalar_float(${x} ${expr.op} ${y})`;
638
+ if (!fast || integer)
639
+ return fast;
640
+ // Widening can leave an INT-tagged value in a statically float position.
641
+ // Use the existing numeric semantics until its representation is FLOAT.
642
+ const guards = [{ type: a, slot: left }, { type: b, slot: right }].flatMap(({ type, slot }) => type.name === 'float' ? [`${this.slot(slot)}.tag == AUG_FLOAT`] : []);
643
+ return `(${guards.join(' && ')} ? ${fast} : aug_binary(${cString(expr.op)}, ${this.slot(left)}, ${this.slot(right)}))`;
644
+ }
645
+ emitArguments(expr) {
646
+ const receiver = expr.callee.kind === 'member' ? this.emitExpr(expr.callee.object) : undefined;
647
+ const sourceArgs = expr.args.map(arg => this.emitExpr(arg));
648
+ const plan = this.generator.callPlan(expr);
649
+ const args = plan ? plan.sourceIndices.map((source, index) => {
650
+ if (source !== undefined)
651
+ return sourceArgs[source];
652
+ const dependency = plan.injectionSources?.[index];
653
+ if (dependency) {
654
+ const slot = this.newSlot();
655
+ if (dependency.startsWith('self.'))
656
+ this.line(`${this.slot(slot)} = aug_field(${this.slot(this.locals.get('self'))}, ${this.classFields.get(dependency.slice(5))});`);
657
+ else
658
+ this.line(`${this.slot(slot)} = ${this.slot(this.locals.get(dependency))};`);
659
+ return slot;
660
+ }
661
+ const slot = this.newSlot();
662
+ this.line(`${this.slot(slot)} = ${plan.bindingKeys[index] ? `aug_resolve_${this.generator.bindingIndex(plan.bindingKeys[index])}()` : 'aug_null()'};`);
663
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
664
+ return slot;
665
+ }) : sourceArgs;
666
+ return { receiver, args };
667
+ }
668
+ emitInvoke(expr, receiver, args) {
669
+ const slot = this.newSlot();
670
+ const array = this.label('args');
671
+ this.line(`AugValue ${array}[] = { ${args.map(index => this.slot(index)).join(', ') || 'aug_scalar_null()'} };`);
672
+ if (expr.callee.kind === 'name' && expr.callee.name === 'exit') {
673
+ this.line(`int aug_exit_code_${slot} = (int)aug_cint(${this.slot(args[0])});`);
674
+ this.line(`aug_cancelled = true; aug_shutdown(); exit(aug_exit_code_${slot} >= 0 && aug_exit_code_${slot} <= 255 ? aug_exit_code_${slot} : 1);`);
675
+ return slot;
676
+ }
677
+ if (expr.callee.kind === 'name' && expr.callee.name === 'Json') {
678
+ this.line(`${this.slot(slot)} = aug_json_wrap(${this.slot(args[0])});`);
679
+ return slot;
680
+ }
681
+ if (expr.callee.kind === 'name' && expr.callee.name === 'HttpTestClient') {
682
+ const endpoint = this.generator.testEndpoint();
683
+ const routes = this.generator.serveRoutes(endpoint.file, [endpoint.name]);
684
+ this.line(`${this.slot(slot)} = aug_http_test_client(${routes}, ${this.generator.serveRouteCount(1)});`);
685
+ return slot;
686
+ }
687
+ if (expr.callee.kind === 'name' && expr.callee.name === 'Shared') {
688
+ this.line(`${this.slot(slot)} = aug_shared_new(${this.slot(args[0])});`);
689
+ if (expr.args[0]?.kind === 'name') {
690
+ const source = this.locals.get(expr.args[0].name);
691
+ if (source !== undefined && this.owned.has(source))
692
+ this.line(`${this.slot(source)} = aug_scalar_null();`);
693
+ }
694
+ return slot;
695
+ }
696
+ if (expr.callee.kind === 'name' && expr.callee.name === 'ServerEvent') {
697
+ this.line(`${this.slot(slot)} = aug_http_event(${args.map(arg => this.slot(arg)).join(', ')});`);
698
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
699
+ return slot;
700
+ }
701
+ if (expr.callee.kind === 'name' && ['Headers', 'HttpResponse'].includes(expr.callee.name)) {
702
+ this.line(`${this.slot(slot)} = ${expr.callee.name === 'Headers' ? 'aug_headers_new()' : `aug_http_response_full(${this.slot(args[0])}, ${this.slot(args[1])}, ${this.slot(args[2])})`};`);
703
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
704
+ return slot;
705
+ }
706
+ if (expr.callee.kind === 'name' && ['c_int', 'int'].includes(expr.callee.name)) {
707
+ this.line(`${this.slot(slot)} = ${expr.callee.name === 'c_int' ? `aug_to_c_int(${this.slot(args[0])})` : this.slot(args[0])};`);
708
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
709
+ return slot;
710
+ }
711
+ if (expr.callee.kind === 'name' && expr.callee.name === 'print') {
712
+ if (args[0] !== undefined)
713
+ this.line(`aug_print(${this.slot(args[0])});`);
714
+ this.line(`${this.slot(slot)} = aug_scalar_null();`);
715
+ return slot;
716
+ }
717
+ if (expr.callee.kind === 'name' && expr.callee.name === 'assert') {
718
+ this.line(`aug_assert(${this.slot(args[0])}, ${cString(this.generator.expressionSource(expr.args[0]))}, ${cString(expr.span.file)}, ${expr.span.line});`);
719
+ this.line(`${this.slot(slot)} = aug_scalar_null();`);
720
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
721
+ return slot;
722
+ }
723
+ if (expr.callee.kind === 'name' && expr.callee.name === 'arguments') {
724
+ this.line(`${this.slot(slot)} = aug_arguments();`);
725
+ return slot;
726
+ }
727
+ if (expr.callee.kind === 'name' && expr.callee.name === 'read_file') {
728
+ this.line(`${this.slot(slot)} = aug_read_file(${this.slot(args[0])});`);
729
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
730
+ return slot;
731
+ }
732
+ if (expr.callee.kind === 'name' && expr.callee.name === 'write_file') {
733
+ this.line(`${this.slot(slot)} = aug_write_file(${this.slot(args[0])}, ${this.slot(args[1])});`);
734
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
735
+ return slot;
736
+ }
737
+ if (expr.callee.kind === 'name' && ['List', 'Set', 'Tuple'].includes(expr.callee.name)) {
738
+ this.line(`${this.slot(slot)} = aug_${expr.callee.name.toLowerCase()}_new(${array}, ${args.length});`);
739
+ return slot;
740
+ }
741
+ if (expr.callee.kind === 'name' && expr.callee.name === 'Map') {
742
+ this.line(`${this.slot(slot)} = aug_map_new();`);
743
+ return slot;
744
+ }
745
+ if (expr.callee.kind === 'name' && errorNames.includes(expr.callee.name)) {
746
+ this.line(`${this.slot(slot)} = aug_new_object(${cString(expr.callee.name)}, 0, NULL, NULL, 0);`);
747
+ return slot;
748
+ }
749
+ if (expr.callee.kind === 'name') {
750
+ const def = this.generator.definition(this.file, expr.callee.name);
751
+ if (def?.node.kind === 'class') {
752
+ this.line(`${this.slot(slot)} = ${this.generator.cConstructor(def)}(${array}, ${args.length});`);
753
+ this.clearMovedArgs(expr, def.node.fields);
754
+ }
755
+ else if (def?.node.kind === 'function') {
756
+ if (def.node.externC && !this.generator.hasInterceptors(def.node))
757
+ this.emitExternCall(def, args, slot);
758
+ else
759
+ this.line(`${this.slot(slot)} = ${this.generator.cName(def)}(${array}, ${args.length});`);
760
+ this.clearMovedArgs(expr, def.node.params);
761
+ }
762
+ }
763
+ else if (expr.callee.kind === 'member') {
764
+ const methodName = expr.callee.name;
765
+ const type = this.generator.expressionType(expr.callee.object);
766
+ const operation = type && collectionOperations[type.name]?.find(operation => operation.name === methodName);
767
+ if (operation) {
768
+ if (type.name === 'Json' && methodName === 'decode' || type.name === 'HttpRequest' && methodName === 'form') {
769
+ this.line(`${this.slot(slot)} = ${methodName === 'form' ? 'aug_httprequest_form' : 'aug_json_decode'}(${this.slot(receiver)}, &${this.generator.schema(this.generator.expressionType(expr))});`);
770
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
771
+ return slot;
772
+ }
773
+ const values = [this.slot(receiver), ...args.map((index, position) => operation.parameters[position]?.type === 'int' ? `aug_cint(${this.slot(index)})` : this.slot(index))];
774
+ const call = `aug_${type.name.toLowerCase()}_${operation.native}(${values.join(', ')})`;
775
+ if (operation.returns === 'void') {
776
+ this.line(`${call};`);
777
+ this.line(`${this.slot(slot)} = aug_scalar_null();`);
778
+ }
779
+ else
780
+ this.line(`${this.slot(slot)} = ${operation.returns === 'bool' ? `aug_scalar_bool(${call})` : operation.returns === 'int' ? `aug_scalar_int(${call})` : call};`);
781
+ }
782
+ else {
783
+ this.line(`${this.slot(slot)} = aug_call_method(${this.slot(receiver)}, ${cString(methodName)}, ${array}, ${args.length});`);
784
+ const node = type?.def?.node;
785
+ const method = node?.kind === 'class' || node?.kind === 'interface' || node?.kind === 'interceptor' ?
786
+ node.methods.find(item => item.name === methodName) : undefined;
787
+ if (method)
788
+ this.clearMovedArgs(expr, method.params);
789
+ }
790
+ }
791
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
792
+ return slot;
793
+ }
794
+ clearMovedArgs(call, params) {
795
+ const plan = this.generator.callPlan(call);
796
+ params.forEach((param, index) => {
797
+ const source = plan ? plan.sourceIndices[index] : index;
798
+ if (source === undefined || param.ownership !== 'own' ||
799
+ call.args[source]?.kind !== 'name')
800
+ return;
801
+ const name = call.args[source].name;
802
+ const slot = this.locals.get(name);
803
+ if (slot !== undefined && this.owned.has(slot))
804
+ this.line(`${this.slot(slot)} = aug_scalar_null();`);
805
+ });
806
+ }
807
+ emitExternCall(def, args, output) {
808
+ const fn = def.node;
809
+ if (fn.valueAbi) {
810
+ this.line(`${this.slot(output)} = ${fn.name}(${args.map(index => this.slot(index)).join(', ')});`);
811
+ return;
812
+ }
813
+ const values = args.map((index, i) => {
814
+ const type = fn.params[i]?.type.name;
815
+ return type === 'string' ? `aug_cstring(${this.slot(index)})` :
816
+ type === 'int' ? `aug_cint(${this.slot(index)})` : type === 'c_int' ? `(int)aug_cint(${this.slot(index)})` :
817
+ type === 'float' ? `aug_cfloat(${this.slot(index)})` :
818
+ type === 'bool' ? `aug_truthy(${this.slot(index)})` : this.slot(index);
819
+ });
820
+ const call = `${fn.name}(${values.join(', ')})`;
821
+ const convert = fn.returns.name === 'void' ? `${call}; ${this.slot(output)} = aug_scalar_null()` :
822
+ fn.returns.name === 'string' ? `aug_string(${call})` :
823
+ ['int', 'c_int'].includes(fn.returns.name) ? `aug_scalar_int(${call})` :
824
+ fn.returns.name === 'float' ? `aug_scalar_float(${call})` : `aug_scalar_bool(${call})`;
825
+ this.line(fn.returns.name === 'void' ? `${convert};` : `${this.slot(output)} = ${convert};`);
826
+ }
827
+ beginTestCase() { this.line('aug_test_assertions = 0;'); }
828
+ emitStatement(stmt) {
829
+ if (stmt.kind === 'lock') {
830
+ const value = this.emitExpr(stmt.value), slot = this.newSlot();
831
+ const names = new Map(this.locals);
832
+ this.locals.set(stmt.name, slot);
833
+ this.line(`${this.slot(slot)} = aug_shared_lock(${this.slot(value)});`);
834
+ this.line(`if (aug_cancelled) goto ${this.returnTarget};`);
835
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
836
+ this.emitScoped(stmt.body);
837
+ this.line('aug_lock_leave();');
838
+ this.locals = names;
839
+ return;
840
+ }
841
+ this.line(`#line ${stmt.span.line} ${cString(stmt.span.file)}`);
842
+ if (this.generator.coveragePoint(stmt))
843
+ this.line(`aug_cover(${cString(stmt.span.file)}, ${stmt.span.line});`);
844
+ if (stmt.kind === 'serve') {
845
+ const port = this.emitExpr(stmt.port), routes = this.generator.serveRoutes(this.file, stmt.names);
846
+ this.line(`aug_http_serve(${routes}, ${this.generator.serveRouteCount(stmt.names.length)}, aug_cint(${this.slot(port)}));`);
847
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
848
+ return;
849
+ }
850
+ if (stmt.kind === 'freeze') {
851
+ const value = this.emitExpr(stmt.value);
852
+ this.line(`aug_freeze(${this.slot(value)});`);
853
+ const slot = this.newSlot();
854
+ this.locals.set(stmt.name, slot);
855
+ this.line(`${this.slot(slot)} = ${this.slot(value)};`);
856
+ if (stmt.value.kind === 'name') {
857
+ const source = this.locals.get(stmt.value.name);
858
+ if (source !== undefined)
859
+ this.owned.delete(source);
860
+ }
861
+ return;
862
+ }
863
+ if (stmt.kind === 'expr') {
864
+ this.emitExpr(stmt.expr);
865
+ return;
866
+ }
867
+ if (stmt.kind === 'destructure') {
868
+ const value = this.emitExpr(stmt.value);
869
+ for (const [index, name] of stmt.names.entries()) {
870
+ const slot = this.newSlot();
871
+ this.locals.set(name, slot);
872
+ this.line(`${this.slot(slot)} = aug_tuple_get(${this.slot(value)}, ${index});`);
873
+ }
874
+ return;
875
+ }
876
+ if (stmt.kind === 'for') {
877
+ const value = this.emitExpr(stmt.iterable);
878
+ const snapshot = this.newSlot();
879
+ const iterableType = this.generator.expressionType(stmt.iterable);
880
+ const flatMap = stmt.names.length === 2 && iterableType?.kind === 'builtin' && iterableType.name === 'Map';
881
+ this.line(`${this.slot(snapshot)} = ${flatMap ? 'aug_map_entries_snapshot' : 'aug_iter_snapshot'}(${this.slot(value)});`);
882
+ const index = this.label('aug_index');
883
+ const names = new Map(this.locals);
884
+ const slots = stmt.names.map(name => { const slot = this.newSlot(); this.locals.set(name, slot); return slot; });
885
+ if (flatMap)
886
+ slots.forEach((slot, index) => {
887
+ if (this.isScalar(this.generator.expressionType(stmt.iterable)?.args[index]))
888
+ this.scalarSlots.add(slot);
889
+ });
890
+ this.line(`for (size_t ${index} = 0; ${index} < ${this.slot(snapshot)}.as.object->field_count${flatMap ? ' / 2' : ''}; ${index}++) {`);
891
+ this.line('if (aug_execution->fiber || aug_task_checkpoint_hook) aug_task_checkpoint();');
892
+ this.line(`if (aug_cancelled) goto ${this.returnTarget};`);
893
+ if (flatMap)
894
+ slots.forEach((slot, position) => this.line(`${this.slot(slot)} = ${this.slot(snapshot)}.as.object->fields[${index} * 2 + ${position}];`));
895
+ else {
896
+ const item = this.newSlot();
897
+ this.line(`${this.slot(item)} = ${this.slot(snapshot)}.as.object->fields[${index}];`);
898
+ slots.forEach((slot, position) => this.line(`${this.slot(slot)} = ${slots.length === 1 ? this.slot(item) : `aug_tuple_get(${this.slot(item)}, ${position})`};`));
899
+ }
900
+ this.emitScoped(stmt.body);
901
+ this.line('}');
902
+ this.locals = names;
903
+ return;
904
+ }
905
+ if (stmt.kind === 'match') {
906
+ const value = this.emitExpr(stmt.value);
907
+ const literals = stmt.cases.map(clause => clause.literal ? this.emitExpr(clause.literal) : undefined);
908
+ for (const [index, clause] of stmt.cases.entries()) {
909
+ const literal = literals[index];
910
+ const type = clause.type ? this.generator.definition(this.file, clause.type.name) : undefined;
911
+ const condition = clause.pattern === 'else' ? '1' : clause.pattern === 'null' ? `${this.slot(value)}.tag == AUG_NULL` :
912
+ clause.pattern === 'some' ? `${this.slot(value)}.tag != AUG_NULL` : clause.pattern === 'type' ?
913
+ `${this.slot(value)}.tag == AUG_OBJECT && !strcmp(${this.slot(value)}.as.object->type_name, ${cString(type?.node.kind === 'class' && type.node.record ? type.id : clause.type.name)})` :
914
+ `aug_truthy(aug_binary("==", ${this.slot(value)}, ${this.slot(literal)}))`;
915
+ this.line(`${index ? 'else ' : ''}if (${condition}) {`);
916
+ const names = new Map(this.locals);
917
+ if (clause.name)
918
+ this.locals.set(clause.name, value);
919
+ this.emitScoped(clause.body);
920
+ this.locals = names;
921
+ this.line('}');
922
+ }
923
+ return;
924
+ }
925
+ if (stmt.kind === 'assign') {
926
+ const value = this.emitExpr(stmt.value);
927
+ const sourceSlot = stmt.value.kind === 'name' ? this.locals.get(stmt.value.name) : undefined;
928
+ if (stmt.target.kind === 'name') {
929
+ const existing = this.locals.get(stmt.target.name);
930
+ if (existing !== undefined)
931
+ this.line(`${this.slot(existing)} = ${this.slot(value)};`);
932
+ else if (this.classFields.has(stmt.target.name))
933
+ this.line(`aug_set_field(${this.slot(this.locals.get('self'))}, ${this.classFields.get(stmt.target.name)}, ${this.slot(value)});`);
934
+ else {
935
+ const target = this.newSlot();
936
+ this.locals.set(stmt.target.name, target);
937
+ this.line(`${this.slot(target)} = ${this.slot(value)};`);
938
+ if (this.isScalar(this.generator.expressionType(stmt.value)) && (!stmt.declaredType || ['int', 'c_int', 'float', 'bool'].includes(stmt.declaredType.name)))
939
+ this.scalarSlots.add(target);
940
+ if (stmt.ownership === 'own')
941
+ this.owned.add(target);
942
+ }
943
+ }
944
+ else if (stmt.target.kind === 'member') {
945
+ const object = this.emitExpr(stmt.target.object);
946
+ this.line(`aug_set_field(${this.slot(object)}, ${this.memberIndex(stmt.target.object, stmt.target.name)}, ${this.slot(value)});`);
947
+ }
948
+ let targetOwns = stmt.ownership === 'own';
949
+ if (stmt.target.kind === 'member') {
950
+ const memberName = stmt.target.name;
951
+ const node = this.generator.expressionType(stmt.target.object)?.def?.node;
952
+ targetOwns ||= (node?.kind === 'class' || node?.kind === 'interceptor') && !!fieldsOf(node).find(field => field.name === memberName && field.ownership === 'own');
953
+ }
954
+ if (sourceSlot !== undefined && this.owned.has(sourceSlot) && targetOwns)
955
+ this.line(`${this.slot(sourceSlot)} = aug_scalar_null();`);
956
+ return;
957
+ }
958
+ if (stmt.kind === 'yield') {
959
+ const value = this.emitExpr(stmt.value);
960
+ this.line(`aug_http_yield(${this.slot(value)});`);
961
+ this.line(`if (aug_has_error || aug_cancelled) goto ${this.errorTarget};`);
962
+ return;
963
+ }
964
+ if (stmt.kind === 'return') {
965
+ const value = stmt.value ? this.emitExpr(stmt.value) : undefined;
966
+ this.line(`${this.slot(0)} = ${value === undefined ? 'aug_scalar_null()' : this.slot(value)};`);
967
+ if (value !== undefined && this.owned.has(value))
968
+ this.line(`${this.slot(value)} = aug_scalar_null();`);
969
+ this.line(`goto ${this.returnTarget};`);
970
+ return;
971
+ }
972
+ if (stmt.kind === 'throw') {
973
+ const value = this.emitExpr(stmt.value);
974
+ this.line(`aug_throw(${this.slot(value)});`);
975
+ if (this.owned.has(value))
976
+ this.line(`${this.slot(value)} = aug_scalar_null();`);
977
+ this.line(`goto ${this.errorTarget};`);
978
+ return;
979
+ }
980
+ if (stmt.kind === 'if') {
981
+ const condition = this.emitExpr(stmt.test);
982
+ this.line(`if (${this.slot(condition)}.as.boolean) {`);
983
+ this.emitScoped(stmt.then);
984
+ this.line('} else {');
985
+ this.emitScoped(stmt.otherwise);
986
+ this.line('}');
987
+ return;
988
+ }
989
+ if (stmt.kind === 'while') {
990
+ this.line('while (1) {');
991
+ this.line('if (aug_execution->fiber || aug_task_checkpoint_hook) aug_task_checkpoint();');
992
+ this.line(`if (aug_cancelled) goto ${this.returnTarget};`);
993
+ const condition = this.emitExpr(stmt.test);
994
+ this.line(`if (!${this.slot(condition)}.as.boolean) break;`);
995
+ this.emitScoped(stmt.body);
996
+ this.line('}');
997
+ return;
998
+ }
999
+ if (stmt.kind === 'scope') {
1000
+ this.line('aug_scope_enter(aug_scoped);');
1001
+ this.line('{');
1002
+ this.emitScoped(stmt.body, true);
1003
+ this.line('}');
1004
+ this.line('aug_scope_leave();');
1005
+ this.line(`if (aug_cancelled) goto ${this.returnTarget};`);
1006
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
1007
+ return;
1008
+ }
1009
+ if (stmt.kind === 'unsafe' || stmt.kind === 'borrow') {
1010
+ this.line('{');
1011
+ this.emitScoped(stmt.body);
1012
+ this.line('}');
1013
+ return;
1014
+ }
1015
+ if (stmt.kind === 'try') {
1016
+ if (stmt.always) {
1017
+ this.emitTryAlways(stmt);
1018
+ return;
1019
+ }
1020
+ const catchLabel = this.label('aug_catch');
1021
+ const afterLabel = this.label('aug_after_catch');
1022
+ const outerTarget = this.errorTarget;
1023
+ const ownedBefore = new Set(this.owned);
1024
+ const scopeDepth = this.label('aug_catch_depth');
1025
+ const lockDepth = this.label('aug_catch_locks');
1026
+ this.line(`size_t ${scopeDepth} = aug_scope_depth();`);
1027
+ this.line(`size_t ${lockDepth} = aug_lock_depth();`);
1028
+ this.errorTarget = catchLabel;
1029
+ this.line('{');
1030
+ this.emitScoped(stmt.body);
1031
+ this.line('}');
1032
+ this.errorTarget = outerTarget;
1033
+ this.line(`goto ${afterLabel};`);
1034
+ this.line(`${catchLabel}:;`);
1035
+ this.line(`aug_scope_restore(${scopeDepth});`);
1036
+ this.line(`aug_lock_restore(${lockDepth});`);
1037
+ this.line(`if (aug_cancelled) goto ${this.returnTarget};`);
1038
+ for (const slot of this.owned)
1039
+ if (!ownedBefore.has(slot))
1040
+ this.line(`if (${this.slot(slot)}.tag != AUG_NULL) { aug_drop(${this.slot(slot)}); ${this.slot(slot)} = aug_scalar_null(); }`);
1041
+ for (const clause of stmt.catches) {
1042
+ this.line(`if (aug_error_is(${cString(clause.type.name)})) {`);
1043
+ const slot = this.newSlot();
1044
+ const prior = this.locals.get(clause.name);
1045
+ this.locals.set(clause.name, slot);
1046
+ this.line(`${this.slot(slot)} = aug_take_error();`);
1047
+ this.emitScoped(clause.body);
1048
+ if (prior === undefined)
1049
+ this.locals.delete(clause.name);
1050
+ else
1051
+ this.locals.set(clause.name, prior);
1052
+ this.line(`goto ${afterLabel};`);
1053
+ this.line('}');
1054
+ }
1055
+ this.line(`goto ${outerTarget};`);
1056
+ this.line(`${afterLabel}:;`);
1057
+ }
1058
+ }
1059
+ emitTryAlways(stmt) {
1060
+ const outerError = this.errorTarget, outerReturn = this.returnTarget;
1061
+ const caught = this.label('aug_final_catch'), failed = this.label('aug_final_error'), returned = this.label('aug_final_return');
1062
+ const cleanup = this.label('aug_always'), done = this.label('aug_always_done'), after = this.label('aug_always_after');
1063
+ const reason = this.label('aug_exit_reason'), depth = this.label('aug_final_depth'), cancellation = this.label('aug_final_cancel');
1064
+ const locks = this.label('aug_final_locks');
1065
+ const pending = this.newSlot();
1066
+ this.line(`int ${reason} = 0; size_t ${depth} = aug_scope_depth(); bool ${cancellation} = false;`);
1067
+ this.line(`size_t ${locks} = aug_lock_depth();`);
1068
+ this.errorTarget = caught;
1069
+ this.returnTarget = returned;
1070
+ this.emitScoped(stmt.body);
1071
+ this.line(`goto ${cleanup};`);
1072
+ this.line(`${caught}:;`);
1073
+ this.line(`aug_scope_restore(${depth}); if (aug_cancelled) goto ${failed};`);
1074
+ this.line(`aug_lock_restore(${locks});`);
1075
+ this.errorTarget = failed;
1076
+ for (const clause of stmt.catches) {
1077
+ this.line(`if (aug_error_is(${cString(clause.type.name)})) {`);
1078
+ const names = new Map(this.locals), slot = this.newSlot();
1079
+ this.locals.set(clause.name, slot);
1080
+ this.line(`${this.slot(slot)} = aug_take_error();`);
1081
+ this.emitScoped(clause.body);
1082
+ this.locals = names;
1083
+ this.line(`goto ${cleanup};`);
1084
+ this.line('}');
1085
+ }
1086
+ this.line(`goto ${failed};`);
1087
+ this.line(`${returned}: ${reason} = 1; goto ${cleanup};`);
1088
+ this.line(`${failed}: ${reason} = 2;`);
1089
+ this.line(`${cleanup}:;`);
1090
+ this.line(`aug_scope_restore(${depth}); ${this.slot(pending)} = aug_has_error ? aug_take_error() : aug_scalar_null();`);
1091
+ this.line(`aug_lock_restore(${locks});`);
1092
+ this.line(`${cancellation} = aug_cancelled; aug_cancelled = false;`);
1093
+ this.errorTarget = done;
1094
+ this.returnTarget = done;
1095
+ this.emitScoped(stmt.always);
1096
+ this.line(`${done}:; aug_cancelled = ${cancellation};`);
1097
+ this.line(`if (!aug_has_error && ${this.slot(pending)}.tag != AUG_NULL) aug_throw(${this.slot(pending)});`);
1098
+ this.line(`if (aug_cancelled || ${reason} == 1) goto ${outerReturn};`);
1099
+ this.line(`if (aug_has_error || ${reason} == 2) goto ${outerError};`);
1100
+ this.line(`goto ${after}; ${after}:;`);
1101
+ this.errorTarget = outerError;
1102
+ this.returnTarget = outerReturn;
1103
+ }
1104
+ emitScoped(body, joinBeforeDrop = false) {
1105
+ const names = new Set(this.locals.keys());
1106
+ const owned = new Set(this.owned);
1107
+ for (const stmt of body)
1108
+ this.emitStatement(stmt);
1109
+ const endingOwned = [...this.owned].filter(slot => !owned.has(slot));
1110
+ if (joinBeforeDrop && endingOwned.length)
1111
+ this.line('aug_scope_join_to(aug_scope_depth() - 1);');
1112
+ for (const slot of endingOwned) {
1113
+ this.line(`aug_drop(${this.slot(slot)}); ${this.slot(slot)} = aug_scalar_null();`);
1114
+ }
1115
+ if (endingOwned.length) {
1116
+ this.line(`if (aug_has_error) goto ${this.errorTarget};`);
1117
+ this.line(`if (aug_cancelled) goto ${this.returnTarget};`);
1118
+ }
1119
+ for (const name of this.locals.keys())
1120
+ if (!names.has(name))
1121
+ this.locals.delete(name);
1122
+ }
1123
+ finish(name, method, paramCount) {
1124
+ const body = this.lines.map(line => ` ${line}`).join('\n')
1125
+ // Match complete C strings first so source text and #line paths are never
1126
+ // interpreted as generated identifiers or slot references.
1127
+ .replace(/"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\broots\[(\d+)\]|\baug_has_error\b|\baug_cancelled\b/g, (token, index) => {
1128
+ if (index !== undefined)
1129
+ return this.scalarSlots.has(Number(index)) ? `scalar_${index}` : token;
1130
+ if (token === 'aug_has_error')
1131
+ return 'aug_execution->has_error';
1132
+ if (token === 'aug_cancelled')
1133
+ return 'aug_execution->cancelled';
1134
+ return token;
1135
+ });
1136
+ const ownedCleanup = [...this.owned].map(slot => ` if (${this.slot(slot)}.tag != AUG_NULL) { aug_drop(${this.slot(slot)}); ${this.slot(slot)} = aug_scalar_null(); }`).join('\n');
1137
+ return [
1138
+ `static AugValue ${name}(${method ? 'AugValue self, ' : ''}AugValue *args, int count) {`,
1139
+ ` (void)args; (void)count;`,
1140
+ ` AugExecution *aug_execution = aug_execution_current();`,
1141
+ ...[...this.scalarSlots].map(slot => ` AugValue scalar_${slot} = {0};`),
1142
+ ` AugValue roots[${Math.max(1, this.slots)}] = {0};`,
1143
+ ` AugFrame frame; aug_frame_enter(&frame, roots, ${Math.max(1, this.slots)});`,
1144
+ ` size_t aug_scope_base = aug_scope_depth();`,
1145
+ ` size_t aug_lock_base = aug_lock_depth();`,
1146
+ ` ${this.slot(0)} = aug_scalar_null();`,
1147
+ body,
1148
+ `aug_cleanup:;`,
1149
+ ` aug_lock_restore(aug_lock_base);`,
1150
+ ` aug_scope_join_to(aug_scope_base);`,
1151
+ ownedCleanup,
1152
+ ` aug_scope_restore(aug_scope_base);`,
1153
+ ` AugValue result = ${this.slot(0)};`,
1154
+ ` aug_frame_leave(&frame);`,
1155
+ ` return result;`,
1156
+ `}`,
1157
+ ].join('\n');
1158
+ }
1159
+ }