@greenpandastudios/aug-cli 0.20.1 → 0.21.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 (295) hide show
  1. package/README.md +1 -1
  2. package/docs/assets/benchmarks/execution.svg +774 -637
  3. package/docs/assets/benchmarks/http.svg +278 -249
  4. package/docs/assets/benchmarks/improvements.svg +66 -66
  5. package/docs/assets/benchmarks/kernels-mobile.svg +1 -0
  6. package/docs/assets/benchmarks/kernels.svg +1 -0
  7. package/docs/assets/benchmarks/memory.svg +153 -153
  8. package/docs/benchmark-results.json +227089 -90363
  9. package/docs/compatibility.md +6 -6
  10. package/docs/contributing-benchmarks.md +36 -6
  11. package/docs/dev-containers.md +8 -15
  12. package/docs/dgx-consumers.json +122 -0
  13. package/docs/dgx-gyms.json +784 -0
  14. package/docs/dgx-kernels.json +1170 -0
  15. package/docs/dgx-performance.json +227849 -0
  16. package/docs/dgx-spark.md +64 -0
  17. package/docs/diagnostics.md +1 -1
  18. package/docs/docker.md +16 -17
  19. package/docs/example-projects.json +32 -0
  20. package/docs/examples/approved-design/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
  21. package/docs/examples/approved-design/domain/app.md +4 -4
  22. package/docs/examples/approved-design/main.md +2 -2
  23. package/docs/examples/calls-benchmark/index.md +36 -0
  24. package/docs/examples/calls-benchmark/main.md +78 -0
  25. package/docs/examples/calls-benchmark/operations.md +60 -0
  26. package/docs/examples/developer-workflow/calculator.md +5 -5
  27. package/docs/examples/developer-workflow/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
  28. package/docs/examples/developer-workflow/logging/console.md +2 -2
  29. package/docs/examples/developer-workflow/logging/logger.md +2 -2
  30. package/docs/examples/developer-workflow/main.md +2 -2
  31. package/docs/examples/errors-benchmark/index.md +36 -0
  32. package/docs/examples/errors-benchmark/main.md +92 -0
  33. package/docs/examples/errors-benchmark/operations.md +65 -0
  34. package/docs/examples/float-benchmark/index.md +35 -0
  35. package/docs/examples/float-benchmark/main.md +75 -0
  36. package/docs/examples/generic-di/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
  37. package/docs/examples/generic-di/main.md +2 -2
  38. package/docs/examples/generic-di/types.md +3 -3
  39. package/docs/examples/hello/app/greeter.md +3 -3
  40. package/docs/examples/hello/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
  41. package/docs/examples/hello/logging/console.md +2 -2
  42. package/docs/examples/hello/logging/logger.md +2 -2
  43. package/docs/examples/hello/main.md +2 -2
  44. package/docs/examples/index.md +18 -1
  45. package/docs/examples/interceptors/app.md +5 -5
  46. package/docs/examples/interceptors/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
  47. package/docs/examples/interceptors/interceptors.md +2 -2
  48. package/docs/examples/interceptors/logging.md +3 -3
  49. package/docs/examples/interceptors/main.md +2 -2
  50. package/docs/examples/list-benchmark/index.md +35 -0
  51. package/docs/examples/list-benchmark/main.md +78 -0
  52. package/docs/examples/map-churn-benchmark/index.md +35 -0
  53. package/docs/examples/map-churn-benchmark/main.md +106 -0
  54. package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/api.md +104 -0
  55. package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.md +54 -0
  56. package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/native.abi-json.md +48 -0
  57. package/docs/examples/native-blake3/hashing.md +93 -0
  58. package/docs/examples/native-blake3/index.md +38 -0
  59. package/docs/examples/native-blake3/main.md +73 -0
  60. package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/api.md +406 -0
  61. package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.md +51 -0
  62. package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.md +63 -0
  63. package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/native.abi-json.md +161 -0
  64. package/docs/examples/native-pytorch/index.md +38 -0
  65. package/docs/examples/native-pytorch/main.md +73 -0
  66. package/docs/examples/native-pytorch/tensors.md +123 -0
  67. package/docs/examples/native-sqlite/database.md +116 -0
  68. package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/api.md +284 -0
  69. package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.md +51 -0
  70. package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.md +75 -0
  71. package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/native.abi-json.md +119 -0
  72. package/docs/examples/native-sqlite/index.md +38 -0
  73. package/docs/examples/native-sqlite/main.md +73 -0
  74. package/docs/examples/native-zlib/compression.md +99 -0
  75. package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/api.md +153 -0
  76. package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.md +54 -0
  77. package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/native.abi-json.md +76 -0
  78. package/docs/examples/native-zlib/index.md +38 -0
  79. package/docs/examples/native-zlib/main.md +78 -0
  80. package/docs/examples/new-syntax/console.md +2 -2
  81. package/docs/examples/new-syntax/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
  82. package/docs/examples/new-syntax/greeter.md +3 -3
  83. package/docs/examples/new-syntax/logger.md +2 -2
  84. package/docs/examples/new-syntax/main.md +2 -2
  85. package/docs/examples/ownership-transfer/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
  86. package/docs/examples/ownership-transfer/main.md +2 -2
  87. package/docs/examples/ownership-transfer/resource.md +2 -2
  88. package/docs/examples/packages-math/aug-package-json.md +1 -1
  89. package/docs/examples/records-benchmark/data.md +55 -0
  90. package/docs/examples/records-benchmark/index.md +36 -0
  91. package/docs/examples/records-benchmark/main.md +85 -0
  92. package/docs/examples/strings-benchmark/index.md +35 -0
  93. package/docs/examples/strings-benchmark/main.md +76 -0
  94. package/docs/examples/tasks-benchmark/index.md +36 -0
  95. package/docs/examples/tasks-benchmark/main.md +89 -0
  96. package/docs/examples/tasks-benchmark/operations.md +58 -0
  97. package/docs/getting-started.md +3 -3
  98. package/docs/grammar.md +2 -2
  99. package/docs/gym-results.json +784 -0
  100. package/docs/implementation-map.md +6 -0
  101. package/docs/index.md +1 -1
  102. package/docs/kernel-results.json +1170 -0
  103. package/docs/language-conformance.md +6 -0
  104. package/docs/language-constructs.md +9 -1
  105. package/docs/learn/index.md +1 -1
  106. package/docs/maintaining-docs.md +1 -1
  107. package/docs/native-implementation.md +276 -0
  108. package/docs/native-interop-llvm-plan.md +342 -0
  109. package/docs/native-package-examples.md +684 -0
  110. package/docs/native-packages.md +179 -0
  111. package/docs/packages.md +2 -2
  112. package/docs/performance.md +50 -29
  113. package/docs/production-readiness.md +11 -1
  114. package/docs/public/downloads/approved-design.zip +0 -0
  115. package/docs/public/downloads/calls-benchmark.zip +0 -0
  116. package/docs/public/downloads/developer-workflow.zip +0 -0
  117. package/docs/public/downloads/errors-benchmark.zip +0 -0
  118. package/docs/public/downloads/float-benchmark.zip +0 -0
  119. package/docs/public/downloads/generic-di.zip +0 -0
  120. package/docs/public/downloads/hello.zip +0 -0
  121. package/docs/public/downloads/interceptors.zip +0 -0
  122. package/docs/public/downloads/json-benchmark.zip +0 -0
  123. package/docs/public/downloads/list-benchmark.zip +0 -0
  124. package/docs/public/downloads/map-churn-benchmark.zip +0 -0
  125. package/docs/public/downloads/native-blake3.zip +0 -0
  126. package/docs/public/downloads/native-pytorch.zip +0 -0
  127. package/docs/public/downloads/native-sqlite.zip +0 -0
  128. package/docs/public/downloads/native-zlib.zip +0 -0
  129. package/docs/public/downloads/new-syntax.zip +0 -0
  130. package/docs/public/downloads/oidc-login.zip +0 -0
  131. package/docs/public/downloads/ownership-transfer.zip +0 -0
  132. package/docs/public/downloads/packages-app.zip +0 -0
  133. package/docs/public/downloads/packages-math.zip +0 -0
  134. package/docs/public/downloads/records-benchmark.zip +0 -0
  135. package/docs/public/downloads/strings-benchmark.zip +0 -0
  136. package/docs/public/downloads/tasks-benchmark.zip +0 -0
  137. package/docs/qualification-results.md +66 -0
  138. package/docs/reference.md +24 -0
  139. package/docs/releasing.md +81 -6
  140. package/docs/research/libtorch-native-qualification.md +115 -0
  141. package/docs/research/native-interop-llvm.md +197 -0
  142. package/docs/research/qualification-methods.md +15 -0
  143. package/docs/roadmap.md +1 -0
  144. package/docs/safety-gyms.md +41 -0
  145. package/docs/tooling.md +16 -15
  146. package/docs/web-library-gaps.md +1 -1
  147. package/docs/web.md +4 -0
  148. package/examples/approved-design/.aug-spec/manifest.json +3 -3
  149. package/examples/approved-design/domain/app.aug.md +4 -4
  150. package/examples/approved-design/main.aug.md +2 -2
  151. package/examples/developer-workflow/.aug-spec/manifest.json +3 -3
  152. package/examples/developer-workflow/calculator.aug.md +5 -5
  153. package/examples/developer-workflow/logging/console.aug.md +2 -2
  154. package/examples/developer-workflow/logging/logger.aug.md +2 -2
  155. package/examples/developer-workflow/main.aug.md +2 -2
  156. package/examples/generic-di/.aug-spec/manifest.json +3 -3
  157. package/examples/generic-di/main.aug.md +2 -2
  158. package/examples/generic-di/types.aug.md +3 -3
  159. package/examples/hello/.aug-spec/manifest.json +3 -3
  160. package/examples/hello/app/greeter.aug.md +3 -3
  161. package/examples/hello/logging/console.aug.md +2 -2
  162. package/examples/hello/logging/logger.aug.md +2 -2
  163. package/examples/hello/main.aug.md +2 -2
  164. package/examples/interceptors/.aug-spec/manifest.json +3 -3
  165. package/examples/interceptors/app.aug.md +5 -5
  166. package/examples/interceptors/interceptors.aug.md +2 -2
  167. package/examples/interceptors/logging.aug.md +3 -3
  168. package/examples/interceptors/main.aug.md +2 -2
  169. package/examples/native-blake3/.aug-spec/manifest.json +16 -0
  170. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.1/native.abi.json +29 -0
  171. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/api.aug +14 -0
  172. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/api.aug.md +34 -0
  173. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.aug +4 -0
  174. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.aug.md +8 -0
  175. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/native.abi.json +29 -0
  176. package/examples/native-blake3/AGENTS.md +5 -0
  177. package/examples/native-blake3/aug.lock.json +253 -0
  178. package/examples/native-blake3/hashing.aug +11 -0
  179. package/examples/native-blake3/hashing.aug.md +25 -0
  180. package/examples/native-blake3/main.aug +8 -0
  181. package/examples/native-blake3/main.aug.md +13 -0
  182. package/examples/native-pytorch/.aug-spec/manifest.json +18 -0
  183. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.1/native.abi.json +142 -0
  184. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.3/native.abi.json +142 -0
  185. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/api.aug +101 -0
  186. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/api.aug.md +160 -0
  187. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.aug +3 -0
  188. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.aug.md +8 -0
  189. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.aug +6 -0
  190. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.aug.md +13 -0
  191. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/native.abi.json +142 -0
  192. package/examples/native-pytorch/AGENTS.md +5 -0
  193. package/examples/native-pytorch/aug.lock.json +309 -0
  194. package/examples/native-pytorch/main.aug +8 -0
  195. package/examples/native-pytorch/main.aug.md +13 -0
  196. package/examples/native-pytorch/tensors.aug +23 -0
  197. package/examples/native-pytorch/tensors.aug.md +35 -0
  198. package/examples/native-sqlite/.aug-spec/manifest.json +18 -0
  199. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.2/native.abi.json +100 -0
  200. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/api.aug +48 -0
  201. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/api.aug.md +91 -0
  202. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.aug +3 -0
  203. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.aug.md +8 -0
  204. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.aug +8 -0
  205. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.aug.md +22 -0
  206. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/native.abi.json +100 -0
  207. package/examples/native-sqlite/AGENTS.md +5 -0
  208. package/examples/native-sqlite/aug.lock.json +236 -0
  209. package/examples/native-sqlite/database.aug +15 -0
  210. package/examples/native-sqlite/database.aug.md +27 -0
  211. package/examples/native-sqlite/main.aug +8 -0
  212. package/examples/native-sqlite/main.aug.md +13 -0
  213. package/examples/native-zlib/.aug-spec/manifest.json +16 -0
  214. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.1/native.abi.json +57 -0
  215. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/api.aug +29 -0
  216. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/api.aug.md +54 -0
  217. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.aug +4 -0
  218. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.aug.md +8 -0
  219. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/native.abi.json +57 -0
  220. package/examples/native-zlib/AGENTS.md +5 -0
  221. package/examples/native-zlib/aug.lock.json +236 -0
  222. package/examples/native-zlib/compression.aug +15 -0
  223. package/examples/native-zlib/compression.aug.md +27 -0
  224. package/examples/native-zlib/main.aug +10 -0
  225. package/examples/native-zlib/main.aug.md +13 -0
  226. package/examples/new-syntax/.aug-spec/manifest.json +3 -3
  227. package/examples/new-syntax/console.aug.md +2 -2
  228. package/examples/new-syntax/greeter.aug.md +3 -3
  229. package/examples/new-syntax/logger.aug.md +2 -2
  230. package/examples/new-syntax/main.aug.md +2 -2
  231. package/examples/oidc-login/aug.lock.json +6 -6
  232. package/examples/ownership-transfer/.aug-spec/manifest.json +3 -3
  233. package/examples/ownership-transfer/main.aug.md +2 -2
  234. package/examples/ownership-transfer/resource.aug.md +2 -2
  235. package/examples/packages/math/aug-package.json +1 -1
  236. package/native/compiler-packs.json +43 -0
  237. package/package.json +3 -2
  238. package/runtime/aug_http.c +48 -21
  239. package/runtime/aug_http_ir.c +30 -0
  240. package/runtime/aug_http_ir.h +18 -0
  241. package/runtime/aug_ir.c +209 -0
  242. package/runtime/aug_ir.h +89 -0
  243. package/runtime/aug_json.c +6 -1
  244. package/runtime/aug_runtime.c +82 -16
  245. package/runtime/aug_runtime.h +16 -2
  246. package/runtime/aug_tasks.c +38 -7
  247. package/runtime/aug_values.c +12 -6
  248. package/scripts/bootstrap-native.mjs +4 -1
  249. package/src/ast.js +1 -1
  250. package/src/checker.js +110 -28
  251. package/src/cli.js +92 -14
  252. package/src/codegen.js +31 -6
  253. package/src/compiler-packs.js +66 -0
  254. package/src/config.js +2 -2
  255. package/src/editor.js +15 -6
  256. package/src/formatter.js +4 -2
  257. package/src/git-http.js +137 -0
  258. package/src/git-packages.js +9 -1
  259. package/src/help.js +10 -2
  260. package/src/ir-types.js +5 -0
  261. package/src/ir-verify.js +277 -0
  262. package/src/ir.js +962 -0
  263. package/src/llvm-debug.js +101 -0
  264. package/src/llvm-native.js +152 -0
  265. package/src/llvm-platform.js +20 -0
  266. package/src/llvm.js +781 -0
  267. package/src/native-artifacts.js +207 -0
  268. package/src/native-bindings.js +189 -0
  269. package/src/native-contracts.js +295 -0
  270. package/src/native-declarations.js +68 -0
  271. package/src/native-facts.js +63 -0
  272. package/src/package-locking.js +43 -0
  273. package/src/package-manager.js +23 -8
  274. package/src/parser.js +20 -2
  275. package/src/project.js +2 -2
  276. package/src/runtime-abi.js +23 -0
  277. package/src/runtime-adapters.js +18 -0
  278. package/src/schemas.js +24 -17
  279. package/src/semantic.js +8 -3
  280. package/src/snippets.js +1 -0
  281. package/src/spec.js +49 -8
  282. /package/examples/approved-design/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
  283. /package/examples/approved-design/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
  284. /package/examples/developer-workflow/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
  285. /package/examples/developer-workflow/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
  286. /package/examples/generic-di/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
  287. /package/examples/generic-di/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
  288. /package/examples/hello/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
  289. /package/examples/hello/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
  290. /package/examples/interceptors/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
  291. /package/examples/interceptors/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
  292. /package/examples/new-syntax/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
  293. /package/examples/new-syntax/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
  294. /package/examples/ownership-transfer/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
  295. /package/examples/ownership-transfer/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
