semantifold 0.3.0 → 0.5.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 +61 -15
- package/build/index.d.ts +52 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +60 -8
- package/build/src/artifact-path.d.ts +23 -1
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +45 -3
- package/build/src/artifacts.d.ts.map +1 -1
- package/build/src/artifacts.js +66 -1
- package/build/src/backends/android.d.ts +49 -0
- package/build/src/backends/android.d.ts.map +1 -0
- package/build/src/backends/android.js +1274 -0
- package/build/src/backends/c-validation.d.ts.map +1 -1
- package/build/src/backends/c-validation.js +7 -3
- package/build/src/backends/cpp-validation.d.ts.map +1 -1
- package/build/src/backends/cpp-validation.js +7 -3
- package/build/src/backends/csharp.js +7 -1
- package/build/src/backends/dart-runtime.d.ts +2 -0
- package/build/src/backends/dart-runtime.d.ts.map +1 -0
- package/build/src/backends/dart-runtime.js +41 -0
- package/build/src/backends/dart.d.ts +20 -0
- package/build/src/backends/dart.d.ts.map +1 -0
- package/build/src/backends/dart.js +321 -0
- package/build/src/backends/effects.d.ts +60 -0
- package/build/src/backends/effects.d.ts.map +1 -0
- package/build/src/backends/effects.js +746 -0
- package/build/src/backends/go.js +18 -4
- package/build/src/backends/identifiers.d.ts +36 -4
- package/build/src/backends/identifiers.d.ts.map +1 -1
- package/build/src/backends/identifiers.js +160 -10
- package/build/src/backends/index.d.ts.map +1 -1
- package/build/src/backends/index.js +27 -4
- package/build/src/backends/ios.d.ts +68 -0
- package/build/src/backends/ios.d.ts.map +1 -0
- package/build/src/backends/ios.js +1503 -0
- package/build/src/backends/java.d.ts.map +1 -1
- package/build/src/backends/java.js +429 -36
- package/build/src/backends/javascript.d.ts +6 -0
- package/build/src/backends/javascript.d.ts.map +1 -1
- package/build/src/backends/javascript.js +380 -24
- package/build/src/backends/kotlin-runtime.d.ts +3 -0
- package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
- package/build/src/backends/kotlin-runtime.js +29 -0
- package/build/src/backends/kotlin.d.ts +33 -0
- package/build/src/backends/kotlin.d.ts.map +1 -0
- package/build/src/backends/kotlin.js +138 -0
- package/build/src/backends/native-validation.d.ts +2 -2
- package/build/src/backends/native-validation.d.ts.map +1 -1
- package/build/src/backends/native-validation.js +2 -2
- package/build/src/backends/ordered-expressions.d.ts.map +1 -1
- package/build/src/backends/ordered-expressions.js +39 -7
- package/build/src/backends/php-stdlib-support.d.ts +19 -0
- package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
- package/build/src/backends/php-stdlib-support.js +227 -0
- package/build/src/backends/php.d.ts.map +1 -1
- package/build/src/backends/php.js +448 -33
- package/build/src/backends/program.d.ts +83 -0
- package/build/src/backends/program.d.ts.map +1 -0
- package/build/src/backends/program.js +1309 -0
- package/build/src/backends/python.js +7 -1
- package/build/src/backends/ruby.d.ts.map +1 -1
- package/build/src/backends/ruby.js +310 -24
- package/build/src/backends/rust-runtime.d.ts +7 -0
- package/build/src/backends/rust-runtime.d.ts.map +1 -0
- package/build/src/backends/rust-runtime.js +32 -0
- package/build/src/backends/rust-validation.d.ts +9 -0
- package/build/src/backends/rust-validation.d.ts.map +1 -0
- package/build/src/backends/rust-validation.js +78 -0
- package/build/src/backends/rust.d.ts +24 -0
- package/build/src/backends/rust.d.ts.map +1 -0
- package/build/src/backends/rust.js +344 -0
- package/build/src/backends/scalars.d.ts +14 -6
- package/build/src/backends/scalars.d.ts.map +1 -1
- package/build/src/backends/scalars.js +167 -17
- package/build/src/backends/shared.d.ts +23 -4
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +2174 -62
- package/build/src/backends/stdlib-support.d.ts +14 -0
- package/build/src/backends/stdlib-support.d.ts.map +1 -0
- package/build/src/backends/stdlib-support.js +237 -0
- package/build/src/backends/swift-runtime.d.ts +3 -0
- package/build/src/backends/swift-runtime.d.ts.map +1 -0
- package/build/src/backends/swift-runtime.js +14 -0
- package/build/src/backends/swift.d.ts +8 -0
- package/build/src/backends/swift.d.ts.map +1 -0
- package/build/src/backends/swift.js +127 -0
- package/build/src/backends/typescript.d.ts.map +1 -1
- package/build/src/backends/typescript.js +344 -24
- package/build/src/backends/wasm.d.ts +43 -0
- package/build/src/backends/wasm.d.ts.map +1 -0
- package/build/src/backends/wasm.js +2164 -0
- package/build/src/backends/writer.d.ts +255 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +491 -3
- package/build/src/diagnostic.d.ts +4 -3
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +5 -3
- package/build/src/frontends/c.d.ts.map +1 -1
- package/build/src/frontends/c.js +5 -3
- package/build/src/frontends/cpp.d.ts.map +1 -1
- package/build/src/frontends/cpp.js +5 -3
- package/build/src/frontends/csharp.d.ts.map +1 -1
- package/build/src/frontends/csharp.js +7 -3
- package/build/src/frontends/dart.d.ts +10 -0
- package/build/src/frontends/dart.d.ts.map +1 -0
- package/build/src/frontends/dart.js +913 -0
- package/build/src/frontends/index.d.ts +3 -1
- package/build/src/frontends/index.d.ts.map +1 -1
- package/build/src/frontends/index.js +15 -5
- package/build/src/frontends/java.d.ts +110 -1
- package/build/src/frontends/java.d.ts.map +1 -1
- package/build/src/frontends/java.js +1725 -70
- package/build/src/frontends/javascript-typescript.d.ts +69 -1
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
- package/build/src/frontends/javascript-typescript.js +1825 -93
- package/build/src/frontends/kotlin.d.ts +10 -0
- package/build/src/frontends/kotlin.d.ts.map +1 -0
- package/build/src/frontends/kotlin.js +685 -0
- package/build/src/frontends/php.d.ts +118 -1
- package/build/src/frontends/php.d.ts.map +1 -1
- package/build/src/frontends/php.js +1583 -76
- package/build/src/frontends/program.d.ts +74 -0
- package/build/src/frontends/program.d.ts.map +1 -0
- package/build/src/frontends/program.js +989 -0
- package/build/src/frontends/ruby.d.ts +68 -1
- package/build/src/frontends/ruby.d.ts.map +1 -1
- package/build/src/frontends/ruby.js +1446 -101
- package/build/src/frontends/rust-parser.d.ts +11 -0
- package/build/src/frontends/rust-parser.d.ts.map +1 -0
- package/build/src/frontends/rust-parser.js +15 -0
- package/build/src/frontends/rust.d.ts +14 -0
- package/build/src/frontends/rust.d.ts.map +1 -0
- package/build/src/frontends/rust.js +715 -0
- package/build/src/frontends/scalars.d.ts +10 -0
- package/build/src/frontends/scalars.d.ts.map +1 -1
- package/build/src/frontends/scalars.js +28 -2
- package/build/src/frontends/swift.d.ts +10 -0
- package/build/src/frontends/swift.d.ts.map +1 -0
- package/build/src/frontends/swift.js +860 -0
- package/build/src/frontends/types.d.ts +186 -0
- package/build/src/frontends/types.d.ts.map +1 -0
- package/build/src/frontends/types.js +634 -0
- package/build/src/language-registry.d.ts +46 -4
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +177 -13
- package/build/src/mapping.d.ts +2 -2
- package/build/src/mapping.d.ts.map +1 -1
- package/build/src/mapping.js +31 -10
- package/build/src/semantic/capabilities.d.ts +66 -0
- package/build/src/semantic/capabilities.d.ts.map +1 -0
- package/build/src/semantic/capabilities.js +649 -0
- package/build/src/semantic/effects.d.ts +26 -0
- package/build/src/semantic/effects.d.ts.map +1 -0
- package/build/src/semantic/effects.js +764 -0
- package/build/src/semantic/generics.d.ts +23 -0
- package/build/src/semantic/generics.d.ts.map +1 -0
- package/build/src/semantic/generics.js +61 -0
- package/build/src/semantic/lifetime.d.ts +37 -0
- package/build/src/semantic/lifetime.d.ts.map +1 -0
- package/build/src/semantic/lifetime.js +527 -0
- package/build/src/semantic/provenance.d.ts +9 -2
- package/build/src/semantic/provenance.d.ts.map +1 -1
- package/build/src/semantic/provenance.js +462 -20
- package/build/src/semantic/scalars.d.ts +11 -0
- package/build/src/semantic/scalars.d.ts.map +1 -1
- package/build/src/semantic/scalars.js +16 -1
- package/build/src/semantic/stdlib.d.ts +254 -0
- package/build/src/semantic/stdlib.d.ts.map +1 -0
- package/build/src/semantic/stdlib.js +880 -0
- package/build/src/semantic/types.d.ts +3108 -178
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +730 -15
- package/build/src/semantic/validate.d.ts +85 -5
- package/build/src/semantic/validate.d.ts.map +1 -1
- package/build/src/semantic/validate.js +2576 -98
- package/build/src/stdlib-facades.d.ts +304 -0
- package/build/src/stdlib-facades.d.ts.map +1 -0
- package/build/src/stdlib-facades.js +1167 -0
- package/build/src/stdlib-negotiation.d.ts +69 -0
- package/build/src/stdlib-negotiation.d.ts.map +1 -0
- package/build/src/stdlib-negotiation.js +403 -0
- package/build/src/stdlib-providers.d.ts +72 -0
- package/build/src/stdlib-providers.d.ts.map +1 -0
- package/build/src/stdlib-providers.js +339 -0
- package/build/src/toolchains.d.ts +55 -1
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +15 -4
- package/docs/android.md +79 -0
- package/docs/architecture.md +47 -13
- package/docs/dart.md +60 -0
- package/docs/goals.md +3 -3
- package/docs/ios.md +121 -0
- package/docs/kotlin.md +42 -0
- package/docs/language-support.md +238 -26
- package/docs/multi-file-modules.md +52 -0
- package/docs/parser-qualification.md +121 -8
- package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
- package/docs/rust.md +88 -0
- package/docs/source-maps.md +17 -7
- package/docs/specification.md +5 -0
- package/docs/standard-library-portability.md +39 -8
- package/docs/swift.md +44 -0
- package/docs/testing.md +381 -4
- package/docs/webassembly.md +52 -0
- package/index.js +66 -8
- package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
- package/package.json +5 -2
- package/src/artifact-path.js +47 -2
- package/src/artifacts.js +67 -0
- package/src/backends/android.js +1370 -0
- package/src/backends/c-validation.js +6 -1
- package/src/backends/cpp-validation.js +6 -1
- package/src/backends/csharp.js +3 -0
- package/src/backends/dart-runtime.js +41 -0
- package/src/backends/dart.js +326 -0
- package/src/backends/effects.js +705 -0
- package/src/backends/go.js +14 -2
- package/src/backends/identifiers.js +166 -9
- package/src/backends/index.js +27 -2
- package/src/backends/ios.js +1612 -0
- package/src/backends/java.js +454 -36
- package/src/backends/javascript.js +389 -23
- package/src/backends/kotlin-runtime.js +29 -0
- package/src/backends/kotlin.js +144 -0
- package/src/backends/native-validation.js +1 -1
- package/src/backends/ordered-expressions.js +40 -6
- package/src/backends/php-stdlib-support.js +239 -0
- package/src/backends/php.js +469 -32
- package/src/backends/program.js +1408 -0
- package/src/backends/python.js +3 -0
- package/src/backends/ruby.js +326 -23
- package/src/backends/rust-runtime.js +34 -0
- package/src/backends/rust-validation.js +75 -0
- package/src/backends/rust.js +335 -0
- package/src/backends/scalars.js +141 -16
- package/src/backends/shared.js +2314 -115
- package/src/backends/stdlib-support.js +234 -0
- package/src/backends/swift-runtime.js +14 -0
- package/src/backends/swift.js +132 -0
- package/src/backends/typescript.js +349 -23
- package/src/backends/wasm.js +2208 -0
- package/src/backends/writer.js +545 -2
- package/src/diagnostic.js +4 -2
- package/src/frontends/c.js +4 -2
- package/src/frontends/cpp.js +4 -2
- package/src/frontends/csharp.js +4 -2
- package/src/frontends/dart.js +963 -0
- package/src/frontends/index.js +14 -4
- package/src/frontends/java.js +1977 -69
- package/src/frontends/javascript-typescript.js +2046 -102
- package/src/frontends/kotlin.js +713 -0
- package/src/frontends/php.js +1725 -79
- package/src/frontends/program.js +1062 -0
- package/src/frontends/ruby.js +1624 -98
- package/src/frontends/rust-parser.js +18 -0
- package/src/frontends/rust.js +714 -0
- package/src/frontends/scalars.js +31 -1
- package/src/frontends/swift.js +893 -0
- package/src/frontends/types.js +750 -0
- package/src/language-registry.js +182 -12
- package/src/mapping.js +33 -9
- package/src/semantic/capabilities.js +671 -0
- package/src/semantic/effects.js +737 -0
- package/src/semantic/generics.js +58 -0
- package/src/semantic/lifetime.js +517 -0
- package/src/semantic/provenance.js +412 -19
- package/src/semantic/scalars.js +17 -0
- package/src/semantic/stdlib.js +921 -0
- package/src/semantic/types.js +810 -14
- package/src/semantic/validate.js +2934 -209
- package/src/stdlib-facades.js +1211 -0
- package/src/stdlib-negotiation.js +446 -0
- package/src/stdlib-providers.js +377 -0
- package/src/toolchains.js +16 -3
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import {unsupportedCapability} from "../diagnostic.js"
|
|
4
|
+
import {isTask034ResourceProbe} from "../semantic/capabilities.js"
|
|
5
|
+
|
|
6
|
+
const adoptedTargets = new Set(["php", "ruby", "javascript", "typescript", "java"])
|
|
7
|
+
const task037Authorities = new Set([
|
|
8
|
+
"semantifold.output", "semantifold.resource", "semantifold.socket-client", "semantifold.text-stream"
|
|
9
|
+
])
|
|
10
|
+
const protectedSupportNames = new Set([
|
|
11
|
+
"ProbeOperationFailure", "ProbeAcquireFailure", "ProbeReadFailure", "ProbeCloseFailure", "ProbeResourceClosed", "ProbeResource",
|
|
12
|
+
"probeEffect", "probeAcquire", "probeRead", "probeClose", "probeTrace"
|
|
13
|
+
])
|
|
14
|
+
|
|
15
|
+
/** @typedef {{expression: import("../semantic/types.js").Expression, path: string}} ExpressionPath */
|
|
16
|
+
/** @typedef {{detail: string, location: import("../semantic/types.js").SourceLocation}} ExcludedEffect */
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Validates Task 034 target support before a SourceWriter is allocated.
|
|
20
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Candidate module.
|
|
21
|
+
* @param {import("../semantic/types.js").BackendLanguage} language - Requested target.
|
|
22
|
+
* @param {{usedOperations?: readonly string[]}} [options] - Program-wide used canonical
|
|
23
|
+
* operations for a linked stdlib provider; restricts the reserved support surface to the
|
|
24
|
+
* operations actually materialized in the provider artifact.
|
|
25
|
+
* @returns {void}
|
|
26
|
+
*/
|
|
27
|
+
export function preflightEffectCapabilities(module, language, options = {}) {
|
|
28
|
+
const capabilities = module?.capabilities
|
|
29
|
+
|
|
30
|
+
if (capabilities === undefined) {
|
|
31
|
+
const unauthorized = findTask034Node(module)
|
|
32
|
+
|
|
33
|
+
if (unauthorized) {
|
|
34
|
+
unsupportedCapability(language, "MISSING_CAPABILITY_AUTHORITY: Task 034 IR requires its compiler authority graph",
|
|
35
|
+
/** @type {import("../semantic/types.js").SourceLocation | undefined} */ (Reflect.get(unauthorized, "location") ?? module?.location))
|
|
36
|
+
}
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
if (!Array.isArray(capabilities) || capabilities.length == 0) {
|
|
40
|
+
unsupportedCapability(language, "malformed or empty Task 034 capability graph", module?.location)
|
|
41
|
+
}
|
|
42
|
+
if (!adoptedTargets.has(language)) {
|
|
43
|
+
unsupportedCapability(language, "Task 034 effectful capabilities and owned resources", module.location)
|
|
44
|
+
}
|
|
45
|
+
const task037 = language == "php" && capabilities.every((capability) => task037Authorities.has(capability.authorityId))
|
|
46
|
+
|
|
47
|
+
if (!isTask034ResourceProbe(capabilities) && !task037) {
|
|
48
|
+
unsupportedCapability(language, "unbound Task 034 capability authority", module.location)
|
|
49
|
+
}
|
|
50
|
+
if (!Array.isArray(module.functions) || !module.entryPoint || typeof module.entryPoint != "object" ||
|
|
51
|
+
!module.entryPoint.body || !Array.isArray(module.entryPoint.body.statements) ||
|
|
52
|
+
[module.records, module.classes, module.errors].some((declarations) => declarations !== undefined && !Array.isArray(declarations))) {
|
|
53
|
+
unsupportedCapability(language, "malformed Task 034 semantic module", module.location)
|
|
54
|
+
}
|
|
55
|
+
const collision = moduleNeedsEffectSupport(module) ? findSupportCollision(module, language, options.usedOperations) : undefined
|
|
56
|
+
|
|
57
|
+
if (collision) unsupportedCapability(language, `protected Task 034 support name '${collision.name}'`, collision.location)
|
|
58
|
+
const excluded = findExcludedEffectContext(module)
|
|
59
|
+
if (excluded) unsupportedCapability(language, excluded.detail, excluded.location)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Finds compiler-authorized Task 034 IR that has been detached from its authority graph.
|
|
64
|
+
* @param {unknown} value - Candidate semantic graph.
|
|
65
|
+
* @param {Set<object>} [seen] - Cycle protection.
|
|
66
|
+
* @returns {object | undefined} First unauthorized Task 034 node.
|
|
67
|
+
*/
|
|
68
|
+
function findTask034Node(value, seen = new Set()) {
|
|
69
|
+
if (!value || typeof value != "object" || seen.has(value)) return undefined
|
|
70
|
+
seen.add(value)
|
|
71
|
+
if (!Array.isArray(value)) {
|
|
72
|
+
const kind = Reflect.get(value, "kind")
|
|
73
|
+
|
|
74
|
+
if (["EffectCallExpression", "OwnedBorrowExpression", "OwnedMoveExpression", "OwnedReferenceType", "OwnedResourceType"].includes(String(kind)) ||
|
|
75
|
+
kind == "ErrorType" && /^capability:[0-9]+\/failure:[0-9]+$/u.test(String(Reflect.get(value, "declarationId")))) return value
|
|
76
|
+
}
|
|
77
|
+
for (const [key, child] of Object.entries(value)) {
|
|
78
|
+
if (["location", "sourceProvenance"].includes(key)) continue
|
|
79
|
+
const found = findTask034Node(child, seen)
|
|
80
|
+
if (found) return found
|
|
81
|
+
}
|
|
82
|
+
return undefined
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Finds one user declaration that would collide with the protected support surface.
|
|
87
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Validated semantic graph.
|
|
88
|
+
* @param {import("../semantic/types.js").BackendLanguage} language - Target language.
|
|
89
|
+
* @param {readonly string[]} [usedOperations] - Linked provider operations; omitted for the full inlined surface.
|
|
90
|
+
* @returns {{name: string, location: import("../semantic/types.js").SourceLocation} | undefined} First collision.
|
|
91
|
+
*/
|
|
92
|
+
function findSupportCollision(module, language, usedOperations) {
|
|
93
|
+
const reserved = new Set()
|
|
94
|
+
|
|
95
|
+
if (usedOperations === undefined) {
|
|
96
|
+
for (const name of protectedSupportNames) reserved.add(supportNameKey(name, language))
|
|
97
|
+
if (language == "javascript" || language == "typescript") {
|
|
98
|
+
reserved.add("__semantifoldTask034Fs")
|
|
99
|
+
reserved.add("__semantifoldTask034Trace")
|
|
100
|
+
} else if (language == "php") reserved.add("__semantifold_task034_trace")
|
|
101
|
+
} else {
|
|
102
|
+
const used = new Set(usedOperations)
|
|
103
|
+
|
|
104
|
+
for (const name of used) reserved.add(supportNameKey(name, language))
|
|
105
|
+
if (used.has("probeEffect")) reserved.add(supportNameKey("ProbeOperationFailure", language))
|
|
106
|
+
if (used.has("probeAcquire")) reserved.add(supportNameKey("ProbeAcquireFailure", language))
|
|
107
|
+
if (used.has("probeRead")) reserved.add(supportNameKey("ProbeReadFailure", language))
|
|
108
|
+
if (used.has("probeClose")) reserved.add(supportNameKey("ProbeCloseFailure", language))
|
|
109
|
+
if (used.has("probeRead") || used.has("probeClose")) reserved.add(supportNameKey("ProbeResourceClosed", language))
|
|
110
|
+
if (used.has("probeAcquire") || used.has("probeRead") || used.has("probeClose")) {
|
|
111
|
+
reserved.add(supportNameKey("ProbeResource", language))
|
|
112
|
+
}
|
|
113
|
+
if (used.size > 0) {
|
|
114
|
+
if (language == "javascript" || language == "typescript") {
|
|
115
|
+
reserved.add("__semantifoldTask034Trace")
|
|
116
|
+
if (used.has("probeAcquire")) reserved.add("__semantifoldTask034Fs")
|
|
117
|
+
} else if (language == "php") reserved.add("__semantifold_task034_trace")
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const declarations = [...module.records ?? [], ...module.classes ?? [], ...module.errors ?? [], ...module.functions]
|
|
121
|
+
|
|
122
|
+
for (const declaration of declarations) {
|
|
123
|
+
if (!declaration || typeof declaration != "object") continue
|
|
124
|
+
if (reserved.has(supportNameKey(declaration.name, language))) return {location: declaration.location, name: declaration.name}
|
|
125
|
+
}
|
|
126
|
+
if (language == "javascript" || language == "typescript" || language == "php") {
|
|
127
|
+
for (const statement of module.entryPoint.body.statements) {
|
|
128
|
+
if (!statement || typeof statement != "object") continue
|
|
129
|
+
if (statement.kind == "LocalDeclaration" && reserved.has(supportNameKey(statement.name, language))) {
|
|
130
|
+
return {location: statement.location, name: statement.name}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return undefined
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Applies target namespace casing to a protected support name.
|
|
139
|
+
* @param {string} name - Source name.
|
|
140
|
+
* @param {import("../semantic/types.js").BackendLanguage} language - Target language.
|
|
141
|
+
* @returns {string} Comparable name.
|
|
142
|
+
*/
|
|
143
|
+
function supportNameKey(name, language) {
|
|
144
|
+
return language == "php" ? name.toLowerCase() : name
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Emits fixed target-private Task 034 conformance support.
|
|
149
|
+
* @param {import("./writer.js").SourceWriter} writer - Destination writer.
|
|
150
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Authorized module.
|
|
151
|
+
* @param {"php" | "ruby" | "javascript" | "typescript" | "java"} language - Adopted target.
|
|
152
|
+
* @param {"top" | "members"} [placement] - Java support placement.
|
|
153
|
+
* @returns {void}
|
|
154
|
+
*/
|
|
155
|
+
export function emitEffectSupport(writer, module, language, placement = "top") {
|
|
156
|
+
const linked = writer.stdlibProviderEntries !== undefined
|
|
157
|
+
|
|
158
|
+
if (language == "java" && linked) {
|
|
159
|
+
if (placement != "members" || writer.stdlibProviderShims === undefined) return
|
|
160
|
+
} else if (linked || !module.capabilities || !moduleNeedsEffectSupport(module)) {
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
const content = language == "php" ? phpSupport : language == "ruby" ? rubySupport : language == "javascript" ? javascriptSupport :
|
|
164
|
+
language == "typescript" ? typescriptSupport :
|
|
165
|
+
writer.stdlibProviderShims !== undefined ? javaProgramNestedSupport + javaMemberSupport :
|
|
166
|
+
placement == "top" ? javaTopSupport : javaMemberSupport
|
|
167
|
+
|
|
168
|
+
writer.synthetic(content, "semantifold-task034-support", [module])
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Emits the public static provider shims for the program-wide used operations on the Java owner module.
|
|
173
|
+
* @param {import("./writer.js").SourceWriter} writer - Destination writer.
|
|
174
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Owner module.
|
|
175
|
+
* @returns {void}
|
|
176
|
+
*/
|
|
177
|
+
export function emitEffectProviderEntries(writer, module) {
|
|
178
|
+
const operations = writer.stdlibProviderShims ?? []
|
|
179
|
+
|
|
180
|
+
if (operations.length == 0) return
|
|
181
|
+
const lines = operations.map((operation) => ` ${javaProviderShims[operation]}`)
|
|
182
|
+
|
|
183
|
+
writer.synthetic(`${lines.join("\n")}\n\n`, "semantifold-stdlib-provider-entries", [module])
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Recognizes only the byte-exact protected support emitted by this backend.
|
|
188
|
+
* Frontends use this in addition to parser-shape checks during generated-source reparse.
|
|
189
|
+
* @param {string} source - Complete candidate source.
|
|
190
|
+
* @param {"php" | "ruby" | "javascript" | "typescript" | "java"} language - Adopted target.
|
|
191
|
+
* @param {"top" | "members"} [placement] - Java support placement.
|
|
192
|
+
* @returns {boolean} Whether the exact protected segment is present.
|
|
193
|
+
*/
|
|
194
|
+
export function hasExactEffectSupport(source, language, placement = "top") {
|
|
195
|
+
const content = language == "php" ? phpSupport : language == "ruby" ? rubySupport : language == "javascript" ? javascriptSupport :
|
|
196
|
+
language == "typescript" ? typescriptSupport : placement == "top" ? javaTopSupport : javaMemberSupport
|
|
197
|
+
|
|
198
|
+
return source.includes(content)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Materializes nested effect sites before their enclosing eager expression.
|
|
203
|
+
* The installed replacements remain active until the next statement begins.
|
|
204
|
+
* @param {import("./writer.js").SourceWriter} writer - Destination writer.
|
|
205
|
+
* @param {import("../semantic/types.js").Statement} statement - Current statement.
|
|
206
|
+
* @param {string} indent - Current target indentation.
|
|
207
|
+
* @param {string} path - Exact statement path.
|
|
208
|
+
* @param {"php" | "ruby" | "javascript" | "typescript" | "java"} language - Adopted target.
|
|
209
|
+
* @param {(expression: import("../semantic/types.js").Expression, path: string) => void} emit - Target expression emitter.
|
|
210
|
+
* @returns {void}
|
|
211
|
+
*/
|
|
212
|
+
export function emitEffectPrefixes(writer, statement, indent, path, language, emit) {
|
|
213
|
+
/** @type {ExpressionPath[]} */
|
|
214
|
+
const planned = []
|
|
215
|
+
|
|
216
|
+
for (const root of statementExpressionRoots(statement, path)) collectNestedEffects(root.expression, root.path, root.expression, planned)
|
|
217
|
+
writer.planEffectReplacements(planned.map(({expression}) => expression))
|
|
218
|
+
for (const {expression, path: expressionPath} of planned) {
|
|
219
|
+
const name = writer.effectTemporaryName(expression)
|
|
220
|
+
const type = effectExpressionType(writer, expression)
|
|
221
|
+
const typeName = emittedTypeName(writer, type, language)
|
|
222
|
+
const declaration = language == "php"
|
|
223
|
+
? `/**\n${indent} * @var ${typeName} $${name}\n${indent} * @semantifold-immutable\n${indent} */\n${indent}$${name} = `
|
|
224
|
+
: language == "ruby"
|
|
225
|
+
? `# @type [${typeName}]\n${indent}# @semantifold-immutable\n${indent}${name} = `
|
|
226
|
+
: language == "javascript" ? `/** @type {${typeName}} */\n${indent}const ${name} = `
|
|
227
|
+
: language == "typescript" ? `const ${name}: ${typeName} = ` : `final ${typeName} ${name} = `
|
|
228
|
+
|
|
229
|
+
writer.synthetic(`${indent}${declaration}`, "exactly-once effect temporary", [expression], [expressionPath])
|
|
230
|
+
writer.emitEffectDefinition(expression, () => emit(expression, expressionPath))
|
|
231
|
+
writer.synthetic(language == "ruby" ? "\n" : ";\n", "exactly-once effect temporary terminator", [expression], [expressionPath])
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Resolves the result type needed for an effect temporary.
|
|
237
|
+
* @param {import("./writer.js").SourceWriter} writer - Active writer.
|
|
238
|
+
* @param {import("../semantic/types.js").Expression} expression - Effectful expression.
|
|
239
|
+
* @returns {import("../semantic/types.js").SemanticFunctionReturnType | undefined} Result type.
|
|
240
|
+
*/
|
|
241
|
+
function effectExpressionType(writer, expression) {
|
|
242
|
+
if (expression.kind == "EffectCallExpression") return writer.effectOperationForId(expression.operation).returnType
|
|
243
|
+
if (expression.kind == "MethodCallExpression" || expression.kind == "CallExpression") {
|
|
244
|
+
return expression.resolution ? semanticTypeForIdentity(expression.resolution.returnType) : undefined
|
|
245
|
+
}
|
|
246
|
+
return undefined
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Rehydrates a resolved call result for target-local temporary spelling.
|
|
251
|
+
* @param {import("../semantic/types.js").FunctionReturnTypeIdentity} identity - Exact resolved result identity.
|
|
252
|
+
* @returns {import("../semantic/types.js").SemanticFunctionReturnType} Detached semantic type.
|
|
253
|
+
*/
|
|
254
|
+
function semanticTypeForIdentity(identity) {
|
|
255
|
+
if (typeof identity == "string") {
|
|
256
|
+
return {kind: "TypeReference", name: /** @type {import("../semantic/types.js").FunctionReturnTypeName} */ (identity)}
|
|
257
|
+
}
|
|
258
|
+
if (identity.kind == "ListType") return {elementType: semanticTypeForValueIdentity(identity.elementType), kind: "ListType"}
|
|
259
|
+
if (identity.kind == "MapType") return {keyType: /** @type {import("../semantic/types.js").TypeReference} */ (
|
|
260
|
+
semanticTypeForValueIdentity(identity.keyType)), kind: "MapType",
|
|
261
|
+
valueType: semanticTypeForValueIdentity(identity.valueType)}
|
|
262
|
+
if (identity.kind == "OrderedMapType") return {keyType: /** @type {import("../semantic/types.js").TypeReference} */ (
|
|
263
|
+
semanticTypeForValueIdentity(identity.keyType)), kind: "OrderedMapType",
|
|
264
|
+
order: "insertion", valueType: semanticTypeForValueIdentity(identity.valueType)}
|
|
265
|
+
if (identity.kind == "OptionalType") return {kind: "OptionalType", valueType: semanticTypeForValueIdentity(identity.valueType)}
|
|
266
|
+
if (identity.kind == "RecordType") return {arguments: identity.arguments?.map(semanticTypeForValueIdentity),
|
|
267
|
+
declarationId: identity.declarationId, kind: "RecordType"}
|
|
268
|
+
if (identity.kind == "ReferenceType") return {declarationId: identity.declarationId, kind: "ReferenceType"}
|
|
269
|
+
if (identity.kind == "OwnedResourceType") return {kind: "OwnedResourceType", resourceId: identity.resourceId}
|
|
270
|
+
if (identity.kind == "OwnedReferenceType") return {declarationId: identity.declarationId, kind: "OwnedReferenceType"}
|
|
271
|
+
return {kind: "TypeVariableReference", location: /** @type {never} */ (undefined), parameterId: identity.parameterId}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Rehydrates one non-void resolved type identity.
|
|
276
|
+
* @param {import("../semantic/types.js").SemanticTypeIdentity} identity - Exact type identity.
|
|
277
|
+
* @returns {import("../semantic/types.js").SemanticValueType} Detached semantic type.
|
|
278
|
+
*/
|
|
279
|
+
function semanticTypeForValueIdentity(identity) {
|
|
280
|
+
return /** @type {import("../semantic/types.js").SemanticValueType} */ (semanticTypeForIdentity(identity))
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Renders the subset of semantic types admitted for synthetic temporaries.
|
|
285
|
+
* @param {import("./writer.js").SourceWriter} writer - Active writer.
|
|
286
|
+
* @param {import("../semantic/types.js").SemanticFunctionReturnType | undefined} type - Semantic type.
|
|
287
|
+
* @param {"php" | "ruby" | "javascript" | "typescript" | "java"} language - Target.
|
|
288
|
+
* @param {boolean} [nested] - Whether Java requires a boxed scalar.
|
|
289
|
+
* @returns {string} Target type spelling.
|
|
290
|
+
*/
|
|
291
|
+
function emittedTypeName(writer, type, language, nested = false) {
|
|
292
|
+
if (!type || type.kind == "TypeReference" && type.name == "void") return language == "java" ? "Object" : "unknown"
|
|
293
|
+
if (type.kind == "TypeReference") {
|
|
294
|
+
if (language == "php") return type.name == "integer" ? "int" : type.name == "boolean" ? "bool" : "string"
|
|
295
|
+
if (language == "ruby") return type.name == "integer" ? "Integer" : type.name == "boolean" ? "Boolean" : "String"
|
|
296
|
+
if (language == "java") return type.name == "integer" ? nested ? "Integer" : "int" :
|
|
297
|
+
type.name == "boolean" ? nested ? "Boolean" : "boolean" : "String"
|
|
298
|
+
return type.name == "integer" ? "number" : type.name
|
|
299
|
+
}
|
|
300
|
+
if (type.kind == "OwnedResourceType") return writer.resourceForId(type.resourceId).name
|
|
301
|
+
if (type.kind == "ReferenceType" || type.kind == "OwnedReferenceType") return writer.classNameForId(type.declarationId)
|
|
302
|
+
if (type.kind == "TypeVariableReference") return writer.typeParameterForId(type.parameterId).name
|
|
303
|
+
if (type.kind == "RecordType") {
|
|
304
|
+
const name = writer.recordNameForId(type.declarationId)
|
|
305
|
+
const arguments_ = type.arguments?.map((argument) => emittedTypeName(writer, argument, language, true)) ?? []
|
|
306
|
+
|
|
307
|
+
return arguments_.length == 0 ? name : language == "ruby" ? `${name}[${arguments_.join(",")}]` : `${name}<${arguments_.join(",")}>`
|
|
308
|
+
}
|
|
309
|
+
if (type.kind == "OptionalType") {
|
|
310
|
+
const value = emittedTypeName(writer, type.valueType, language, true)
|
|
311
|
+
return language == "php" ? `?${value}` : language == "ruby" ? `${value}?` :
|
|
312
|
+
language == "java" ? `java.util.Optional<${value}>` : `${value} | null`
|
|
313
|
+
}
|
|
314
|
+
if (type.kind == "ListType") {
|
|
315
|
+
const value = emittedTypeName(writer, type.elementType, language, true)
|
|
316
|
+
return language == "php" ? `list<${value}>` : language == "ruby" ? `Array<${value}>` :
|
|
317
|
+
language == "java" ? `java.util.List<${value}>` : `readonly ${value}[]`
|
|
318
|
+
}
|
|
319
|
+
if (type.kind == "MapType" || type.kind == "OrderedMapType") {
|
|
320
|
+
const key = emittedTypeName(writer, type.keyType, language, true)
|
|
321
|
+
const value = emittedTypeName(writer, type.valueType, language, true)
|
|
322
|
+
|
|
323
|
+
if (language == "php") return `array<${key},${value}>`
|
|
324
|
+
if (language == "ruby") return `Hash[${key},${value}]`
|
|
325
|
+
if (language == "java") return `${type.kind == "OrderedMapType" ? "java.util.SequencedMap" : "java.util.Map"}<${key},${value}>`
|
|
326
|
+
return `ReadonlyMap<${key}, ${value}>`
|
|
327
|
+
}
|
|
328
|
+
return language == "java" ? "Object" : "unknown"
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Returns the expression roots evaluated by one statement.
|
|
333
|
+
* @param {import("../semantic/types.js").Statement} statement - Statement.
|
|
334
|
+
* @param {string} path - Stable statement path.
|
|
335
|
+
* @returns {ExpressionPath[]} Expression roots.
|
|
336
|
+
*/
|
|
337
|
+
function statementExpressionRoots(statement, path) {
|
|
338
|
+
if (statement.kind == "LocalDeclaration") return [{expression: statement.initializer, path: `${path}/initializer`}]
|
|
339
|
+
if (statement.kind == "AssignmentStatement" || statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement") {
|
|
340
|
+
return [{expression: statement.expression, path: `${path}/expression`}]
|
|
341
|
+
}
|
|
342
|
+
if (statement.kind == "ReturnStatement") return statement.expression ? [{expression: statement.expression, path: `${path}/expression`}] : []
|
|
343
|
+
if (statement.kind == "PrivateFieldWriteStatement") return [{expression: statement.expression, path: `${path}/expression`}]
|
|
344
|
+
if (statement.kind == "IfStatement" || statement.kind == "WhileStatement") return [{expression: statement.condition, path: `${path}/condition`}]
|
|
345
|
+
if (statement.kind == "ForEachStatement") return [{expression: statement.list, path: `${path}/list`}]
|
|
346
|
+
if (statement.kind == "ForEachMapStatement") return [{expression: statement.map, path: `${path}/map`}]
|
|
347
|
+
if (statement.kind == "RaiseStatement") return [{expression: statement.error.message, path: `${path}/error/message`}]
|
|
348
|
+
return []
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Collects nested effect sites in postorder so children are materialized first.
|
|
353
|
+
* @param {import("../semantic/types.js").Expression} expression - Current expression.
|
|
354
|
+
* @param {string} path - Current occurrence path.
|
|
355
|
+
* @param {import("../semantic/types.js").Expression} root - Statement expression root.
|
|
356
|
+
* @param {ExpressionPath[]} output - Ordered plan receiving nested sites.
|
|
357
|
+
* @returns {void}
|
|
358
|
+
*/
|
|
359
|
+
function collectNestedEffects(expression, path, root, output) {
|
|
360
|
+
for (const child of expressionChildren(expression, path)) collectNestedEffects(child.expression, child.path, root, output)
|
|
361
|
+
if (expression !== root && (expression.kind == "EffectCallExpression" || typeof Reflect.get(expression, "effectSiteId") == "string")) {
|
|
362
|
+
output.push({expression, path})
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Returns path-bearing expression children in evaluation order.
|
|
368
|
+
* @param {import("../semantic/types.js").Expression} expression - Parent expression.
|
|
369
|
+
* @param {string} path - Parent path.
|
|
370
|
+
* @returns {ExpressionPath[]} Children.
|
|
371
|
+
*/
|
|
372
|
+
function expressionChildren(expression, path) {
|
|
373
|
+
if (expression.kind == "CallExpression" || expression.kind == "EffectCallExpression" || expression.kind == "ReferenceConstruction" ||
|
|
374
|
+
expression.kind == "RecordConstruction") return expression.arguments.map((child, index) => ({expression: child, path: `${path}/arguments/${index}`}))
|
|
375
|
+
if (expression.kind == "MethodCallExpression") return [
|
|
376
|
+
{expression: expression.receiver, path: `${path}/receiver`},
|
|
377
|
+
...expression.arguments.map((child, index) => ({expression: child, path: `${path}/arguments/${index}`}))
|
|
378
|
+
]
|
|
379
|
+
if (expression.kind == "OwnedMoveExpression" || expression.kind == "OwnedBorrowExpression") {
|
|
380
|
+
return [{expression: expression.expression, path: `${path}/expression`}]
|
|
381
|
+
}
|
|
382
|
+
if (expression.kind == "BinaryExpression") return [
|
|
383
|
+
{expression: expression.left, path: `${path}/left`}, {expression: expression.right, path: `${path}/right`}
|
|
384
|
+
]
|
|
385
|
+
if (expression.kind == "UnaryExpression") return [{expression: expression.operand, path: `${path}/operand`}]
|
|
386
|
+
if (expression.kind == "OptionalSome") return [{expression: expression.value, path: `${path}/value`}]
|
|
387
|
+
if (expression.kind == "OptionalIsPresent" || expression.kind == "OptionalUnwrap") {
|
|
388
|
+
return [{expression: expression.operand, path: `${path}/operand`}]
|
|
389
|
+
}
|
|
390
|
+
if (expression.kind == "ListLiteral") return expression.elements.map((child, index) => ({expression: child, path: `${path}/elements/${index}`}))
|
|
391
|
+
if (expression.kind == "MapLiteral" || expression.kind == "OrderedMapLiteral") return expression.entries.flatMap((entry, index) => [
|
|
392
|
+
{expression: entry.key, path: `${path}/entries/${index}/key`}, {expression: entry.value, path: `${path}/entries/${index}/value`}
|
|
393
|
+
])
|
|
394
|
+
if (expression.kind == "ListIndexExpression") return [
|
|
395
|
+
{expression: expression.collection, path: `${path}/collection`}, {expression: expression.index, path: `${path}/index`}
|
|
396
|
+
]
|
|
397
|
+
if (expression.kind == "MapLookupExpression") return [
|
|
398
|
+
{expression: expression.collection, path: `${path}/collection`}, {expression: expression.key, path: `${path}/key`}
|
|
399
|
+
]
|
|
400
|
+
if (expression.kind == "CollectionSizeExpression") return [{expression: expression.collection, path: `${path}/collection`}]
|
|
401
|
+
if (expression.kind == "MemberRead") return [{expression: expression.receiver, path: `${path}/receiver`}]
|
|
402
|
+
return []
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Checks whether generated support is required by a semantic capability node or type.
|
|
407
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Semantic module.
|
|
408
|
+
* @returns {boolean} Whether the protected binding is required.
|
|
409
|
+
*/
|
|
410
|
+
function moduleNeedsEffectSupport(module) {
|
|
411
|
+
/** @type {unknown[]} */
|
|
412
|
+
const pending = [module.entryPoint, ...module.functions, ...module.records ?? [], ...module.errors ?? [], ...module.classes ?? []]
|
|
413
|
+
const seen = new Set()
|
|
414
|
+
|
|
415
|
+
while (pending.length > 0) {
|
|
416
|
+
const value = pending.pop()
|
|
417
|
+
|
|
418
|
+
if (!value || typeof value != "object" || seen.has(value)) continue
|
|
419
|
+
seen.add(value)
|
|
420
|
+
const kind = Reflect.get(value, "kind")
|
|
421
|
+
|
|
422
|
+
if (kind == "EffectCallExpression" || kind == "OwnedResourceType" || kind == "OwnedReferenceType" ||
|
|
423
|
+
kind == "ErrorType" && /^capability:[0-9]+\/failure:[0-9]+$/u.test(String(Reflect.get(value, "declarationId")))) return true
|
|
424
|
+
for (const [key, child] of Object.entries(value)) {
|
|
425
|
+
if (["location", "sourceProvenance"].includes(key)) continue
|
|
426
|
+
if (Array.isArray(child)) pending.push(...child)
|
|
427
|
+
else if (child && typeof child == "object") pending.push(child)
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return false
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Finds a context excluded from bounded eager lowering.
|
|
435
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Semantic module.
|
|
436
|
+
* @returns {ExcludedEffect | undefined} First deterministic exclusion.
|
|
437
|
+
*/
|
|
438
|
+
function findExcludedEffectContext(module) {
|
|
439
|
+
/** @type {object[]} */
|
|
440
|
+
const owners = [...module.functions.filter((owner) => owner && typeof owner == "object"), module.entryPoint]
|
|
441
|
+
|
|
442
|
+
for (const declaration of module.classes ?? []) {
|
|
443
|
+
if (!declaration || typeof declaration != "object") continue
|
|
444
|
+
if (declaration.constructor && typeof declaration.constructor == "object") owners.push(declaration.constructor)
|
|
445
|
+
if (Array.isArray(declaration.methods)) owners.push(...declaration.methods.filter((owner) => owner && typeof owner == "object"))
|
|
446
|
+
}
|
|
447
|
+
for (const owner of owners) {
|
|
448
|
+
const body = Reflect.get(owner, "body")
|
|
449
|
+
|
|
450
|
+
if (!body || typeof body != "object") continue
|
|
451
|
+
const found = blockExcluded(/** @type {import("../semantic/types.js").Block} */ (body))
|
|
452
|
+
if (found) return found
|
|
453
|
+
}
|
|
454
|
+
return undefined
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Finds an excluded context in one structured block.
|
|
459
|
+
* @param {import("../semantic/types.js").Block} block - Semantic block.
|
|
460
|
+
* @returns {ExcludedEffect | undefined} First deterministic exclusion.
|
|
461
|
+
*/
|
|
462
|
+
function blockExcluded(block) {
|
|
463
|
+
if (!block || typeof block != "object" || !Array.isArray(block.statements)) return undefined
|
|
464
|
+
for (const statement of block.statements) {
|
|
465
|
+
if (!statement || typeof statement != "object") continue
|
|
466
|
+
if (statement.kind == "WhileStatement" && containsEffect(statement.condition)) {
|
|
467
|
+
return {detail: "effectful condition-controlled loop condition", location: statement.condition.location}
|
|
468
|
+
}
|
|
469
|
+
const expressions = statement.kind == "LocalDeclaration" ? [statement.initializer] :
|
|
470
|
+
statement.kind == "AssignmentStatement" || statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement" ? [statement.expression] :
|
|
471
|
+
statement.kind == "ReturnStatement" ? statement.expression ? [statement.expression] : [] :
|
|
472
|
+
statement.kind == "IfStatement" ? [statement.condition] : statement.kind == "ForEachStatement" ? [statement.list] :
|
|
473
|
+
statement.kind == "ForEachMapStatement" ? [statement.map] : statement.kind == "PrivateFieldWriteStatement" ? [statement.expression] :
|
|
474
|
+
statement.kind == "RaiseStatement" ? [statement.error.message] : []
|
|
475
|
+
for (const expression of expressions) {
|
|
476
|
+
const conditional = findConditionalEffect(expression)
|
|
477
|
+
if (conditional) return {detail: "effectful short-circuit BooleanAnd/BooleanOr expression", location: conditional.location}
|
|
478
|
+
}
|
|
479
|
+
const nested = statement.kind == "IfStatement" ? [statement.consequent, ...(statement.alternate ? [statement.alternate] : [])] :
|
|
480
|
+
statement.kind == "ForEachStatement" || statement.kind == "ForEachMapStatement" || statement.kind == "WhileStatement" ? [statement.body] :
|
|
481
|
+
statement.kind == "TryStatement" ? [statement.body, statement.catchBody] : []
|
|
482
|
+
for (const child of nested) {
|
|
483
|
+
const found = blockExcluded(child)
|
|
484
|
+
if (found) return found
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return undefined
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Finds an effect below a short-circuit operator.
|
|
492
|
+
* @param {import("../semantic/types.js").Expression} expression - Expression root.
|
|
493
|
+
* @returns {import("../semantic/types.js").Expression | undefined} Invalid conditional effect.
|
|
494
|
+
*/
|
|
495
|
+
function findConditionalEffect(expression) {
|
|
496
|
+
if (!expression || typeof expression != "object") return undefined
|
|
497
|
+
if (expression.kind == "BinaryExpression" && ["BooleanAnd", "BooleanOr"].includes(expression.operation) &&
|
|
498
|
+
(containsEffect(expression.left) || containsEffect(expression.right))) return expression
|
|
499
|
+
for (const child of children(expression)) {
|
|
500
|
+
const found = findConditionalEffect(child)
|
|
501
|
+
if (found) return found
|
|
502
|
+
}
|
|
503
|
+
return undefined
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Checks whether an expression evaluates an effect.
|
|
508
|
+
* @param {import("../semantic/types.js").Expression} expression - Expression root.
|
|
509
|
+
* @returns {boolean} Whether an effect is reachable.
|
|
510
|
+
*/
|
|
511
|
+
function containsEffect(expression) {
|
|
512
|
+
if (!expression || typeof expression != "object") return false
|
|
513
|
+
return expression.kind == "EffectCallExpression" || Boolean(Reflect.get(expression, "effectSiteId")) || children(expression).some(containsEffect)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Returns child expressions in evaluation order.
|
|
518
|
+
* @param {import("../semantic/types.js").Expression} expression - Parent expression.
|
|
519
|
+
* @returns {import("../semantic/types.js").Expression[]} Children.
|
|
520
|
+
*/
|
|
521
|
+
function children(expression) {
|
|
522
|
+
if (!expression || typeof expression != "object") return []
|
|
523
|
+
if (expression.kind == "CallExpression" || expression.kind == "EffectCallExpression" || expression.kind == "ReferenceConstruction" ||
|
|
524
|
+
expression.kind == "RecordConstruction") return expression.arguments
|
|
525
|
+
if (expression.kind == "MethodCallExpression") return [expression.receiver, ...expression.arguments]
|
|
526
|
+
if (expression.kind == "OwnedMoveExpression" || expression.kind == "OwnedBorrowExpression") return [expression.expression]
|
|
527
|
+
if (expression.kind == "BinaryExpression") return [expression.left, expression.right]
|
|
528
|
+
if (expression.kind == "UnaryExpression") return [expression.operand]
|
|
529
|
+
if (expression.kind == "OptionalSome") return [expression.value]
|
|
530
|
+
if (expression.kind == "OptionalIsPresent" || expression.kind == "OptionalUnwrap") return [expression.operand]
|
|
531
|
+
if (expression.kind == "ListLiteral") return expression.elements
|
|
532
|
+
if (expression.kind == "MapLiteral" || expression.kind == "OrderedMapLiteral") return expression.entries.flatMap(({key, value}) => [key, value])
|
|
533
|
+
if (expression.kind == "ListIndexExpression") return [expression.collection, expression.index]
|
|
534
|
+
if (expression.kind == "MapLookupExpression") return [expression.collection, expression.key]
|
|
535
|
+
if (expression.kind == "CollectionSizeExpression") return [expression.collection]
|
|
536
|
+
if (expression.kind == "MemberRead") return [expression.receiver]
|
|
537
|
+
return []
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const phpSupport = `/* semantifold-task034-support */
|
|
541
|
+
final class ProbeOperationFailure extends RuntimeException {}
|
|
542
|
+
final class ProbeAcquireFailure extends RuntimeException {}
|
|
543
|
+
final class ProbeReadFailure extends RuntimeException {}
|
|
544
|
+
final class ProbeCloseFailure extends RuntimeException {}
|
|
545
|
+
final class ProbeResourceClosed extends RuntimeException {}
|
|
546
|
+
final class ProbeResource {
|
|
547
|
+
public bool $closed = false;
|
|
548
|
+
public function __construct(public mixed $handle) {}
|
|
549
|
+
}
|
|
550
|
+
$GLOBALS['__semantifold_task034_trace'] = [];
|
|
551
|
+
function probeEffect(string $label, int $value, bool $fail): int {
|
|
552
|
+
$GLOBALS['__semantifold_task034_trace'][] = 'effect:' . $label;
|
|
553
|
+
if ($fail) throw new ProbeOperationFailure('ProbeOperationFailure');
|
|
554
|
+
return $value;
|
|
555
|
+
}
|
|
556
|
+
function probeAcquire(bool $fail): ProbeResource {
|
|
557
|
+
$GLOBALS['__semantifold_task034_trace'][] = 'acquire';
|
|
558
|
+
if ($fail) throw new ProbeAcquireFailure('ProbeAcquireFailure');
|
|
559
|
+
try { $handle = @fopen((string) getenv('SEMANTIFOLD_TASK034_PROBE_PATH'), 'rb'); }
|
|
560
|
+
catch (Throwable) { throw new ProbeAcquireFailure('ProbeAcquireFailure'); }
|
|
561
|
+
if ($handle === false) throw new ProbeAcquireFailure('ProbeAcquireFailure');
|
|
562
|
+
return new ProbeResource($handle);
|
|
563
|
+
}
|
|
564
|
+
function probeRead(ProbeResource $resource, bool $fail): ?string {
|
|
565
|
+
if ($resource->closed) throw new ProbeResourceClosed('ProbeResourceClosed');
|
|
566
|
+
$GLOBALS['__semantifold_task034_trace'][] = 'read';
|
|
567
|
+
if ($fail) throw new ProbeReadFailure('ProbeReadFailure');
|
|
568
|
+
try { $line = @fgets($resource->handle); }
|
|
569
|
+
catch (Throwable) { throw new ProbeReadFailure('ProbeReadFailure'); }
|
|
570
|
+
if ($line === false) {
|
|
571
|
+
if (feof($resource->handle)) return null;
|
|
572
|
+
throw new ProbeReadFailure('ProbeReadFailure');
|
|
573
|
+
}
|
|
574
|
+
return rtrim($line, "\\r\\n");
|
|
575
|
+
}
|
|
576
|
+
function probeClose(ProbeResource $resource, bool $fail): void {
|
|
577
|
+
if ($resource->closed) throw new ProbeResourceClosed('ProbeResourceClosed');
|
|
578
|
+
$GLOBALS['__semantifold_task034_trace'][] = 'close';
|
|
579
|
+
try { $closed = @fclose($resource->handle); }
|
|
580
|
+
catch (Throwable) { $resource->closed = true; throw new ProbeCloseFailure('ProbeCloseFailure'); }
|
|
581
|
+
$resource->closed = true;
|
|
582
|
+
if ($fail || !$closed) throw new ProbeCloseFailure('ProbeCloseFailure');
|
|
583
|
+
}
|
|
584
|
+
function probeTrace(): string { return implode(',', $GLOBALS['__semantifold_task034_trace']); }
|
|
585
|
+
/* semantifold-task034-support-end */
|
|
586
|
+
|
|
587
|
+
`
|
|
588
|
+
|
|
589
|
+
const rubySupport = `# semantifold-task034-support
|
|
590
|
+
class ProbeOperationFailure < StandardError; end
|
|
591
|
+
class ProbeAcquireFailure < StandardError; end
|
|
592
|
+
class ProbeReadFailure < StandardError; end
|
|
593
|
+
class ProbeCloseFailure < StandardError; end
|
|
594
|
+
class ProbeResourceClosed < StandardError; end
|
|
595
|
+
class ProbeResource
|
|
596
|
+
attr_accessor :handle, :closed
|
|
597
|
+
def initialize(handle); @handle = handle; @closed = false; end
|
|
598
|
+
end
|
|
599
|
+
$__semantifold_task034_trace = []
|
|
600
|
+
def probeEffect(label, value, fail_value)
|
|
601
|
+
$__semantifold_task034_trace << "effect:#{label}"
|
|
602
|
+
raise ProbeOperationFailure, "ProbeOperationFailure" if fail_value
|
|
603
|
+
value
|
|
604
|
+
end
|
|
605
|
+
def probeAcquire(fail_value)
|
|
606
|
+
$__semantifold_task034_trace << "acquire"
|
|
607
|
+
raise ProbeAcquireFailure, "ProbeAcquireFailure" if fail_value
|
|
608
|
+
begin; ProbeResource.new(File.open(ENV.fetch("SEMANTIFOLD_TASK034_PROBE_PATH"), "r")); rescue ProbeAcquireFailure; raise; rescue StandardError; raise ProbeAcquireFailure, "ProbeAcquireFailure"; end
|
|
609
|
+
end
|
|
610
|
+
def probeRead(resource, fail_value)
|
|
611
|
+
raise ProbeResourceClosed, "ProbeResourceClosed" if resource.closed
|
|
612
|
+
$__semantifold_task034_trace << "read"
|
|
613
|
+
raise ProbeReadFailure, "ProbeReadFailure" if fail_value
|
|
614
|
+
begin; value = resource.handle.gets; value.nil? ? nil : value.chomp; rescue ProbeReadFailure; raise; rescue StandardError; raise ProbeReadFailure, "ProbeReadFailure"; end
|
|
615
|
+
end
|
|
616
|
+
def probeClose(resource, fail_value)
|
|
617
|
+
raise ProbeResourceClosed, "ProbeResourceClosed" if resource.closed
|
|
618
|
+
$__semantifold_task034_trace << "close"
|
|
619
|
+
begin; resource.handle.close; rescue StandardError; resource.closed = true; raise ProbeCloseFailure, "ProbeCloseFailure"; end
|
|
620
|
+
resource.closed = true
|
|
621
|
+
raise ProbeCloseFailure, "ProbeCloseFailure" if fail_value
|
|
622
|
+
nil
|
|
623
|
+
end
|
|
624
|
+
def probeTrace; $__semantifold_task034_trace.join(","); end
|
|
625
|
+
# semantifold-task034-support-end
|
|
626
|
+
|
|
627
|
+
`
|
|
628
|
+
|
|
629
|
+
const javascriptSupport = `/* semantifold-task034-support */
|
|
630
|
+
const __semantifoldTask034Fs = process.getBuiltinModule("node:fs")
|
|
631
|
+
class ProbeOperationFailure extends Error {}
|
|
632
|
+
class ProbeAcquireFailure extends Error {}
|
|
633
|
+
class ProbeReadFailure extends Error {}
|
|
634
|
+
class ProbeCloseFailure extends Error {}
|
|
635
|
+
class ProbeResourceClosed extends Error {}
|
|
636
|
+
class ProbeResource { constructor(handle) { this.handle = handle; this.closed = false; this.position = 0 } }
|
|
637
|
+
const __semantifoldTask034Trace = []
|
|
638
|
+
function probeEffect(label, value, fail) { __semantifoldTask034Trace.push(\`effect:\${label}\`); if (fail) throw new ProbeOperationFailure("ProbeOperationFailure"); return value }
|
|
639
|
+
function probeAcquire(fail) { __semantifoldTask034Trace.push("acquire"); if (fail) throw new ProbeAcquireFailure("ProbeAcquireFailure"); try { return new ProbeResource(__semantifoldTask034Fs.openSync(process.env.SEMANTIFOLD_TASK034_PROBE_PATH, "r")) } catch { throw new ProbeAcquireFailure("ProbeAcquireFailure") } }
|
|
640
|
+
function probeRead(resource, fail) { if (resource.closed) throw new ProbeResourceClosed("ProbeResourceClosed"); __semantifoldTask034Trace.push("read"); if (fail) throw new ProbeReadFailure("ProbeReadFailure"); try { const bytes = []; const buffer = Buffer.alloc(1); while (true) { const count = __semantifoldTask034Fs.readSync(resource.handle, buffer, 0, 1, resource.position++); if (count === 0) return bytes.length === 0 ? null : Buffer.from(bytes).toString("utf8"); if (buffer[0] === 10) return Buffer.from(bytes).toString("utf8").replace(/\\r$/u, ""); bytes.push(buffer[0]) } } catch { throw new ProbeReadFailure("ProbeReadFailure") } }
|
|
641
|
+
function probeClose(resource, fail) { if (resource.closed) throw new ProbeResourceClosed("ProbeResourceClosed"); __semantifoldTask034Trace.push("close"); try { __semantifoldTask034Fs.closeSync(resource.handle) } catch { resource.closed = true; throw new ProbeCloseFailure("ProbeCloseFailure") } resource.closed = true; if (fail) throw new ProbeCloseFailure("ProbeCloseFailure") }
|
|
642
|
+
function probeTrace() { return __semantifoldTask034Trace.join(",") }
|
|
643
|
+
/* semantifold-task034-support-end */
|
|
644
|
+
|
|
645
|
+
`
|
|
646
|
+
|
|
647
|
+
const typescriptSupport = `/* semantifold-task034-support */
|
|
648
|
+
const __semantifoldTask034Fs = process.getBuiltinModule("node:fs")
|
|
649
|
+
class ProbeOperationFailure extends Error {}
|
|
650
|
+
class ProbeAcquireFailure extends Error {}
|
|
651
|
+
class ProbeReadFailure extends Error {}
|
|
652
|
+
class ProbeCloseFailure extends Error {}
|
|
653
|
+
class ProbeResourceClosed extends Error {}
|
|
654
|
+
class ProbeResource { closed = false; position = 0; constructor(readonly handle: number) {} }
|
|
655
|
+
const __semantifoldTask034Trace: string[] = []
|
|
656
|
+
function probeEffect(label: string, value: number, fail: boolean): number { __semantifoldTask034Trace.push(\`effect:\${label}\`); if (fail) throw new ProbeOperationFailure("ProbeOperationFailure"); return value }
|
|
657
|
+
function probeAcquire(fail: boolean): ProbeResource { __semantifoldTask034Trace.push("acquire"); if (fail) throw new ProbeAcquireFailure("ProbeAcquireFailure"); try { return new ProbeResource(__semantifoldTask034Fs.openSync(process.env.SEMANTIFOLD_TASK034_PROBE_PATH as string, "r")) } catch { throw new ProbeAcquireFailure("ProbeAcquireFailure") } }
|
|
658
|
+
function probeRead(resource: ProbeResource, fail: boolean): string | null { if (resource.closed) throw new ProbeResourceClosed("ProbeResourceClosed"); __semantifoldTask034Trace.push("read"); if (fail) throw new ProbeReadFailure("ProbeReadFailure"); try { const bytes: number[] = []; const buffer = Buffer.alloc(1); while (true) { const count = __semantifoldTask034Fs.readSync(resource.handle, buffer, 0, 1, resource.position++); if (count === 0) return bytes.length === 0 ? null : Buffer.from(bytes).toString("utf8"); if (buffer[0] === 10) return Buffer.from(bytes).toString("utf8").replace(/\\r$/u, ""); bytes.push(buffer[0]) } } catch { throw new ProbeReadFailure("ProbeReadFailure") } }
|
|
659
|
+
function probeClose(resource: ProbeResource, fail: boolean): void { if (resource.closed) throw new ProbeResourceClosed("ProbeResourceClosed"); __semantifoldTask034Trace.push("close"); try { __semantifoldTask034Fs.closeSync(resource.handle) } catch { resource.closed = true; throw new ProbeCloseFailure("ProbeCloseFailure") } resource.closed = true; if (fail) throw new ProbeCloseFailure("ProbeCloseFailure") }
|
|
660
|
+
function probeTrace(): string { return __semantifoldTask034Trace.join(",") }
|
|
661
|
+
/* semantifold-task034-support-end */
|
|
662
|
+
|
|
663
|
+
`
|
|
664
|
+
|
|
665
|
+
const javaTopSupport = `// semantifold-task034-support
|
|
666
|
+
final class ProbeOperationFailure extends RuntimeException { ProbeOperationFailure() { super("ProbeOperationFailure"); } }
|
|
667
|
+
final class ProbeAcquireFailure extends RuntimeException { ProbeAcquireFailure() { super("ProbeAcquireFailure"); } }
|
|
668
|
+
final class ProbeReadFailure extends RuntimeException { ProbeReadFailure() { super("ProbeReadFailure"); } }
|
|
669
|
+
final class ProbeCloseFailure extends RuntimeException { ProbeCloseFailure() { super("ProbeCloseFailure"); } }
|
|
670
|
+
final class ProbeResourceClosed extends RuntimeException { ProbeResourceClosed() { super("ProbeResourceClosed"); } }
|
|
671
|
+
final class ProbeResource { final java.nio.channels.FileChannel handle; boolean closed = false; ProbeResource(java.nio.channels.FileChannel handle) { this.handle = handle; } }
|
|
672
|
+
// semantifold-task034-support-top-end
|
|
673
|
+
|
|
674
|
+
`
|
|
675
|
+
|
|
676
|
+
const javaMemberSupport = ` // semantifold-task034-support-members
|
|
677
|
+
private static final java.util.ArrayList<String> __semantifoldTask034Trace = new java.util.ArrayList<>();
|
|
678
|
+
static int probeEffect(String label, int value, boolean fail) { __semantifoldTask034Trace.add("effect:" + label); if (fail) throw new ProbeOperationFailure(); return value; }
|
|
679
|
+
static ProbeResource probeAcquire(boolean fail) { __semantifoldTask034Trace.add("acquire"); if (fail) throw new ProbeAcquireFailure(); try { return new ProbeResource(java.nio.channels.FileChannel.open(java.nio.file.Path.of(System.getenv("SEMANTIFOLD_TASK034_PROBE_PATH")))); } catch (RuntimeException | java.io.IOException exception) { throw new ProbeAcquireFailure(); } }
|
|
680
|
+
static java.util.Optional<String> probeRead(ProbeResource resource, boolean fail) { if (resource.closed) throw new ProbeResourceClosed(); __semantifoldTask034Trace.add("read"); if (fail) throw new ProbeReadFailure(); try { java.io.ByteArrayOutputStream bytes = new java.io.ByteArrayOutputStream(); java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(1); while (true) { buffer.clear(); int count = resource.handle.read(buffer); if (count < 0) return bytes.size() == 0 ? java.util.Optional.empty() : java.util.Optional.of(bytes.toString(java.nio.charset.StandardCharsets.UTF_8)); buffer.flip(); byte value = buffer.get(); if (value == 10) return java.util.Optional.of(bytes.toString(java.nio.charset.StandardCharsets.UTF_8).replaceFirst("\\r$", "")); bytes.write(value); } } catch (java.io.IOException exception) { throw new ProbeReadFailure(); } }
|
|
681
|
+
static void probeClose(ProbeResource resource, boolean fail) { if (resource.closed) throw new ProbeResourceClosed(); __semantifoldTask034Trace.add("close"); try { resource.handle.close(); } catch (java.io.IOException exception) { resource.closed = true; throw new ProbeCloseFailure(); } resource.closed = true; if (fail) throw new ProbeCloseFailure(); }
|
|
682
|
+
static String probeTrace() { return String.join(",", __semantifoldTask034Trace); }
|
|
683
|
+
// semantifold-task034-support-members-end
|
|
684
|
+
|
|
685
|
+
`
|
|
686
|
+
|
|
687
|
+
const javaProgramNestedSupport = ` // semantifold-task034-support-program
|
|
688
|
+
public static final class ProbeOperationFailure extends RuntimeException { ProbeOperationFailure() { super("ProbeOperationFailure"); } }
|
|
689
|
+
public static final class ProbeAcquireFailure extends RuntimeException { ProbeAcquireFailure() { super("ProbeAcquireFailure"); } }
|
|
690
|
+
public static final class ProbeReadFailure extends RuntimeException { ProbeReadFailure() { super("ProbeReadFailure"); } }
|
|
691
|
+
public static final class ProbeCloseFailure extends RuntimeException { ProbeCloseFailure() { super("ProbeCloseFailure"); } }
|
|
692
|
+
public static final class ProbeResourceClosed extends RuntimeException { ProbeResourceClosed() { super("ProbeResourceClosed"); } }
|
|
693
|
+
public static final class ProbeResource { final java.nio.channels.FileChannel handle; boolean closed = false; ProbeResource(java.nio.channels.FileChannel handle) { this.handle = handle; } }
|
|
694
|
+
// semantifold-task034-support-program-end
|
|
695
|
+
|
|
696
|
+
`
|
|
697
|
+
|
|
698
|
+
/** @type {Record<string, string>} */
|
|
699
|
+
const javaProviderShims = {
|
|
700
|
+
probeAcquire: "public static ProbeResource __semantifold_provider_java_probeAcquire(boolean fail) { return probeAcquire(fail); }",
|
|
701
|
+
probeClose: "public static void __semantifold_provider_java_probeClose(ProbeResource resource, boolean fail) { probeClose(resource, fail); }",
|
|
702
|
+
probeEffect: "public static int __semantifold_provider_java_probeEffect(String label, int value, boolean fail) { return probeEffect(label, value, fail); }",
|
|
703
|
+
probeRead: "public static java.util.Optional<String> __semantifold_provider_java_probeRead(ProbeResource resource, boolean fail) { return probeRead(resource, fail); }",
|
|
704
|
+
probeTrace: "public static String __semantifold_provider_java_probeTrace() { return probeTrace(); }"
|
|
705
|
+
}
|