@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.
- package/README.md +1 -1
- package/docs/assets/benchmarks/execution.svg +774 -637
- package/docs/assets/benchmarks/http.svg +278 -249
- package/docs/assets/benchmarks/improvements.svg +66 -66
- package/docs/assets/benchmarks/kernels-mobile.svg +1 -0
- package/docs/assets/benchmarks/kernels.svg +1 -0
- package/docs/assets/benchmarks/memory.svg +153 -153
- package/docs/benchmark-results.json +227089 -90363
- package/docs/compatibility.md +6 -6
- package/docs/contributing-benchmarks.md +36 -6
- package/docs/dev-containers.md +8 -15
- package/docs/dgx-consumers.json +122 -0
- package/docs/dgx-gyms.json +784 -0
- package/docs/dgx-kernels.json +1170 -0
- package/docs/dgx-performance.json +227849 -0
- package/docs/dgx-spark.md +64 -0
- package/docs/diagnostics.md +1 -1
- package/docs/docker.md +16 -17
- package/docs/example-projects.json +32 -0
- package/docs/examples/approved-design/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
- package/docs/examples/approved-design/domain/app.md +4 -4
- package/docs/examples/approved-design/main.md +2 -2
- package/docs/examples/calls-benchmark/index.md +36 -0
- package/docs/examples/calls-benchmark/main.md +78 -0
- package/docs/examples/calls-benchmark/operations.md +60 -0
- package/docs/examples/developer-workflow/calculator.md +5 -5
- package/docs/examples/developer-workflow/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
- package/docs/examples/developer-workflow/logging/console.md +2 -2
- package/docs/examples/developer-workflow/logging/logger.md +2 -2
- package/docs/examples/developer-workflow/main.md +2 -2
- package/docs/examples/errors-benchmark/index.md +36 -0
- package/docs/examples/errors-benchmark/main.md +92 -0
- package/docs/examples/errors-benchmark/operations.md +65 -0
- package/docs/examples/float-benchmark/index.md +35 -0
- package/docs/examples/float-benchmark/main.md +75 -0
- package/docs/examples/generic-di/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
- package/docs/examples/generic-di/main.md +2 -2
- package/docs/examples/generic-di/types.md +3 -3
- package/docs/examples/hello/app/greeter.md +3 -3
- package/docs/examples/hello/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
- package/docs/examples/hello/logging/console.md +2 -2
- package/docs/examples/hello/logging/logger.md +2 -2
- package/docs/examples/hello/main.md +2 -2
- package/docs/examples/index.md +18 -1
- package/docs/examples/interceptors/app.md +5 -5
- package/docs/examples/interceptors/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
- package/docs/examples/interceptors/interceptors.md +2 -2
- package/docs/examples/interceptors/logging.md +3 -3
- package/docs/examples/interceptors/main.md +2 -2
- package/docs/examples/list-benchmark/index.md +35 -0
- package/docs/examples/list-benchmark/main.md +78 -0
- package/docs/examples/map-churn-benchmark/index.md +35 -0
- package/docs/examples/map-churn-benchmark/main.md +106 -0
- package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/api.md +104 -0
- package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.md +54 -0
- package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/native.abi-json.md +48 -0
- package/docs/examples/native-blake3/hashing.md +93 -0
- package/docs/examples/native-blake3/index.md +38 -0
- package/docs/examples/native-blake3/main.md +73 -0
- package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/api.md +406 -0
- package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.md +51 -0
- package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.md +63 -0
- package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/native.abi-json.md +161 -0
- package/docs/examples/native-pytorch/index.md +38 -0
- package/docs/examples/native-pytorch/main.md +73 -0
- package/docs/examples/native-pytorch/tensors.md +123 -0
- package/docs/examples/native-sqlite/database.md +116 -0
- package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/api.md +284 -0
- package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.md +51 -0
- package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.md +75 -0
- package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/native.abi-json.md +119 -0
- package/docs/examples/native-sqlite/index.md +38 -0
- package/docs/examples/native-sqlite/main.md +73 -0
- package/docs/examples/native-zlib/compression.md +99 -0
- package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/api.md +153 -0
- package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.md +54 -0
- package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/native.abi-json.md +76 -0
- package/docs/examples/native-zlib/index.md +38 -0
- package/docs/examples/native-zlib/main.md +78 -0
- package/docs/examples/new-syntax/console.md +2 -2
- package/docs/examples/new-syntax/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
- package/docs/examples/new-syntax/greeter.md +3 -3
- package/docs/examples/new-syntax/logger.md +2 -2
- package/docs/examples/new-syntax/main.md +2 -2
- package/docs/examples/ownership-transfer/dependencies/august/{0.20.1 → 0.21.0}/io/contracts.md +3 -3
- package/docs/examples/ownership-transfer/main.md +2 -2
- package/docs/examples/ownership-transfer/resource.md +2 -2
- package/docs/examples/packages-math/aug-package-json.md +1 -1
- package/docs/examples/records-benchmark/data.md +55 -0
- package/docs/examples/records-benchmark/index.md +36 -0
- package/docs/examples/records-benchmark/main.md +85 -0
- package/docs/examples/strings-benchmark/index.md +35 -0
- package/docs/examples/strings-benchmark/main.md +76 -0
- package/docs/examples/tasks-benchmark/index.md +36 -0
- package/docs/examples/tasks-benchmark/main.md +89 -0
- package/docs/examples/tasks-benchmark/operations.md +58 -0
- package/docs/getting-started.md +3 -3
- package/docs/grammar.md +2 -2
- package/docs/gym-results.json +784 -0
- package/docs/implementation-map.md +6 -0
- package/docs/index.md +1 -1
- package/docs/kernel-results.json +1170 -0
- package/docs/language-conformance.md +6 -0
- package/docs/language-constructs.md +9 -1
- package/docs/learn/index.md +1 -1
- package/docs/maintaining-docs.md +1 -1
- package/docs/native-implementation.md +276 -0
- package/docs/native-interop-llvm-plan.md +342 -0
- package/docs/native-package-examples.md +684 -0
- package/docs/native-packages.md +179 -0
- package/docs/packages.md +2 -2
- package/docs/performance.md +50 -29
- package/docs/production-readiness.md +11 -1
- package/docs/public/downloads/approved-design.zip +0 -0
- package/docs/public/downloads/calls-benchmark.zip +0 -0
- package/docs/public/downloads/developer-workflow.zip +0 -0
- package/docs/public/downloads/errors-benchmark.zip +0 -0
- package/docs/public/downloads/float-benchmark.zip +0 -0
- package/docs/public/downloads/generic-di.zip +0 -0
- package/docs/public/downloads/hello.zip +0 -0
- package/docs/public/downloads/interceptors.zip +0 -0
- package/docs/public/downloads/json-benchmark.zip +0 -0
- package/docs/public/downloads/list-benchmark.zip +0 -0
- package/docs/public/downloads/map-churn-benchmark.zip +0 -0
- package/docs/public/downloads/native-blake3.zip +0 -0
- package/docs/public/downloads/native-pytorch.zip +0 -0
- package/docs/public/downloads/native-sqlite.zip +0 -0
- package/docs/public/downloads/native-zlib.zip +0 -0
- package/docs/public/downloads/new-syntax.zip +0 -0
- package/docs/public/downloads/oidc-login.zip +0 -0
- package/docs/public/downloads/ownership-transfer.zip +0 -0
- package/docs/public/downloads/packages-app.zip +0 -0
- package/docs/public/downloads/packages-math.zip +0 -0
- package/docs/public/downloads/records-benchmark.zip +0 -0
- package/docs/public/downloads/strings-benchmark.zip +0 -0
- package/docs/public/downloads/tasks-benchmark.zip +0 -0
- package/docs/qualification-results.md +66 -0
- package/docs/reference.md +24 -0
- package/docs/releasing.md +81 -6
- package/docs/research/libtorch-native-qualification.md +115 -0
- package/docs/research/native-interop-llvm.md +197 -0
- package/docs/research/qualification-methods.md +15 -0
- package/docs/roadmap.md +1 -0
- package/docs/safety-gyms.md +41 -0
- package/docs/tooling.md +16 -15
- package/docs/web-library-gaps.md +1 -1
- package/docs/web.md +4 -0
- package/examples/approved-design/.aug-spec/manifest.json +3 -3
- package/examples/approved-design/domain/app.aug.md +4 -4
- package/examples/approved-design/main.aug.md +2 -2
- package/examples/developer-workflow/.aug-spec/manifest.json +3 -3
- package/examples/developer-workflow/calculator.aug.md +5 -5
- package/examples/developer-workflow/logging/console.aug.md +2 -2
- package/examples/developer-workflow/logging/logger.aug.md +2 -2
- package/examples/developer-workflow/main.aug.md +2 -2
- package/examples/generic-di/.aug-spec/manifest.json +3 -3
- package/examples/generic-di/main.aug.md +2 -2
- package/examples/generic-di/types.aug.md +3 -3
- package/examples/hello/.aug-spec/manifest.json +3 -3
- package/examples/hello/app/greeter.aug.md +3 -3
- package/examples/hello/logging/console.aug.md +2 -2
- package/examples/hello/logging/logger.aug.md +2 -2
- package/examples/hello/main.aug.md +2 -2
- package/examples/interceptors/.aug-spec/manifest.json +3 -3
- package/examples/interceptors/app.aug.md +5 -5
- package/examples/interceptors/interceptors.aug.md +2 -2
- package/examples/interceptors/logging.aug.md +3 -3
- package/examples/interceptors/main.aug.md +2 -2
- package/examples/native-blake3/.aug-spec/manifest.json +16 -0
- package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.1/native.abi.json +29 -0
- package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/api.aug +14 -0
- package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/api.aug.md +34 -0
- package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.aug +4 -0
- package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.aug.md +8 -0
- package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/native.abi.json +29 -0
- package/examples/native-blake3/AGENTS.md +5 -0
- package/examples/native-blake3/aug.lock.json +253 -0
- package/examples/native-blake3/hashing.aug +11 -0
- package/examples/native-blake3/hashing.aug.md +25 -0
- package/examples/native-blake3/main.aug +8 -0
- package/examples/native-blake3/main.aug.md +13 -0
- package/examples/native-pytorch/.aug-spec/manifest.json +18 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.1/native.abi.json +142 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.3/native.abi.json +142 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/api.aug +101 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/api.aug.md +160 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.aug +3 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.aug.md +8 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.aug +6 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.aug.md +13 -0
- package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/native.abi.json +142 -0
- package/examples/native-pytorch/AGENTS.md +5 -0
- package/examples/native-pytorch/aug.lock.json +309 -0
- package/examples/native-pytorch/main.aug +8 -0
- package/examples/native-pytorch/main.aug.md +13 -0
- package/examples/native-pytorch/tensors.aug +23 -0
- package/examples/native-pytorch/tensors.aug.md +35 -0
- package/examples/native-sqlite/.aug-spec/manifest.json +18 -0
- package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.2/native.abi.json +100 -0
- package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/api.aug +48 -0
- package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/api.aug.md +91 -0
- package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.aug +3 -0
- package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.aug.md +8 -0
- package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.aug +8 -0
- package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.aug.md +22 -0
- package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/native.abi.json +100 -0
- package/examples/native-sqlite/AGENTS.md +5 -0
- package/examples/native-sqlite/aug.lock.json +236 -0
- package/examples/native-sqlite/database.aug +15 -0
- package/examples/native-sqlite/database.aug.md +27 -0
- package/examples/native-sqlite/main.aug +8 -0
- package/examples/native-sqlite/main.aug.md +13 -0
- package/examples/native-zlib/.aug-spec/manifest.json +16 -0
- package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.1/native.abi.json +57 -0
- package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/api.aug +29 -0
- package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/api.aug.md +54 -0
- package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.aug +4 -0
- package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.aug.md +8 -0
- package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/native.abi.json +57 -0
- package/examples/native-zlib/AGENTS.md +5 -0
- package/examples/native-zlib/aug.lock.json +236 -0
- package/examples/native-zlib/compression.aug +15 -0
- package/examples/native-zlib/compression.aug.md +27 -0
- package/examples/native-zlib/main.aug +10 -0
- package/examples/native-zlib/main.aug.md +13 -0
- package/examples/new-syntax/.aug-spec/manifest.json +3 -3
- package/examples/new-syntax/console.aug.md +2 -2
- package/examples/new-syntax/greeter.aug.md +3 -3
- package/examples/new-syntax/logger.aug.md +2 -2
- package/examples/new-syntax/main.aug.md +2 -2
- package/examples/oidc-login/aug.lock.json +6 -6
- package/examples/ownership-transfer/.aug-spec/manifest.json +3 -3
- package/examples/ownership-transfer/main.aug.md +2 -2
- package/examples/ownership-transfer/resource.aug.md +2 -2
- package/examples/packages/math/aug-package.json +1 -1
- package/native/compiler-packs.json +43 -0
- package/package.json +3 -2
- package/runtime/aug_http.c +48 -21
- package/runtime/aug_http_ir.c +30 -0
- package/runtime/aug_http_ir.h +18 -0
- package/runtime/aug_ir.c +209 -0
- package/runtime/aug_ir.h +89 -0
- package/runtime/aug_json.c +6 -1
- package/runtime/aug_runtime.c +82 -16
- package/runtime/aug_runtime.h +16 -2
- package/runtime/aug_tasks.c +38 -7
- package/runtime/aug_values.c +12 -6
- package/scripts/bootstrap-native.mjs +4 -1
- package/src/ast.js +1 -1
- package/src/checker.js +110 -28
- package/src/cli.js +92 -14
- package/src/codegen.js +31 -6
- package/src/compiler-packs.js +66 -0
- package/src/config.js +2 -2
- package/src/editor.js +15 -6
- package/src/formatter.js +4 -2
- package/src/git-http.js +137 -0
- package/src/git-packages.js +9 -1
- package/src/help.js +10 -2
- package/src/ir-types.js +5 -0
- package/src/ir-verify.js +277 -0
- package/src/ir.js +962 -0
- package/src/llvm-debug.js +101 -0
- package/src/llvm-native.js +152 -0
- package/src/llvm-platform.js +20 -0
- package/src/llvm.js +781 -0
- package/src/native-artifacts.js +207 -0
- package/src/native-bindings.js +189 -0
- package/src/native-contracts.js +295 -0
- package/src/native-declarations.js +68 -0
- package/src/native-facts.js +63 -0
- package/src/package-locking.js +43 -0
- package/src/package-manager.js +23 -8
- package/src/parser.js +20 -2
- package/src/project.js +2 -2
- package/src/runtime-abi.js +23 -0
- package/src/runtime-adapters.js +18 -0
- package/src/schemas.js +24 -17
- package/src/semantic.js +8 -3
- package/src/snippets.js +1 -0
- package/src/spec.js +49 -8
- /package/examples/approved-design/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
- /package/examples/approved-design/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
- /package/examples/developer-workflow/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
- /package/examples/developer-workflow/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
- /package/examples/generic-di/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
- /package/examples/generic-di/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
- /package/examples/hello/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
- /package/examples/hello/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
- /package/examples/interceptors/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
- /package/examples/interceptors/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
- /package/examples/new-syntax/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
- /package/examples/new-syntax/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug.md +0 -0
- /package/examples/ownership-transfer/.aug-spec/august/{0.20.1 → 0.21.0}/io/contracts.aug +0 -0
- /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
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
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
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
406
|
-
|
|
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
|
-
|
|
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
|
}
|