package/src/checker.js CHANGED
@@ -15,6 +15,7 @@ import { jsonDataType } from "./schemas.js";
15
15
  import { htmlTags, htmlVoidTags, htmlAttribute, htmlUrlAttributes } from "./html.js";
16
16
  import { generateOpenApi } from "./openapi.js";
17
17
  import { httpPolicyNames, httpPolicyOptions, checkHttpPolicy } from "./http-policies.js";
18
+ import { nativeDeclarations } from "./native-declarations.js";
18
19
  export { tyName } from "./types.js";
19
20
  const builtinNames = new Set(Object.keys(builtinTypes));
20
21
  const errorTy = { id: 'error', name: '<error>', kind: 'error', args: [], nullable: false };
@@ -46,6 +47,7 @@ class Checker {
46
47
  markupCalls = new WeakMap();
47
48
  actions = new Map();
48
49
  httpPolicies = new Map();
50
+ native;
49
51
  bindingByKey = new Map();
50
52
  constructorFreshness = new Map();
51
53
  constraintStack = new Set();
@@ -53,7 +55,7 @@ class Checker {
53
55
  inferring = false;
54
56
  inferenceChanged = false;
55
57
  changingInference = new Set();
56
- constructor(project) { this.project = project; this.diagnostics = [...project.diagnostics]; }
58
+ constructor(project) { this.project = project; this.native = nativeDeclarations(project); this.diagnostics = [...project.diagnostics, ...this.native.diagnostics]; }
57
59
  check() {
58
60
  // Make inherited default bodies visible to forward calls during inference.
59
61
  this.inferring = true;
@@ -174,10 +176,16 @@ class Checker {
174
176
  for (const def of this.project.definitions.values())
175
177
  if (served.has(def.id) && def.node.kind === 'function' && def.node.endpoint?.path === '/__aug/actions.js')
176
178
  this.report(def.node.span, '/__aug/actions.js is reserved for HTTP action transport', 'HTTP');
179
+ for (const [node, layers] of this.interceptorPlans)
180
+ if (node.kind === 'class') {
181
+ for (const [index, layer] of layers.entries())
182
+ layer.constructorResultFresh =
183
+ layers.slice(index + 1).every(inner => this.layerReturnsFresh(inner));
184
+ }
177
185
  return { project: this.project, diagnostics: this.diagnostics, bindings: this.bindings,
178
186
  expressionTypes: this.expressionTypes, defaults: this.defaults, callPlans: this.callPlans,
179
187
  interceptorPlans: this.interceptorPlans, effectContracts: this.effectContracts, callableContracts: this.callableContracts, constructorContracts: this.constructorContracts,
180
- expressionOrigins: this.expressionOrigins, scopes: this.scopes, markupCalls: this.markupCalls, actions: this.actions, httpPolicies: this.httpPolicies };
188
+ expressionOrigins: this.expressionOrigins, scopes: this.scopes, markupCalls: this.markupCalls, actions: this.actions, httpPolicies: this.httpPolicies, native: this.native };
181
189
  }
182
190
  isStatement(item) {
183
191
  return ['expr', 'assign', 'return', 'throw', 'if', 'while', 'for', 'destructure', 'match', 'try', 'unsafe', 'borrow', 'scope', 'freeze', 'serve', 'lock', 'yield'].includes(item.kind);
@@ -323,6 +331,9 @@ class Checker {
323
331
  const args = ref.args.map(arg => this.resolveType(arg, file, params, validateConstraints));
324
332
  if (ref.name !== 'Task' && args.some(arg => arg.id === 'builtin:void'))
325
333
  this.report(ref.span, 'Collections cannot contain void', 'COLLECTION');
334
+ const containsResource = (type) => type.kind === 'resource' || type.args.some(containsResource);
335
+ if (args.some(containsResource))
336
+ this.report(ref.span, 'Native resources require individual own bindings; managed collections cannot retain them', 'OWN');
326
337
  return { ...builtin(ref.name), args,
327
338
  nullable: ref.nullable, optional: ref.optional };
328
339
  }
@@ -427,6 +438,8 @@ class Checker {
427
438
  this.resolveType(param.type, file, params);
428
439
  }
429
440
  this.returnType(fn, file, params);
441
+ if (this.returnType(fn, file, params).kind === 'resource' && fn.returnOwnership !== 'own')
442
+ this.report(fn.span, 'A native resource return must declare returns own', 'OWN');
430
443
  if (fn.endpoint) {
431
444
  const endpoint = fn.endpoint;
432
445
  if (!/^[A-Z]+$/.test(endpoint.method))
@@ -482,22 +495,65 @@ class Checker {
482
495
  this.report(thrown.span, `Thrown type ${typeName(thrown)} must implement Error`);
483
496
  }
484
497
  if (fn.externC) {
485
- if (fn.nativePure && (fn.uses?.length || fn.changes?.length))
486
- this.report(fn.span, 'A pure native declaration cannot declare effects', 'FFI');
487
- if (fn.params.some(param => param.injected))
488
- this.report(fn.span, 'extern C declarations cannot use resolve parameters', 'FFI');
489
- if (fn.typeParams.length || fn.throws.length && !fn.valueAbi)
490
- this.report(fn.span, 'extern C functions cannot be generic or declare unless errors', 'FFI');
491
- if (fn.returnOwnership === 'own' || fn.params.some(param => param.ownership !== 'managed'))
492
- this.report(fn.span, 'extern C functions cannot transfer AugScript ownership', 'FFI');
493
- for (const type of fn.valueAbi ? [] : [...fn.params.map(p => p.type), fn.returns]) {
494
- if (!['int', 'c_int', 'float', 'bool', 'string', 'void'].includes(type.name) || type.args.length || type.nullable)
495
- this.report(type.span, `Type ${typeName(type)} is not supported at the C FFI boundary`, 'FFI');
498
+ const native = this.native.functions.get(fn);
499
+ if (native)
500
+ this.checkNativeSignature(fn, file, native);
501
+ else {
502
+ if (fn.nativePure && (fn.uses?.length || fn.changes?.length))
503
+ this.report(fn.span, 'A pure native declaration cannot declare effects', 'FFI');
504
+ if (fn.params.some(param => param.injected))
505
+ this.report(fn.span, 'extern C declarations cannot use resolve parameters', 'FFI');
506
+ if (fn.typeParams.length || fn.throws.length && !fn.valueAbi)
507
+ this.report(fn.span, 'extern C functions cannot be generic or declare unless errors', 'FFI');
508
+ if (fn.returnOwnership === 'own' || fn.params.some(param => param.ownership !== 'managed'))
509
+ this.report(fn.span, 'extern C functions cannot transfer AugScript ownership', 'FFI');
510
+ for (const type of fn.valueAbi ? [] : [...fn.params.map(p => p.type), fn.returns]) {
511
+ if (!['int', 'c_int', 'float', 'bool', 'string', 'void'].includes(type.name) || type.args.length || type.nullable)
512
+ this.report(type.span, `Type ${typeName(type)} is not supported at the C FFI boundary`, 'FFI');
513
+ }
496
514
  }
497
515
  }
498
516
  if (fn.name === 'drop' && (fn.params.length || fn.throws.length || fn.returns.name !== 'void' || fn.uses?.length))
499
517
  this.report(fn.span, 'drop must take no inputs, return void, and perform only local cleanup; external effects require an explicit method', 'EFFECT');
500
518
  }
519
+ checkNativeSignature(fn, file, binding) {
520
+ const check = (type, view, span) => {
521
+ const name = view.kind === 'i64' ? 'int' : view.kind === 'i32' ? 'c_int' : view.kind === 'f64' ? 'float' : view.kind === 'utf8' ? 'string' : view.kind === 'bytes' ? 'Bytes' : view.kind;
522
+ const valid = view.kind === 'resource' ? type.kind === 'resource' && this.native.resources.get(type.def.node)?.module + '.' + type.name === view.resource && this.native.providers.get(type.def.node) === this.native.providers.get(fn) :
523
+ view.kind === 'f64-list' || view.kind === 'utf8-list' ? type.name === 'List' && type.args.length === 1 && type.args[0].name === (view.kind === 'f64-list' ? 'float' : 'string') : type.name === name;
524
+ if (!valid || type.nullable || type.optional)
525
+ this.report(span, `Native contract expects ${view.resource ?? view.kind}, got ${tyName(type)}`, 'NATIVE_ABI');
526
+ };
527
+ if (fn.body || fn.typeParams.length || fn.params.some(p => p.injected) || fn.annotations?.length)
528
+ this.report(fn.span, 'Native ABI declarations have concrete inputs, no body, no resolve parameters, and no interceptors', 'NATIVE_ABI');
529
+ if (fn.params.length !== binding.params.length)
530
+ this.report(fn.span, 'Native parameter count differs from the binding descriptor', 'NATIVE_ABI');
531
+ fn.params.forEach((p, i) => {
532
+ const view = binding.params[i];
533
+ if (!view)
534
+ return;
535
+ if (p.name !== view.name)
536
+ this.report(p.span, 'Native parameter label differs from the binding descriptor: ' + view.name, 'NATIVE_ABI');
537
+ check(this.resolveType(p.type, file), view, p.span);
538
+ const ownership = view.kind === 'resource' ? view.ownership === 'consume' ? 'own' : view.ownership === 'borrow' ? 'borrow' : 'managed' : 'managed';
539
+ if (p.ownership !== ownership)
540
+ this.report(p.span, 'Native parameter ownership differs from its binding descriptor', 'NATIVE_ABI');
541
+ });
542
+ check(this.returnType(fn, file), binding.result, fn.returns.span);
543
+ if ((binding.result.kind === 'resource') !== (fn.returnOwnership === 'own'))
544
+ this.report(fn.span, 'Native result ownership differs from its binding descriptor', 'NATIVE_ABI');
545
+ const errors = fn.throws.map(t => this.resolveType(t, file));
546
+ if (errors.length !== (binding.error ? 1 : 0) || binding.error && errors[0]?.def?.id !== this.native.errors.get(fn)?.id)
547
+ this.report(fn.span, 'Native checked errors differ from the binding descriptor', 'NATIVE_ABI');
548
+ if (binding.error) {
549
+ const error = errors[0]?.def?.node;
550
+ if (error?.kind !== 'class' || error.typeParams.length || error.fields.length !== 2 || error.fields[0].name !== 'code' || error.fields[0].type.name !== 'int' || error.fields[1].name !== 'message' || error.fields[1].type.name !== 'string' || error.fields.some(p => p.injected || p.ownership !== 'managed' || p.type.nullable || p.type.optional || p.type.args.length) || initializationOf(error).length || error.annotations?.length)
551
+ this.report(fn.span, 'Native status errors require an Error class with int code and string message inputs and no constructor work', 'NATIVE_ABI');
552
+ }
553
+ const uses = (fn.uses ?? []).map(u => u.source + '.' + u.operation).sort(), changes = [...(fn.changes ?? [])].sort();
554
+ if (JSON.stringify(uses) !== JSON.stringify([...binding.uses].sort()) || JSON.stringify(changes) !== JSON.stringify([...binding.changes].sort()))
555
+ this.report(fn.span, 'Native effects or mutation differ from the binding descriptor', 'NATIVE_ABI');
556
+ }
501
557
  checkInterceptorShape(def) {
502
558
  const node = def.node;
503
559
  const types = this.paramsFor(node.typeParams, node, def.file);
@@ -763,6 +819,11 @@ class Checker {
763
819
  if (!cls.record && cls.implements.length === 0)
764
820
  this.report(cls.span, `${cls.name} must implement at least one interface`, 'INTERFACE');
765
821
  const params = this.paramsFor(cls.typeParams, cls, def.file);
822
+ for (const error of cls.validationErrors ?? []) {
823
+ const type = this.resolveType(error, def.file, params);
824
+ if (!this.implementsError(type))
825
+ this.report(error.span, `Thrown type ${typeName(error)} must implement Error`);
826
+ }
766
827
  this.checkVariance(cls, def.file);
767
828
  const names = new Set();
768
829
  for (const field of fieldsOf(cls)) {
@@ -770,6 +831,8 @@ class Checker {
770
831
  this.report(field.span, `Duplicate field ${field.name}`);
771
832
  names.add(field.name);
772
833
  this.resolveType(field.type, def.file, params);
834
+ if (this.resolveType(field.type, def.file, params).kind === 'resource' && field.ownership !== 'own')
835
+ this.report(field.span, 'Native resource fields require own ownership', 'OWN');
773
836
  if (cls.record && (field.mutable || field.injected || field.ownership !== 'managed'))
774
837
  this.report(field.span, 'Record fields are immutable data; dependencies and ownership belong in behavioral classes', 'RECORD');
775
838
  if (cls.record && !this.immutableData(this.resolveType(field.type, def.file, params)))
@@ -994,6 +1057,8 @@ class Checker {
994
1057
  continue;
995
1058
  }
996
1059
  const interfaceDef = this.project.scopes.get(item.span.file)?.get(item.key);
1060
+ if (target.node.validationErrors?.length)
1061
+ this.report(item.span, `${target.name} has a checked constructor failure; construct it explicitly and catch or propagate the error instead of binding it`, 'DI');
997
1062
  let exposedType = targetType;
998
1063
  if (interfaceDef?.node.kind === 'interface') {
999
1064
  exposedType = this.resolveType({ name: item.key, args: item.keyTypeArgs,
@@ -1554,6 +1619,8 @@ class Checker {
1554
1619
  const expected = stmt.declaredType ? this.resolveType(stmt.declaredType, context.file, context.types) :
1555
1620
  stmt.target.kind === 'name' ? context.locals.get(stmt.target.name)?.declaredType ?? context.locals.get(stmt.target.name)?.type : undefined;
1556
1621
  const value = this.checkExpression(stmt.value, context, expected);
1622
+ if (value.kind === 'resource' && stmt.target.kind === 'name' && stmt.ownership !== 'own' && context.locals.get(stmt.target.name)?.origin !== 'field')
1623
+ this.report(stmt.span, 'Native resources must be held by own bindings', 'OWN');
1557
1624
  const source = stmt.value.kind === 'name' ? context.locals.get(stmt.value.name) : undefined;
1558
1625
  const origins = this.placesOf(stmt.value, context);
1559
1626
  const ownedSource = this.ownershipOf(stmt.value, context) === 'own';
@@ -1585,9 +1652,9 @@ class Checker {
1585
1652
  context.flow.declare(stmt.target.name, origins, !!value.readonly, { source: sourceName(stmt.value) });
1586
1653
  }
1587
1654
  else if (existing) {
1588
- if (existing.ownership === 'own')
1655
+ if (existing.ownership === 'own' && existing.origin !== 'field')
1589
1656
  this.report(stmt.target.span, `Reassigning owned value ${stmt.target.name} is not supported; use a new scope`, 'OWN');
1590
- if (source?.ownership === 'own')
1657
+ if (source?.ownership === 'own' && !(existing.origin === 'field' && existing.ownership === 'own'))
1591
1658
  this.report(stmt.value.span, 'Cannot copy an owned value into a managed variable', 'OWN');
1592
1659
  if (existing.origin === 'field' && existing.ownership !== 'own' &&
1593
1660
  !context.initializing && !context.borrowed.has('self') && context.locals.get('self')?.ownership !== 'borrow')
@@ -1613,6 +1680,12 @@ class Checker {
1613
1680
  existing.type = { ...declared, nullable: value.nullable, optional: value.optional, readonly: value.readonly, frozen: value.frozen };
1614
1681
  context.flow.rebind(stmt.target.name, origins, !!value.readonly, stmt.span, (span, message) => this.report(span, message, 'BORROW'), sourceName(stmt.value));
1615
1682
  existing.moved = false;
1683
+ if (existing.origin === 'field' && existing.ownership === 'own') {
1684
+ if (source?.ownership === 'own' && stmt.value.kind === 'name')
1685
+ this.moveOwnedLocal(stmt.value.name, stmt.value.span, context);
1686
+ else if (!['own', 'fresh'].includes(this.ownershipOf(stmt.value, context)))
1687
+ this.report(stmt.value.span, 'An owned field requires a new object or another owned value', 'OWN');
1688
+ }
1616
1689
  }
1617
1690
  else {
1618
1691
  if (source?.ownership === 'own')
@@ -1638,6 +1711,8 @@ class Checker {
1638
1711
  const node = object.def?.node;
1639
1712
  const fieldName = stmt.target.name;
1640
1713
  const field = node?.kind === 'class' || node?.kind === 'interceptor' ? fieldsOf(node).find(item => item.name === fieldName) : undefined;
1714
+ if (value.kind === 'resource' && field?.ownership !== 'own')
1715
+ this.report(stmt.span, 'Native resources must be held by own fields', 'OWN');
1641
1716
  if (!(context.initializing && root === 'self') && !field?.mutable)
1642
1717
  this.report(stmt.target.span, `Field ${fieldName} is read-only; declare mutable storage`, 'MUTABILITY');
1643
1718
  if (object.readonly && !(context.initializing && root === 'self'))
@@ -1986,21 +2061,22 @@ class Checker {
1986
2061
  if (visiting.has(node))
1987
2062
  return false;
1988
2063
  visiting.add(node);
1989
- const result = (this.interceptorPlans.get(node) ?? []).every(layer => {
1990
- const interceptor = layer.definition.node;
1991
- return returnsFresh(layer.around.body ?? [], new Set(interceptor.fields.map(field => field.name)), expr => {
1992
- if (expr.kind !== 'call' || expr.callee.kind !== 'name')
1993
- return false;
1994
- if (expr.callee.name === 'next')
1995
- return true;
1996
- const def = this.project.scopes.get(layer.definition.file)?.get(expr.callee.name);
1997
- return def?.node.kind === 'class' && this.constructorIsFresh(def.node, visiting);
1998
- });
1999
- });
2064
+ const result = (this.interceptorPlans.get(node) ?? []).every(layer => this.layerReturnsFresh(layer, visiting));
2000
2065
  visiting.delete(node);
2001
2066
  this.constructorFreshness.set(node, result);
2002
2067
  return result;
2003
2068
  }
2069
+ layerReturnsFresh(layer, visiting = new Set()) {
2070
+ const interceptor = layer.definition.node;
2071
+ return returnsFresh(layer.around.body ?? [], new Set(interceptor.fields.map(field => field.name)), expr => {
2072
+ if (expr.kind !== 'call' || expr.callee.kind !== 'name')
2073
+ return false;
2074
+ if (expr.callee.name === 'next')
2075
+ return true;
2076
+ const def = this.project.scopes.get(layer.definition.file)?.get(expr.callee.name);
2077
+ return def?.node.kind === 'class' && this.constructorIsFresh(def.node, visiting);
2078
+ });
2079
+ }
2004
2080
  checkAllowedError(type, span, context) {
2005
2081
  if (context.deferredErrors) {
2006
2082
  context.deferredErrors.push(type);
@@ -2146,6 +2222,8 @@ class Checker {
2146
2222
  type = { ...builtin('Task'), args: [result] };
2147
2223
  if (expr.call.kind === 'call' && context.scope) {
2148
2224
  const plan = this.callPlans.get(expr.call), task = [...allocationOrigin(expr.span)][0], scope = `tasks:${context.scope.file}:${context.scope.start}`;
2225
+ if (plan?.returnOwnership === 'own')
2226
+ this.report(expr.call.span, 'A task cannot return an owned value. Return immutable data, or create and release the owned resource inside the task.', 'CONCURRENCY');
2149
2227
  context.flow.registerTask(task, scope, errors);
2150
2228
  const captureOrigins = (origins, actual, exclusive, span) => {
2151
2229
  if (!this.isReference(actual))
@@ -2299,6 +2377,9 @@ class Checker {
2299
2377
  }
2300
2378
  else if (expr.kind === 'call') {
2301
2379
  type = this.checkCall(expr, context);
2380
+ const plan = this.callPlans.get(expr);
2381
+ if (plan)
2382
+ plan.returnOwnership = this.ownershipOf(expr, context) === 'own' ? 'own' : 'managed';
2302
2383
  }
2303
2384
  this.expressionTypes.set(expr, type);
2304
2385
  this.expressionOrigins.set(expr, this.placesOf(expr, context));
@@ -2611,6 +2692,7 @@ class Checker {
2611
2692
  }
2612
2693
  if (expr.callee.kind === 'name' && expr.callee.name === 'Shared') {
2613
2694
  const plan = this.planCall(expr, ['value'], 'Shared'), index = plan.sourceIndices[0];
2695
+ plan.ownerships = ['own'];
2614
2696
  const result = index === undefined ? errorTy : argTypes[index];
2615
2697
  if (index !== undefined && !['fresh', 'own'].includes(this.ownershipOf(expr.args[index], context)))
2616
2698
  this.report(expr.args[index].span, 'Shared takes a fresh value or an owned value; existing mutable aliases cannot survive the transfer', 'OWN');
@@ -2915,7 +2997,7 @@ class Checker {
2915
2997
  }
2916
2998
  if (fn.externC && !context.unsafe)
2917
2999
  this.report(expr.span, `Call to extern C function ${fn.name} requires unsafe { ... }`, 'FFI');
2918
- if (fn.externC && !fn.nativePure && !(fn.valueAbi && fn.uses?.length)) {
3000
+ if (fn.externC && !fn.nativePure && !this.native.functions.has(fn) && !(fn.valueAbi && fn.uses?.length)) {
2919
3001
  const native = this.project.scopes.get(fnFile)?.get(fn.name);
2920
3002
  this.requireUse(`C:${native?.id ?? fn.name}`, `C.${fn.name}`, expr.span, context);
2921
3003
  }
@@ -3053,7 +3135,7 @@ class Checker {
3053
3135
  else if (!['own', 'fresh'].includes(this.ownershipOf(argument, context)))
3054
3136
  this.report(argument.span, 'Owned field requires a new object or owned argument', 'OWN');
3055
3137
  }
3056
- else if (this.ownershipOf(argument, context) === 'own' && param.ownership !== 'borrow')
3138
+ else if (this.ownershipOf(argument, context) === 'own' && param.ownership !== 'borrow' && this.expressionTypes.get(argument)?.kind !== 'resource')
3057
3139
  this.report(argument.span, 'Cannot copy an owned value into managed storage', 'OWN');
3058
3140
  if (param.ownership === 'borrow') {
3059
3141
  if (context.flow.hasTaskCapture(this.placesOf(argument, context)))
package/src/cli.js CHANGED
@@ -4,6 +4,13 @@ import { spawnSync } from 'node:child_process';
4
4
  import { typeName } from "./ast.js";
5
5
  import { checkProject } from "./checker.js";
6
6
  import { generateC } from "./codegen.js";
7
+ import { generateLLVM } from "./llvm.js";
8
+ import { lowerToIR, BackendUnsupported } from "./ir.js";
9
+ import { IRVerificationError } from "./ir-verify.js";
10
+ import { compileLLVM } from "./llvm-native.js";
11
+ import { prepareNativePackages } from "./native-artifacts.js";
12
+ import { prepareLLVMCompiler } from "./compiler-packs.js";
13
+ import { bindNativeHeader } from "./native-bindings.js";
7
14
  import { diagnosticHelp } from "./help.js";
8
15
  import { loadProject } from "./project.js";
9
16
  import { definitionAt } from "./navigation.js";
@@ -55,9 +62,10 @@ function printDiagnostics(diagnostics, json, root) {
55
62
  }
56
63
  function usage() {
57
64
  process.stdout.write(`AugScript compiler\n\n` +
58
- `Usage: aug <init|check|build|run|emit-c|test|openapi|format|migrate|spec|bench|explain|context|lsp|symbols|definition|complete|hover|fixes|semantic-tokens> [project directory] [options] [-- args]\n` +
65
+ `Usage: aug <init|check|build|run|emit-c|emit-llvm|emit-ir|test|openapi|format|migrate|spec|bench|explain|context|lsp|symbols|definition|complete|hover|fixes|semantic-tokens> [project directory] [options] [-- args]\n` +
59
66
  `New application: aug init DIRECTORY [--template hello|weather]\n` +
60
67
  `Run: aug run [project directory] [--offline] [-- args] — prepare dependencies, compile, and start\n` +
68
+ `Backend: LLVM is the default on macOS 14+ ARM64 and GNU/Linux x64/ARM64 with glibc 2.36+. August installs its compiler pack; no separate native toolchain is needed. --backend c selects the migration reference.\n` +
61
69
  `Tests: aug test [project directory] [GROUP_NAME] [--group GROUP_NAME] [--list] [--coverage] [--json] [--timeout milliseconds]\n` +
62
70
  `Format: aug format [project directory] [--file path] [--write]\n` +
63
71
  `Specifications: aug spec [project directory] [--check] [--json]\n` +
@@ -66,6 +74,7 @@ function usage() {
66
74
  `Benchmark: aug bench [project directory] [--iterations 10] [--warmup 2] [--json] [-- args]\n` +
67
75
  `Packages: aug package init DIRECTORY --name @owner/name; aug package pack DIRECTORY\n` +
68
76
  `Dependencies: aug add URL --as NAME [--project DIRECTORY]; aug install [project directory] [--frozen|--update] [--offline]\n` +
77
+ `Native maintainers: aug bind header HEADER --contract native.abi.json --target TRIPLE --output DIRECTORY --clang PATH [-- CLANG_FLAGS]\n` +
69
78
  `Entry point: main.aug at the project root.\n`);
70
79
  }
71
80
  export async function main(argv) {
@@ -80,6 +89,34 @@ export async function main(argv) {
80
89
  usage();
81
90
  return 0;
82
91
  }
92
+ if (command === 'bind') {
93
+ const boundary = argv.indexOf('--'), arguments_ = boundary < 0 ? argv : argv.slice(0, boundary), values = {};
94
+ if (arguments_[1] !== 'header' || !arguments_[2] || arguments_[2].startsWith('--')) {
95
+ process.stderr.write('Use aug bind header HEADER --contract FILE --target TRIPLE --output DIRECTORY --clang PATH\n');
96
+ return 2;
97
+ }
98
+ for (let index = 3; index < arguments_.length; index++) {
99
+ const flag = arguments_[index];
100
+ if (!['--contract', '--target', '--output', '--clang'].includes(flag) || values[flag] !== undefined || !arguments_[index + 1] || arguments_[index + 1].startsWith('--')) {
101
+ process.stderr.write('Invalid or duplicate native binding option: ' + flag + '\n');
102
+ return 2;
103
+ }
104
+ values[flag] = arguments_[++index];
105
+ }
106
+ if (['--contract', '--target', '--output', '--clang'].some(flag => !values[flag])) {
107
+ process.stderr.write('Native header validation requires --contract, --target, --output and --clang. No tool is installed automatically.\n');
108
+ return 2;
109
+ }
110
+ try {
111
+ bindNativeHeader({ header: arguments_[2], contract: values['--contract'], target: values['--target'], output: values['--output'], clang: values['--clang'], flags: boundary < 0 ? [] : argv.slice(boundary + 1) });
112
+ process.stdout.write('Checked native declarations written to ' + resolve(values['--output']) + '\n');
113
+ return 0;
114
+ }
115
+ catch (error) {
116
+ process.stderr.write(failureMessage(error) + '\n');
117
+ return 1;
118
+ }
119
+ }
83
120
  if (command === 'add') {
84
121
  const aliasIndex = argv.indexOf('--as'), projectIndex = argv.indexOf('--project');
85
122
  if (!argv[1] || argv[1].startsWith('--') || aliasIndex < 0 || !argv[aliasIndex + 1]) {
@@ -99,6 +136,7 @@ export async function main(argv) {
99
136
  try {
100
137
  const alias = argv[aliasIndex + 1], root = resolve(projectIndex < 0 ? process.cwd() : argv[projectIndex + 1]);
101
138
  const lock = addPackage(root, argv[1], alias, argv.includes('--offline'));
139
+ await prepareNativePackages(root, { offline: argv.includes('--offline') });
102
140
  process.stdout.write(`Added ${alias}; installed ${lock.packages.length} source package(s).\nImport public names with: import NAME from ${alias}\n`);
103
141
  return 0;
104
142
  }
@@ -129,6 +167,7 @@ export async function main(argv) {
129
167
  ? (command === 'install' ? argv[1] : argv[2]) : process.cwd());
130
168
  if (command === 'install') {
131
169
  const lock = installPackages(root, argv.includes('--frozen'), argv.includes('--offline'), argv.includes('--update'));
170
+ await prepareNativePackages(root, { offline: argv.includes('--offline'), frozen: argv.includes('--frozen') });
132
171
  process.stdout.write(`Installed ${lock.packages.length} August package(s); aug.lock.json is current.\n`);
133
172
  }
134
173
  else if (argv[1] === 'init') {
@@ -163,7 +202,7 @@ export async function main(argv) {
163
202
  }
164
203
  if (command === 'lsp')
165
204
  return runLanguageServer(resolve(argv[1] ?? process.cwd()));
166
- if (!['check', 'build', 'run', 'emit-c', 'test', 'openapi', 'format', 'migrate', 'spec', 'bench', 'explain', 'context', 'symbols', 'definition',
205
+ if (!['check', 'build', 'run', 'emit-c', 'emit-llvm', 'emit-ir', 'test', 'openapi', 'format', 'migrate', 'spec', 'bench', 'explain', 'context', 'symbols', 'definition',
167
206
  'complete', 'hover', 'fixes', 'semantic-tokens'].includes(command)) {
168
207
  process.stderr.write(`Unknown command ${command}\n`);
169
208
  usage();
@@ -176,8 +215,8 @@ export async function main(argv) {
176
215
  usage();
177
216
  return 0;
178
217
  }
179
- const valueOptions = new Set(['--out', '--stdin-file', '--file', '--name', '--offset', '--budget', '--baseline', '--group', '--case', '--timeout', '--iterations', '--warmup']);
180
- const booleanOptions = new Set(['--json', '--coverage', '--list', '--write', '--check', '--offline']);
218
+ const valueOptions = new Set(['--backend', '--out', '--stdin-file', '--file', '--name', '--offset', '--budget', '--baseline', '--group', '--case', '--timeout', '--iterations', '--warmup']);
219
+ const booleanOptions = new Set(['--json', '--coverage', '--list', '--write', '--check', '--offline', '--frozen']);
181
220
  for (let index = 0; index < options.length; index++) {
182
221
  const option = options[index];
183
222
  if (valueOptions.has(option)) {
@@ -193,6 +232,12 @@ export async function main(argv) {
193
232
  }
194
233
  }
195
234
  const json = options.includes('--json');
235
+ const backendIndex = options.indexOf('--backend');
236
+ let backend = backendIndex < 0 ? 'llvm' : options[backendIndex + 1];
237
+ if (!['c', 'llvm'].includes(backend)) {
238
+ process.stderr.write('--backend must be c or llvm\n');
239
+ return 2;
240
+ }
196
241
  const outIndex = options.indexOf('--out');
197
242
  const outputOption = outIndex >= 0 ? options[outIndex + 1] : undefined;
198
243
  const stdinIndex = options.indexOf('--stdin-file');
@@ -217,6 +262,7 @@ export async function main(argv) {
217
262
  const iterations = iterationsIndex >= 0 ? Number(options[iterationsIndex + 1]) : 10;
218
263
  const warmup = warmupIndex >= 0 ? Number(options[warmupIndex + 1]) : 2;
219
264
  const positionals = options.filter((arg, i) => !arg.startsWith('--') &&
265
+ (backendIndex < 0 || i !== backendIndex + 1) &&
220
266
  (outIndex < 0 || i !== outIndex + 1) &&
221
267
  (stdinIndex < 0 || i !== stdinIndex + 1) &&
222
268
  (fileIndex < 0 || i !== fileIndex + 1) &&
@@ -250,8 +296,10 @@ export async function main(argv) {
250
296
  if (!existsSync(root) || !statSync(root).isDirectory())
251
297
  throw new Error(`Project directory does not exist: ${root}\nUse aug init DIRECTORY to create a project, or run aug run from the folder containing main.aug.`);
252
298
  if (command === 'run')
253
- prepareRunPackages(root, options.includes('--offline'));
299
+ prepareRunPackages(root, options.includes('--offline'), options.includes('--frozen'));
254
300
  const project = loadProject(root, overrides);
301
+ if (backendIndex < 0)
302
+ backend = project.config.backend ?? 'llvm';
255
303
  if (project.library && ['build', 'run', 'bench', 'openapi'].includes(command))
256
304
  throw new Error('This is an August library; use check, test, or package pack. Import its exports from an application with main.aug to run it.');
257
305
  if (command === 'format' || command === 'migrate') {
@@ -296,10 +344,17 @@ export async function main(argv) {
296
344
  }
297
345
  const results = [];
298
346
  const coverage = options.includes('--coverage'), reports = [];
347
+ const nativeInputs = backend === 'llvm' ? await prepareNativePackages(root, { offline: options.includes('--offline'), frozen: options.includes('--frozen') }) : undefined;
348
+ const toolchain = backend === 'llvm' ? await prepareLLVMCompiler(options.includes('--offline'), { root, frozen: options.includes('--frozen') }) : undefined;
299
349
  for (const [index, { unit, checked: testChecked }] of checks.entries()) {
300
- const generated = generateC(testChecked, { coverage });
301
- await prepareNativeDependencies(generated, { offline: options.includes('--offline') });
302
- const native = compileNative(root, generated, { testIndex: index, checked: testChecked });
350
+ let native;
351
+ if (backend === 'llvm')
352
+ native = compileLLVM(testChecked, { testIndex: index, coverage, native: nativeInputs, toolchain });
353
+ else {
354
+ const generated = generateC(testChecked, { coverage });
355
+ await prepareNativeDependencies(generated, { offline: options.includes('--offline') });
356
+ native = compileNative(root, generated, { testIndex: index, checked: testChecked });
357
+ }
303
358
  const report = join(root, '.aug-build', 'tests', `coverage-${index}.tsv`);
304
359
  reports.push(report);
305
360
  if (coverage)
@@ -387,23 +442,41 @@ export async function main(argv) {
387
442
  process.stdout.write(json ? JSON.stringify(result) + '\n' : result.stale.length ? 'Stale specifications:\n' + result.stale.map(file => ' ' + file).join('\n') + '\n' : `${result.files} specification artifact(s) ${options.includes('--check') ? 'are current' : 'generated'}.\n`);
388
443
  return result.stale.length ? 1 : 0;
389
444
  }
390
- if (['build', 'run', 'bench'].includes(command)) {
445
+ if (['build', 'run', 'bench'].includes(command) && !options.includes('--frozen')) {
391
446
  checked = updateSpecHints(checked);
392
447
  if (checked.diagnostics.some(issue => issue.severity !== 'warning')) {
393
448
  printDiagnostics(checked.diagnostics, json, root);
394
449
  return 1;
395
450
  }
396
451
  }
397
- const generated = generateC(checked);
452
+ if (command === 'emit-llvm') {
453
+ process.stdout.write(generateLLVM(lowerToIR(checked)));
454
+ return 0;
455
+ }
456
+ if (command === 'emit-ir') {
457
+ process.stdout.write(JSON.stringify(lowerToIR(checked), null, 2) + '\n');
458
+ return 0;
459
+ }
460
+ if ((backend === 'c' || command === 'emit-c') && checked.native.resources.size + checked.native.functions.size)
461
+ throw new Error('NATIVE_BACKEND: Checked native packages require --backend llvm. The C reference backend cannot lower this native ABI.');
398
462
  if (command === 'emit-c') {
399
- process.stdout.write(generated);
463
+ process.stdout.write(generateC(checked));
400
464
  return 0;
401
465
  }
402
466
  if (command === 'bench' && (!Number.isInteger(iterations) || iterations < 1 || iterations > 1000 ||
403
467
  !Number.isInteger(warmup) || warmup < 0 || warmup > 100 || !Number.isInteger(timeout) || timeout < 1))
404
468
  throw new Error('bench requires iterations 1–1000, warmup 0–100, and a positive timeout');
405
- await prepareNativeDependencies(generated, { offline: options.includes('--offline') });
406
- const native = compileNative(root, generated, { output: outputOption, release: command === 'bench' ? true : undefined, checked });
469
+ let native;
470
+ if (backend === 'llvm') {
471
+ const inputs = await prepareNativePackages(root, { offline: options.includes('--offline'), frozen: options.includes('--frozen') });
472
+ const toolchain = await prepareLLVMCompiler(options.includes('--offline'), { root, frozen: options.includes('--frozen') });
473
+ native = compileLLVM(checked, { output: outputOption, release: command === 'bench' || project.config.optimization === 'release', native: inputs, toolchain });
474
+ }
475
+ else {
476
+ const generated = generateC(checked);
477
+ await prepareNativeDependencies(generated, { offline: options.includes('--offline') });
478
+ native = compileNative(root, generated, { output: outputOption, release: command === 'bench' ? true : undefined, checked });
479
+ }
407
480
  const output = native.output;
408
481
  if (native.status !== 0) {
409
482
  if (native.diagnostics.length)
@@ -412,7 +485,8 @@ export async function main(argv) {
412
485
  process.stderr.write(native.error + '\n');
413
486
  return native.status;
414
487
  }
415
- updateSpecs(checked);
488
+ if (!options.includes('--frozen'))
489
+ updateSpecs(checked);
416
490
  if (command === 'build') {
417
491
  process.stdout.write(json ? JSON.stringify({ output, sourceMap: output + '.augmap.json' }) + '\n' : `${output}\n`);
418
492
  return 0;
@@ -432,6 +506,10 @@ export async function main(argv) {
432
506
  return run.status ?? 1;
433
507
  }
434
508
  catch (error) {
509
+ if (error instanceof BackendUnsupported || error instanceof IRVerificationError) {
510
+ printDiagnostics([{ ...error.span, code: error.code, message: error.message }], json, root);
511
+ return 1;
512
+ }
435
513
  process.stderr.write(failureMessage(error) + '\n');
436
514
  return error instanceof Error && 'exitCode' in error && typeof error.exitCode === 'number' ? error.exitCode : 1;
437
515
  }