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.
Files changed (303) hide show
  1. package/README.md +61 -15
  2. package/build/index.d.ts +52 -2
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +60 -8
  5. package/build/src/artifact-path.d.ts +23 -1
  6. package/build/src/artifact-path.d.ts.map +1 -1
  7. package/build/src/artifact-path.js +45 -3
  8. package/build/src/artifacts.d.ts.map +1 -1
  9. package/build/src/artifacts.js +66 -1
  10. package/build/src/backends/android.d.ts +49 -0
  11. package/build/src/backends/android.d.ts.map +1 -0
  12. package/build/src/backends/android.js +1274 -0
  13. package/build/src/backends/c-validation.d.ts.map +1 -1
  14. package/build/src/backends/c-validation.js +7 -3
  15. package/build/src/backends/cpp-validation.d.ts.map +1 -1
  16. package/build/src/backends/cpp-validation.js +7 -3
  17. package/build/src/backends/csharp.js +7 -1
  18. package/build/src/backends/dart-runtime.d.ts +2 -0
  19. package/build/src/backends/dart-runtime.d.ts.map +1 -0
  20. package/build/src/backends/dart-runtime.js +41 -0
  21. package/build/src/backends/dart.d.ts +20 -0
  22. package/build/src/backends/dart.d.ts.map +1 -0
  23. package/build/src/backends/dart.js +321 -0
  24. package/build/src/backends/effects.d.ts +60 -0
  25. package/build/src/backends/effects.d.ts.map +1 -0
  26. package/build/src/backends/effects.js +746 -0
  27. package/build/src/backends/go.js +18 -4
  28. package/build/src/backends/identifiers.d.ts +36 -4
  29. package/build/src/backends/identifiers.d.ts.map +1 -1
  30. package/build/src/backends/identifiers.js +160 -10
  31. package/build/src/backends/index.d.ts.map +1 -1
  32. package/build/src/backends/index.js +27 -4
  33. package/build/src/backends/ios.d.ts +68 -0
  34. package/build/src/backends/ios.d.ts.map +1 -0
  35. package/build/src/backends/ios.js +1503 -0
  36. package/build/src/backends/java.d.ts.map +1 -1
  37. package/build/src/backends/java.js +429 -36
  38. package/build/src/backends/javascript.d.ts +6 -0
  39. package/build/src/backends/javascript.d.ts.map +1 -1
  40. package/build/src/backends/javascript.js +380 -24
  41. package/build/src/backends/kotlin-runtime.d.ts +3 -0
  42. package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
  43. package/build/src/backends/kotlin-runtime.js +29 -0
  44. package/build/src/backends/kotlin.d.ts +33 -0
  45. package/build/src/backends/kotlin.d.ts.map +1 -0
  46. package/build/src/backends/kotlin.js +138 -0
  47. package/build/src/backends/native-validation.d.ts +2 -2
  48. package/build/src/backends/native-validation.d.ts.map +1 -1
  49. package/build/src/backends/native-validation.js +2 -2
  50. package/build/src/backends/ordered-expressions.d.ts.map +1 -1
  51. package/build/src/backends/ordered-expressions.js +39 -7
  52. package/build/src/backends/php-stdlib-support.d.ts +19 -0
  53. package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
  54. package/build/src/backends/php-stdlib-support.js +227 -0
  55. package/build/src/backends/php.d.ts.map +1 -1
  56. package/build/src/backends/php.js +448 -33
  57. package/build/src/backends/program.d.ts +83 -0
  58. package/build/src/backends/program.d.ts.map +1 -0
  59. package/build/src/backends/program.js +1309 -0
  60. package/build/src/backends/python.js +7 -1
  61. package/build/src/backends/ruby.d.ts.map +1 -1
  62. package/build/src/backends/ruby.js +310 -24
  63. package/build/src/backends/rust-runtime.d.ts +7 -0
  64. package/build/src/backends/rust-runtime.d.ts.map +1 -0
  65. package/build/src/backends/rust-runtime.js +32 -0
  66. package/build/src/backends/rust-validation.d.ts +9 -0
  67. package/build/src/backends/rust-validation.d.ts.map +1 -0
  68. package/build/src/backends/rust-validation.js +78 -0
  69. package/build/src/backends/rust.d.ts +24 -0
  70. package/build/src/backends/rust.d.ts.map +1 -0
  71. package/build/src/backends/rust.js +344 -0
  72. package/build/src/backends/scalars.d.ts +14 -6
  73. package/build/src/backends/scalars.d.ts.map +1 -1
  74. package/build/src/backends/scalars.js +167 -17
  75. package/build/src/backends/shared.d.ts +23 -4
  76. package/build/src/backends/shared.d.ts.map +1 -1
  77. package/build/src/backends/shared.js +2174 -62
  78. package/build/src/backends/stdlib-support.d.ts +14 -0
  79. package/build/src/backends/stdlib-support.d.ts.map +1 -0
  80. package/build/src/backends/stdlib-support.js +237 -0
  81. package/build/src/backends/swift-runtime.d.ts +3 -0
  82. package/build/src/backends/swift-runtime.d.ts.map +1 -0
  83. package/build/src/backends/swift-runtime.js +14 -0
  84. package/build/src/backends/swift.d.ts +8 -0
  85. package/build/src/backends/swift.d.ts.map +1 -0
  86. package/build/src/backends/swift.js +127 -0
  87. package/build/src/backends/typescript.d.ts.map +1 -1
  88. package/build/src/backends/typescript.js +344 -24
  89. package/build/src/backends/wasm.d.ts +43 -0
  90. package/build/src/backends/wasm.d.ts.map +1 -0
  91. package/build/src/backends/wasm.js +2164 -0
  92. package/build/src/backends/writer.d.ts +255 -4
  93. package/build/src/backends/writer.d.ts.map +1 -1
  94. package/build/src/backends/writer.js +491 -3
  95. package/build/src/diagnostic.d.ts +4 -3
  96. package/build/src/diagnostic.d.ts.map +1 -1
  97. package/build/src/diagnostic.js +5 -3
  98. package/build/src/frontends/c.d.ts.map +1 -1
  99. package/build/src/frontends/c.js +5 -3
  100. package/build/src/frontends/cpp.d.ts.map +1 -1
  101. package/build/src/frontends/cpp.js +5 -3
  102. package/build/src/frontends/csharp.d.ts.map +1 -1
  103. package/build/src/frontends/csharp.js +7 -3
  104. package/build/src/frontends/dart.d.ts +10 -0
  105. package/build/src/frontends/dart.d.ts.map +1 -0
  106. package/build/src/frontends/dart.js +913 -0
  107. package/build/src/frontends/index.d.ts +3 -1
  108. package/build/src/frontends/index.d.ts.map +1 -1
  109. package/build/src/frontends/index.js +15 -5
  110. package/build/src/frontends/java.d.ts +110 -1
  111. package/build/src/frontends/java.d.ts.map +1 -1
  112. package/build/src/frontends/java.js +1725 -70
  113. package/build/src/frontends/javascript-typescript.d.ts +69 -1
  114. package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
  115. package/build/src/frontends/javascript-typescript.js +1825 -93
  116. package/build/src/frontends/kotlin.d.ts +10 -0
  117. package/build/src/frontends/kotlin.d.ts.map +1 -0
  118. package/build/src/frontends/kotlin.js +685 -0
  119. package/build/src/frontends/php.d.ts +118 -1
  120. package/build/src/frontends/php.d.ts.map +1 -1
  121. package/build/src/frontends/php.js +1583 -76
  122. package/build/src/frontends/program.d.ts +74 -0
  123. package/build/src/frontends/program.d.ts.map +1 -0
  124. package/build/src/frontends/program.js +989 -0
  125. package/build/src/frontends/ruby.d.ts +68 -1
  126. package/build/src/frontends/ruby.d.ts.map +1 -1
  127. package/build/src/frontends/ruby.js +1446 -101
  128. package/build/src/frontends/rust-parser.d.ts +11 -0
  129. package/build/src/frontends/rust-parser.d.ts.map +1 -0
  130. package/build/src/frontends/rust-parser.js +15 -0
  131. package/build/src/frontends/rust.d.ts +14 -0
  132. package/build/src/frontends/rust.d.ts.map +1 -0
  133. package/build/src/frontends/rust.js +715 -0
  134. package/build/src/frontends/scalars.d.ts +10 -0
  135. package/build/src/frontends/scalars.d.ts.map +1 -1
  136. package/build/src/frontends/scalars.js +28 -2
  137. package/build/src/frontends/swift.d.ts +10 -0
  138. package/build/src/frontends/swift.d.ts.map +1 -0
  139. package/build/src/frontends/swift.js +860 -0
  140. package/build/src/frontends/types.d.ts +186 -0
  141. package/build/src/frontends/types.d.ts.map +1 -0
  142. package/build/src/frontends/types.js +634 -0
  143. package/build/src/language-registry.d.ts +46 -4
  144. package/build/src/language-registry.d.ts.map +1 -1
  145. package/build/src/language-registry.js +177 -13
  146. package/build/src/mapping.d.ts +2 -2
  147. package/build/src/mapping.d.ts.map +1 -1
  148. package/build/src/mapping.js +31 -10
  149. package/build/src/semantic/capabilities.d.ts +66 -0
  150. package/build/src/semantic/capabilities.d.ts.map +1 -0
  151. package/build/src/semantic/capabilities.js +649 -0
  152. package/build/src/semantic/effects.d.ts +26 -0
  153. package/build/src/semantic/effects.d.ts.map +1 -0
  154. package/build/src/semantic/effects.js +764 -0
  155. package/build/src/semantic/generics.d.ts +23 -0
  156. package/build/src/semantic/generics.d.ts.map +1 -0
  157. package/build/src/semantic/generics.js +61 -0
  158. package/build/src/semantic/lifetime.d.ts +37 -0
  159. package/build/src/semantic/lifetime.d.ts.map +1 -0
  160. package/build/src/semantic/lifetime.js +527 -0
  161. package/build/src/semantic/provenance.d.ts +9 -2
  162. package/build/src/semantic/provenance.d.ts.map +1 -1
  163. package/build/src/semantic/provenance.js +462 -20
  164. package/build/src/semantic/scalars.d.ts +11 -0
  165. package/build/src/semantic/scalars.d.ts.map +1 -1
  166. package/build/src/semantic/scalars.js +16 -1
  167. package/build/src/semantic/stdlib.d.ts +254 -0
  168. package/build/src/semantic/stdlib.d.ts.map +1 -0
  169. package/build/src/semantic/stdlib.js +880 -0
  170. package/build/src/semantic/types.d.ts +3108 -178
  171. package/build/src/semantic/types.d.ts.map +1 -1
  172. package/build/src/semantic/types.js +730 -15
  173. package/build/src/semantic/validate.d.ts +85 -5
  174. package/build/src/semantic/validate.d.ts.map +1 -1
  175. package/build/src/semantic/validate.js +2576 -98
  176. package/build/src/stdlib-facades.d.ts +304 -0
  177. package/build/src/stdlib-facades.d.ts.map +1 -0
  178. package/build/src/stdlib-facades.js +1167 -0
  179. package/build/src/stdlib-negotiation.d.ts +69 -0
  180. package/build/src/stdlib-negotiation.d.ts.map +1 -0
  181. package/build/src/stdlib-negotiation.js +403 -0
  182. package/build/src/stdlib-providers.d.ts +72 -0
  183. package/build/src/stdlib-providers.d.ts.map +1 -0
  184. package/build/src/stdlib-providers.js +339 -0
  185. package/build/src/toolchains.d.ts +55 -1
  186. package/build/src/toolchains.d.ts.map +1 -1
  187. package/build/src/toolchains.js +15 -4
  188. package/docs/android.md +79 -0
  189. package/docs/architecture.md +47 -13
  190. package/docs/dart.md +60 -0
  191. package/docs/goals.md +3 -3
  192. package/docs/ios.md +121 -0
  193. package/docs/kotlin.md +42 -0
  194. package/docs/language-support.md +238 -26
  195. package/docs/multi-file-modules.md +52 -0
  196. package/docs/parser-qualification.md +121 -8
  197. package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
  198. package/docs/rust.md +88 -0
  199. package/docs/source-maps.md +17 -7
  200. package/docs/specification.md +5 -0
  201. package/docs/standard-library-portability.md +39 -8
  202. package/docs/swift.md +44 -0
  203. package/docs/testing.md +381 -4
  204. package/docs/webassembly.md +52 -0
  205. package/index.js +66 -8
  206. package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
  207. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
  208. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
  209. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
  210. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
  211. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
  212. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
  213. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
  214. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
  215. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
  216. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
  217. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
  218. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
  219. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
  220. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
  221. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
  222. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
  223. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
  224. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
  225. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
  226. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
  227. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
  228. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
  229. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
  230. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
  231. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
  232. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
  233. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
  234. package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
  235. package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
  236. package/package.json +5 -2
  237. package/src/artifact-path.js +47 -2
  238. package/src/artifacts.js +67 -0
  239. package/src/backends/android.js +1370 -0
  240. package/src/backends/c-validation.js +6 -1
  241. package/src/backends/cpp-validation.js +6 -1
  242. package/src/backends/csharp.js +3 -0
  243. package/src/backends/dart-runtime.js +41 -0
  244. package/src/backends/dart.js +326 -0
  245. package/src/backends/effects.js +705 -0
  246. package/src/backends/go.js +14 -2
  247. package/src/backends/identifiers.js +166 -9
  248. package/src/backends/index.js +27 -2
  249. package/src/backends/ios.js +1612 -0
  250. package/src/backends/java.js +454 -36
  251. package/src/backends/javascript.js +389 -23
  252. package/src/backends/kotlin-runtime.js +29 -0
  253. package/src/backends/kotlin.js +144 -0
  254. package/src/backends/native-validation.js +1 -1
  255. package/src/backends/ordered-expressions.js +40 -6
  256. package/src/backends/php-stdlib-support.js +239 -0
  257. package/src/backends/php.js +469 -32
  258. package/src/backends/program.js +1408 -0
  259. package/src/backends/python.js +3 -0
  260. package/src/backends/ruby.js +326 -23
  261. package/src/backends/rust-runtime.js +34 -0
  262. package/src/backends/rust-validation.js +75 -0
  263. package/src/backends/rust.js +335 -0
  264. package/src/backends/scalars.js +141 -16
  265. package/src/backends/shared.js +2314 -115
  266. package/src/backends/stdlib-support.js +234 -0
  267. package/src/backends/swift-runtime.js +14 -0
  268. package/src/backends/swift.js +132 -0
  269. package/src/backends/typescript.js +349 -23
  270. package/src/backends/wasm.js +2208 -0
  271. package/src/backends/writer.js +545 -2
  272. package/src/diagnostic.js +4 -2
  273. package/src/frontends/c.js +4 -2
  274. package/src/frontends/cpp.js +4 -2
  275. package/src/frontends/csharp.js +4 -2
  276. package/src/frontends/dart.js +963 -0
  277. package/src/frontends/index.js +14 -4
  278. package/src/frontends/java.js +1977 -69
  279. package/src/frontends/javascript-typescript.js +2046 -102
  280. package/src/frontends/kotlin.js +713 -0
  281. package/src/frontends/php.js +1725 -79
  282. package/src/frontends/program.js +1062 -0
  283. package/src/frontends/ruby.js +1624 -98
  284. package/src/frontends/rust-parser.js +18 -0
  285. package/src/frontends/rust.js +714 -0
  286. package/src/frontends/scalars.js +31 -1
  287. package/src/frontends/swift.js +893 -0
  288. package/src/frontends/types.js +750 -0
  289. package/src/language-registry.js +182 -12
  290. package/src/mapping.js +33 -9
  291. package/src/semantic/capabilities.js +671 -0
  292. package/src/semantic/effects.js +737 -0
  293. package/src/semantic/generics.js +58 -0
  294. package/src/semantic/lifetime.js +517 -0
  295. package/src/semantic/provenance.js +412 -19
  296. package/src/semantic/scalars.js +17 -0
  297. package/src/semantic/stdlib.js +921 -0
  298. package/src/semantic/types.js +810 -14
  299. package/src/semantic/validate.js +2934 -209
  300. package/src/stdlib-facades.js +1211 -0
  301. package/src/stdlib-negotiation.js +446 -0
  302. package/src/stdlib-providers.js +377 -0
  303. 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
+ }