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
@@ -2,22 +2,138 @@
2
2
 
3
3
  import {createGenerationIndex} from "../semantic/provenance.js"
4
4
 
5
+ /**
6
+ * Collects every caller-controlled binding spelling before synthetic names are chosen.
7
+ * @param {unknown} root - Semantic graph.
8
+ * @returns {Set<string>} Used source names.
9
+ */
10
+ function collectBindingNames(root) {
11
+ const names = new Set()
12
+ const pending = [root]
13
+ const seen = new Set()
14
+
15
+ while (pending.length > 0) {
16
+ const value = pending.pop()
17
+ if (!value || typeof value != "object" || seen.has(value)) continue
18
+ seen.add(value)
19
+ if (!Array.isArray(value) && typeof Reflect.get(value, "name") == "string") names.add(Reflect.get(value, "name"))
20
+ for (const child of Array.isArray(value) ? value : Object.values(value)) {
21
+ if (child && typeof child == "object") pending.push(child)
22
+ }
23
+ }
24
+ return names
25
+ }
26
+
27
+ /**
28
+ * Converts a logical module identity to its canonical target type segment.
29
+ * @param {string} id - Logical module identity.
30
+ * @returns {string} Portable target class/module name.
31
+ */
32
+ function moduleClassName(id) {
33
+ return id.split(/[._-]+/u).map((part) => `${part[0].toUpperCase()}${part.slice(1)}`).join("")
34
+ }
35
+
36
+ /**
37
+ * Looks up one declaration name in its owning program module.
38
+ * @param {Partial<import("../semantic/types.js").SemanticProgramModule>} module - Owning module.
39
+ * @param {string} declarationId - Stable declaration identity.
40
+ * @returns {string} Declaration name.
41
+ */
42
+ function declarationName(module, declarationId) {
43
+ const declaration = [...module.functions ?? [], ...module.records ?? [], ...module.classes ?? [], ...module.errors ?? []]
44
+ .find(({id}) => id == declarationId)
45
+
46
+ if (!declaration) throw new RangeError(`Unknown program declaration '${declarationId}'.`)
47
+
48
+ return declaration.name
49
+ }
50
+
51
+ /**
52
+ * Chooses an unqualified target binding without treating a source-profile qualifier as semantic identity.
53
+ * @param {import("../semantic/types.js").SemanticProgram} program - Owning program.
54
+ * @param {import("../semantic/types.js").SemanticProgramModule} module - Importing module.
55
+ * @param {import("../semantic/types.js").SemanticImport} imported - Resolved import.
56
+ * @returns {string} Target-local binding spelling.
57
+ */
58
+ export function programImportName(program, module, imported) {
59
+ const source = program.sources.find(({filename}) => filename == module.sourceFilename)
60
+
61
+ if (!source) throw new RangeError(`Program module '${module.id}' has no registered source.`)
62
+
63
+ return source.language == "ruby" || source.language == "java" ? imported.importedName : imported.localName
64
+ }
65
+
5
66
  /** Source-aware deterministic generated-output builder. */
6
67
  export class SourceWriter {
7
68
  /**
8
69
  * Creates a source-aware writer.
9
70
  * @param {object} options - Writer options.
10
71
  * @param {string} options.filename - Output filename.
11
- * @param {import("../semantic/types.js").SemanticLanguage} options.language - Output language.
72
+ * @param {import("../semantic/types.js").GeneratedTextLanguage} options.language - Output text language.
12
73
  * @param {import("../semantic/types.js").SemanticModule} options.module - Semantic module.
74
+ * @param {import("../semantic/types.js").SemanticProgram} [options.program] - Owning multi-file program.
75
+ * @param {Map<string, string>} [options.programPaths] - Planned artifact path by module identity.
13
76
  * @param {{filename: string, content: string, language?: import("../semantic/types.js").SemanticLanguage}[]} [options.sources] - Caller-provided sources.
77
+ * @param {Record<string, string>} [options.stdlibProviderEntries] - Used operation to protected native entry for a linked stdlib provider.
78
+ * @param {string} [options.stdlibProviderPath] - Planned stdlib provider artifact path.
79
+ * @param {string[]} [options.stdlibProviderPaths] - Planned stdlib provider artifact paths.
80
+ * @param {string[]} [options.stdlibProviderImports] - Ordered provider names this module must import.
81
+ * @param {string} [options.stdlibProviderOwnerModule] - Java owner module identity hosting the shared support block and shims.
82
+ * @param {string[]} [options.stdlibProviderShims] - Java owner program-wide used operations exposed as public static shims.
83
+ * @param {(expression: import("../semantic/types.js").CallExpression) => string} [options.callNameResolver] - Target-container call spelling override.
84
+ * @param {string} [options.callArgumentSuffix] - Synthetic trailing argument for every semantic function call.
85
+ * @param {boolean} [options.methodStringEquality] - Emit string equality through the platform String method.
14
86
  */
15
- constructor({filename, language, module, sources}) {
87
+ constructor({callArgumentSuffix, callNameResolver, filename, language, methodStringEquality, module, program, programPaths, sources,
88
+ stdlibProviderEntries, stdlibProviderPath, stdlibProviderPaths, stdlibProviderImports, stdlibProviderOwnerModule,
89
+ stdlibProviderShims}) {
16
90
  const index = createGenerationIndex(module, sources)
17
91
 
18
92
  this.filename = filename
19
93
  this.language = language
94
+ this.module = module
95
+ this.program = program
96
+ this.programPaths = programPaths
97
+ this.callArgumentSuffix = callArgumentSuffix
98
+ this.callNameResolver = callNameResolver
99
+ this.methodStringEquality = methodStringEquality ?? false
20
100
  this.index = index
101
+ this.stdlibProviderEntries = stdlibProviderEntries
102
+ this.stdlibProviderPath = stdlibProviderPath
103
+ this.stdlibProviderPaths = stdlibProviderPaths ?? (stdlibProviderPath ? [stdlibProviderPath] : undefined)
104
+ this.stdlibProviderImports = stdlibProviderImports
105
+ this.stdlibProviderOwnerModule = stdlibProviderOwnerModule
106
+ this.stdlibProviderShims = stdlibProviderShims
107
+ const programRecords = program?.modules.flatMap((programModule) => programModule.records ?? []) ?? module.records ?? []
108
+ const programClasses = program?.modules.flatMap((programModule) => programModule.classes ?? []) ?? module.classes ?? []
109
+ const capabilityFailures = module.capabilities?.flatMap(({failures}) => failures) ?? []
110
+ const programErrors = program?.modules.flatMap((programModule) => [
111
+ ...(programModule.errors ?? []),
112
+ ...(programModule.capabilities?.flatMap(({failures}) => failures) ?? [])
113
+ ]) ?? [...module.errors ?? [], ...capabilityFailures]
114
+ const programFunctions = program?.modules.flatMap((programModule) => programModule.functions) ?? module.functions
115
+
116
+ this.records = new Map(programRecords.map((record) => [record.id, record]))
117
+ this.classes = new Map(programClasses.map((declaration) => [declaration.id, declaration]))
118
+ this.errors = new Map(programErrors.map((error) => [error.id, error]))
119
+ this.resources = new Map((module.capabilities?.flatMap(({resources}) => resources) ?? []).map((resource) => [resource.id, resource]))
120
+ this.effectOperations = new Map((module.capabilities?.flatMap(({operations}) => operations) ?? []).map((operation) => [operation.id, operation]))
121
+ this.effectOperationModules = new Map((module.capabilities?.flatMap((capability) =>
122
+ capability.operations.map((operation) => [operation.id, capability.authorityId])) ?? []))
123
+ this.fields = new Map(programRecords.flatMap((record) => record.fields.map((field) => [field.id, field])))
124
+ this.fieldRecords = new Map(programRecords.flatMap((record) => record.fields.map((field) => [field.id, record])))
125
+ this.privateFields = new Map(programClasses.flatMap((declaration) => declaration.fields.map((field) => [field.id, field])))
126
+ this.methods = new Map(programClasses.flatMap((declaration) => declaration.methods.map((method) => [method.id, method])))
127
+ this.typeParameters = new Map([...programRecords, ...programFunctions].flatMap((declaration) =>
128
+ (declaration.typeParameters ?? []).map((parameter) => [parameter.id, parameter])))
129
+ this.referenceClassEmissionDepth = 0
130
+ /** @type {Map<string, import("../semantic/types.js").SemanticProgramModule>} */
131
+ this.declarationModules = new Map(program?.modules.flatMap((programModule) => [
132
+ ...(programModule.records ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
133
+ ...(programModule.classes ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
134
+ ...(programModule.errors ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
135
+ ...programModule.functions.map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule]))
136
+ ]) ?? [])
21
137
  /** @type {string[]} */
22
138
  this.parts = []
23
139
  /** @type {import("../semantic/types.js").SemantifoldMappingSpan[]} */
@@ -25,6 +141,65 @@ export class SourceWriter {
25
141
  this.offset = 0
26
142
  this.line = 1
27
143
  this.column = 1
144
+ /** @type {Map<import("../semantic/types.js").Expression, string>} */
145
+ this.effectTemporaryNames = new Map()
146
+ /** @type {Map<import("../semantic/types.js").Expression, string>} */
147
+ this.effectReplacementNames = new Map()
148
+ /** @type {import("../semantic/types.js").Expression | undefined} */
149
+ this.effectDefinition = undefined
150
+ this.usedBindingNames = collectBindingNames(module)
151
+ }
152
+
153
+ /**
154
+ * Installs the effect expressions lowered immediately before the current statement.
155
+ * @param {import("../semantic/types.js").Expression[]} expressions - Ordered expressions.
156
+ * @returns {void}
157
+ */
158
+ planEffectReplacements(expressions) {
159
+ this.effectReplacementNames = new Map(expressions.map((expression) => [expression, this.effectTemporaryName(expression)]))
160
+ }
161
+
162
+ /**
163
+ * Allocates a collision-safe name for one deterministic effect site.
164
+ * @param {import("../semantic/types.js").Expression} expression - Effectful expression.
165
+ * @returns {string} Stable temporary name.
166
+ */
167
+ effectTemporaryName(expression) {
168
+ const known = this.effectTemporaryNames.get(expression)
169
+ if (known) return known
170
+ const site = typeof Reflect.get(expression, "effectSiteId") == "string"
171
+ ? Reflect.get(expression, "effectSiteId").slice("effect:".length) : String(this.effectTemporaryNames.size)
172
+ let name = `__semantifold_effect_${site}`
173
+
174
+ while (this.usedBindingNames.has(name)) name = `${name}_`
175
+ this.usedBindingNames.add(name)
176
+ this.effectTemporaryNames.set(expression, name)
177
+ return name
178
+ }
179
+
180
+ /**
181
+ * Returns the planned temporary replacement outside its own definition.
182
+ * @param {import("../semantic/types.js").Expression} expression - Candidate expression.
183
+ * @returns {string | undefined} Temporary name.
184
+ */
185
+ effectReplacementName(expression) {
186
+ return this.effectDefinition === expression ? undefined : this.effectReplacementNames.get(expression)
187
+ }
188
+
189
+ /**
190
+ * Emits one effect definition without recursively replacing itself.
191
+ * @param {import("../semantic/types.js").Expression} expression - Defined expression.
192
+ * @param {() => void} emit - Target expression emitter.
193
+ * @returns {void}
194
+ */
195
+ emitEffectDefinition(expression, emit) {
196
+ const previous = this.effectDefinition
197
+ this.effectDefinition = expression
198
+ try {
199
+ emit()
200
+ } finally {
201
+ this.effectDefinition = previous
202
+ }
28
203
  }
29
204
 
30
205
  /**
@@ -44,6 +219,374 @@ export class SourceWriter {
44
219
  return this.index.recordFor(node).path
45
220
  }
46
221
 
222
+ /**
223
+ * Resolves a validated nominal declaration identity for target emission.
224
+ * @param {string} declarationId - Semantic record identity.
225
+ * @returns {import("../semantic/types.js").RecordDeclaration} Record declaration.
226
+ */
227
+ recordForId(declarationId) {
228
+ const record = this.records.get(declarationId)
229
+
230
+ if (!record) throw new RangeError(`Unknown validated record identity '${declarationId}'.`)
231
+
232
+ return record
233
+ }
234
+
235
+ /**
236
+ * Returns the target spelling for a nominal record identity.
237
+ * @param {string} declarationId - Stable record declaration identity.
238
+ * @param {boolean} [valuePosition] - Whether the binding must exist at runtime.
239
+ * @returns {string} Target record spelling.
240
+ */
241
+ recordNameForId(declarationId, valuePosition = false) {
242
+ const record = this.recordForId(declarationId)
243
+ const owner = this.declarationModules.get(declarationId)
244
+ const imported = this.#programModule()?.imports.find((item) =>
245
+ item.declarationId == declarationId && (!valuePosition || !item.typeOnly))
246
+
247
+ if (this.program && owner && owner.id != Reflect.get(this.module, "id") && this.language == "ruby") {
248
+ return `${moduleClassName(owner.id)}::${record.name}`
249
+ }
250
+ if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
251
+ return this.importNameFor(imported)
252
+ }
253
+
254
+ return record.name
255
+ }
256
+
257
+ /**
258
+ * Resolves one validated reference class.
259
+ * @param {string} declarationId - Stable class identity.
260
+ * @returns {import("../semantic/types.js").ClassDeclaration} Class declaration.
261
+ */
262
+ classForId(declarationId) {
263
+ const declaration = this.classes.get(declarationId)
264
+
265
+ if (!declaration) throw new RangeError(`Unknown validated reference class identity '${declarationId}'.`)
266
+
267
+ return declaration
268
+ }
269
+
270
+ /**
271
+ * Returns the target spelling of one reference class.
272
+ * @param {string} declarationId - Stable class identity.
273
+ * @returns {string} Target spelling.
274
+ */
275
+ classNameForId(declarationId) {
276
+ const declaration = this.classForId(declarationId)
277
+ const imported = this.#programModule()?.imports.find((item) => item.declarationId == declarationId)
278
+
279
+ if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
280
+ return this.importNameFor(imported)
281
+ }
282
+ return declaration.name
283
+ }
284
+
285
+ /**
286
+ * Resolves one validated owned-resource declaration.
287
+ * @param {string} resourceId - Stable resource identity.
288
+ * @returns {import("../semantic/types.js").EffectResourceDeclaration} Resource declaration.
289
+ */
290
+ resourceForId(resourceId) {
291
+ const resource = this.resources.get(resourceId)
292
+ if (!resource) throw new RangeError(`Unknown validated resource identity '${resourceId}'.`)
293
+ return resource
294
+ }
295
+
296
+ /**
297
+ * Resolves one validated capability operation declaration.
298
+ * @param {string} operationId - Stable operation identity.
299
+ * @returns {import("../semantic/types.js").EffectOperationDeclaration} Operation declaration.
300
+ */
301
+ effectOperationForId(operationId) {
302
+ const operation = this.effectOperations.get(operationId)
303
+ if (!operation) throw new RangeError(`Unknown validated effect operation identity '${operationId}'.`)
304
+ return operation
305
+ }
306
+
307
+ /**
308
+ * Resolves one validated private field.
309
+ * @param {string} fieldId - Stable private-field identity.
310
+ * @returns {import("../semantic/types.js").PrivateField} Field declaration.
311
+ */
312
+ privateFieldForId(fieldId) {
313
+ const field = this.privateFields.get(fieldId)
314
+
315
+ if (!field) throw new RangeError(`Unknown validated private field identity '${fieldId}'.`)
316
+
317
+ return field
318
+ }
319
+
320
+ /**
321
+ * Resolves one validated receiver method.
322
+ * @param {string} methodId - Stable method identity.
323
+ * @returns {import("../semantic/types.js").MethodDeclaration} Method declaration.
324
+ */
325
+ methodForId(methodId) {
326
+ const method = this.methods.get(methodId)
327
+
328
+ if (!method) throw new RangeError(`Unknown validated method identity '${methodId}'.`)
329
+
330
+ return method
331
+ }
332
+
333
+ /**
334
+ * Resolves one validated declaration-scoped type parameter.
335
+ * @param {string} parameterId - Stable type-parameter identity.
336
+ * @returns {import("../semantic/types.js").TypeParameter} Type parameter.
337
+ */
338
+ typeParameterForId(parameterId) {
339
+ const parameter = this.typeParameters.get(parameterId)
340
+
341
+ if (!parameter) throw new RangeError(`Unknown validated type parameter identity '${parameterId}'.`)
342
+
343
+ return parameter
344
+ }
345
+
346
+ /**
347
+ * Returns the validated nominal error declaration for an identity.
348
+ * @param {string} declarationId - Stable error identity.
349
+ * @returns {import("../semantic/types.js").ErrorDeclaration | import("../semantic/types.js").EffectFailureDeclaration} Error declaration.
350
+ */
351
+ errorForId(declarationId) {
352
+ const error = this.errors.get(declarationId)
353
+
354
+ if (!error) throw new RangeError(`Unknown validated error identity '${declarationId}'.`)
355
+
356
+ return error
357
+ }
358
+
359
+ /**
360
+ * Returns the target-visible spelling for one nominal error identity.
361
+ * @param {string} declarationId - Stable error identity.
362
+ * @returns {string} Target-visible name.
363
+ */
364
+ errorNameForId(declarationId) {
365
+ const error = this.errorForId(declarationId)
366
+ const owner = this.declarationModules.get(declarationId)
367
+ const imported = this.#programModule()?.imports.find((item) => item.declarationId == declarationId)
368
+
369
+ if (this.program && owner && owner.id != Reflect.get(this.module, "id") && this.language == "ruby") {
370
+ return `${moduleClassName(owner.id)}::${error.name}`
371
+ }
372
+ if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
373
+ return this.importNameFor(imported)
374
+ }
375
+
376
+ return owner ? error.name : this.capabilityNominalName(error.name)
377
+ }
378
+
379
+ /**
380
+ * Returns the target spelling for a nominal name owned by a compiler-authorized capability.
381
+ * PHP program entries live in a generated namespace while stdlib provider classes remain
382
+ * global, so PHP program mode fully qualifies capability names.
383
+ * @param {string} name - Declared nominal name.
384
+ * @returns {string} Target spelling.
385
+ */
386
+ capabilityNominalName(name) {
387
+ return this.program && this.language == "php" ? `\\${name}` : name
388
+ }
389
+
390
+ /**
391
+ * Returns the target spelling for a resolved function call.
392
+ * @param {import("../semantic/types.js").CallExpression} expression - Resolved call.
393
+ * @returns {string} Target call name.
394
+ */
395
+ callNameFor(expression) {
396
+ if (this.callNameResolver) return this.callNameResolver(expression)
397
+ const declarationId = expression.resolution?.declarationId
398
+ const owner = declarationId ? this.declarationModules.get(declarationId) : undefined
399
+ const imported = declarationId ? this.#programModule()?.imports.find((item) => item.declarationId == declarationId) : undefined
400
+
401
+ if (this.language == "java" && !this.program && this.referenceClassEmissionDepth > 0) return `Main.${expression.callee}`
402
+ if (!declarationId || !this.program || !owner || owner.id == Reflect.get(this.module, "id")) return expression.callee
403
+ if (this.language == "ruby" || this.language == "java") return `${moduleClassName(owner.id)}.${declarationName(owner, declarationId)}`
404
+ if (imported) return this.importNameFor(imported)
405
+
406
+ return declarationName(owner, declarationId)
407
+ }
408
+
409
+ /**
410
+ * Returns a target-container trailing argument for a semantic call.
411
+ * @param {import("../semantic/types.js").CallExpression} _expression - Resolved semantic call.
412
+ * @returns {string | undefined} Synthetic argument spelling, when configured.
413
+ */
414
+ callArgumentSuffixFor(_expression) {
415
+ return this.callArgumentSuffix
416
+ }
417
+
418
+ /**
419
+ * Reports whether string equality must avoid a target runtime helper.
420
+ * @returns {boolean} Whether to emit the platform String method.
421
+ */
422
+ usesMethodStringEquality() {
423
+ return this.methodStringEquality
424
+ }
425
+
426
+ /** Marks emission as occurring inside one top-level reference class. */
427
+ beginReferenceClassEmission() {
428
+ this.referenceClassEmissionDepth += 1
429
+ }
430
+
431
+ /** Ends one balanced top-level reference-class emission scope. */
432
+ endReferenceClassEmission() {
433
+ if (this.referenceClassEmissionDepth == 0) throw new RangeError("Reference-class emission scope is not active.")
434
+ this.referenceClassEmissionDepth -= 1
435
+ }
436
+
437
+ /**
438
+ * Returns the target-local binding for one resolved import.
439
+ * @param {import("../semantic/types.js").SemanticImport} imported - Resolved import.
440
+ * @returns {string} Emitted import name.
441
+ */
442
+ importNameFor(imported) {
443
+ const module = this.#programModule()
444
+
445
+ if (!this.program || !module) throw new RangeError("Import names require a validated semantic program.")
446
+
447
+ return programImportName(this.program, module, imported)
448
+ }
449
+
450
+ /**
451
+ * Reports whether one local declaration is exported by the current program module.
452
+ * @param {string | undefined} declarationId - Declaration identity.
453
+ * @returns {boolean} Whether it has a same-name program export.
454
+ */
455
+ isDirectlyExported(declarationId) {
456
+ const module = /** @type {Partial<import("../semantic/types.js").SemanticProgramModule>} */ (this.module)
457
+
458
+ return typeof declarationId == "string" && Boolean(module.exports?.some((item) =>
459
+ item.declarationId == declarationId && item.exportedName == declarationName(module, declarationId)))
460
+ }
461
+
462
+ /**
463
+ * Reports whether one export edge uses its declaration's emitted name.
464
+ * @param {import("../semantic/types.js").SemanticExport} exported - Current export edge.
465
+ * @returns {boolean} Whether this edge is represented by the declaration prefix.
466
+ */
467
+ isDirectExport(exported) {
468
+ return exported.exportedName == declarationName(this.module, exported.declarationId)
469
+ }
470
+
471
+ /**
472
+ * Reports whether one local declaration has any public program export.
473
+ * @param {string | undefined} declarationId - Declaration identity.
474
+ * @returns {boolean} Whether the declaration is exported.
475
+ */
476
+ isExported(declarationId) {
477
+ const module = /** @type {Partial<import("../semantic/types.js").SemanticProgramModule>} */ (this.module)
478
+
479
+ return typeof declarationId == "string" && Boolean(module.exports?.some((item) => item.declarationId == declarationId))
480
+ }
481
+
482
+ /**
483
+ * Returns whether this is the selected program entry module.
484
+ * @returns {boolean} Whether this writer owns the selected entry.
485
+ */
486
+ isProgramEntry() {
487
+ return this.program?.entryModule == Reflect.get(this.module, "id")
488
+ }
489
+
490
+ /**
491
+ * Returns the canonical class/module segment for a logical module identity.
492
+ * @param {string} moduleId - Logical module identity.
493
+ * @returns {string} Target class/module name.
494
+ */
495
+ programModuleName(moduleId) {
496
+ if (!this.program?.modules.some(({id}) => id == moduleId)) throw new RangeError(`Unknown program module '${moduleId}'.`)
497
+
498
+ return moduleClassName(moduleId)
499
+ }
500
+
501
+ /**
502
+ * Finds the current module in the complete program.
503
+ * @returns {import("../semantic/types.js").SemanticProgramModule | undefined} Current program module.
504
+ */
505
+ #programModule() {
506
+ if (!this.program) return undefined
507
+
508
+ return this.program.modules.find(({id}) => id == Reflect.get(this.module, "id"))
509
+ }
510
+
511
+ /**
512
+ * Returns a relative ESM/require specifier for a planned dependency artifact.
513
+ * @param {string} moduleId - Dependency module identity.
514
+ * @param {string} [extension] - Optional replacement extension.
515
+ * @returns {string} Relative POSIX specifier.
516
+ */
517
+ relativeModuleSpecifier(moduleId, extension) {
518
+ const targetPath = this.programPaths?.get(moduleId)
519
+
520
+ if (!targetPath) throw new RangeError(`Unknown planned module path '${moduleId}'.`)
521
+ const adjustedTarget = extension ? targetPath.replace(/\.[^./]+$/u, extension) : targetPath
522
+ const from = this.filename.split("/").slice(0, -1)
523
+ const to = adjustedTarget.split("/")
524
+ let common = 0
525
+
526
+ while (common < from.length && common < to.length && from[common] == to[common]) common++
527
+ const relative = [...from.slice(common).map(() => ".."), ...to.slice(common)].join("/")
528
+
529
+ return relative.startsWith(".") ? relative : `./${relative}`
530
+ }
531
+
532
+ /**
533
+ * Returns the protected native entry for one used stdlib provider operation.
534
+ * @param {import("../semantic/types.js").EffectOperationDeclaration} operation - Canonical operation declaration.
535
+ * @returns {string | undefined} Linked protected entry, or undefined when the operation stays inlined.
536
+ */
537
+ stdlibProviderEntryFor(operation) {
538
+ const module = this.effectOperationModules.get(operation.id)
539
+
540
+ return module === undefined ? undefined : this.stdlibProviderEntries?.[`${module}\u0000${operation.name}`]
541
+ }
542
+
543
+ /**
544
+ * Returns a relative specifier for the planned stdlib provider artifact.
545
+ * @param {string} [extension] - Optional replacement extension.
546
+ * @param {string} [providerPath] - One selected provider artifact path.
547
+ * @returns {string} Relative POSIX specifier.
548
+ */
549
+ stdlibProviderSpecifier(extension, providerPath) {
550
+ const targetPath = providerPath ?? this.stdlibProviderPath ?? this.stdlibProviderPaths?.[0]
551
+
552
+ if (!targetPath) throw new RangeError("A stdlib provider specifier requires a planned provider path.")
553
+ const adjustedTarget = extension ? targetPath.replace(/\.[^./]+$/u, extension) : targetPath
554
+ const from = this.filename.split("/").slice(0, -1)
555
+ const to = adjustedTarget.split("/")
556
+ let common = 0
557
+
558
+ while (common < from.length && common < to.length && from[common] == to[common]) common++
559
+ const relative = [...from.slice(common).map(() => ".."), ...to.slice(common)].join("/")
560
+
561
+ return relative.startsWith(".") ? relative : `./${relative}`
562
+ }
563
+
564
+ /**
565
+ * Resolves a validated field identity for target emission.
566
+ * @param {string} fieldId - Semantic field identity.
567
+ * @returns {import("../semantic/types.js").RecordField} Record field.
568
+ */
569
+ fieldForId(fieldId) {
570
+ const field = this.fields.get(fieldId)
571
+
572
+ if (!field) throw new RangeError(`Unknown validated field identity '${fieldId}'.`)
573
+
574
+ return field
575
+ }
576
+
577
+ /**
578
+ * Resolves the record declaration that owns a validated field identity.
579
+ * @param {string} fieldId - Semantic field identity.
580
+ * @returns {import("../semantic/types.js").RecordDeclaration} Owning record.
581
+ */
582
+ recordForFieldId(fieldId) {
583
+ const record = this.fieldRecords.get(fieldId)
584
+
585
+ if (!record) throw new RangeError(`Unknown validated field identity '${fieldId}'.`)
586
+
587
+ return record
588
+ }
589
+
47
590
  /**
48
591
  * Reports whether an exact parser-owned role range is available.
49
592
  * @param {import("../semantic/types.js").SemanticNode} node - Semantic node occurrence.
package/src/diagnostic.js CHANGED
@@ -45,15 +45,17 @@ export class SemantifoldDiagnostic extends Error {
45
45
  * Throws a normalized parser diagnostic while preserving the parser error.
46
46
  * @param {import("./semantic/types.js").SemanticLanguage} language - Frontend language.
47
47
  * @param {unknown} error - Opaque parser error, narrowed immediately.
48
+ * @param {import("./semantic/types.js").SourceLocation | undefined} [location] - Normalized parser failure range.
48
49
  * @returns {never} Always throws.
49
50
  */
50
- export function parseFailure(language, error) {
51
+ export function parseFailure(language, error, location) {
51
52
  const cause = error instanceof Error ? error : new Error(String(error))
52
53
 
53
54
  throw new SemantifoldDiagnostic({
54
55
  cause,
55
56
  code: "PARSE_ERROR",
56
57
  language,
58
+ location,
57
59
  message: cause.message
58
60
  })
59
61
  }
@@ -104,7 +106,7 @@ export function semanticFailure(language, code, detail, location) {
104
106
 
105
107
  /**
106
108
  * Throws an unsupported backend-capability diagnostic.
107
- * @param {import("./semantic/types.js").SemanticLanguage} language - Backend language.
109
+ * @param {import("./semantic/types.js").BackendLanguage} language - Backend language or binary target.
108
110
  * @param {string} capability - Unsupported semantic capability.
109
111
  * @param {import("./semantic/types.js").SourceLocation | undefined} location - Semantic source location.
110
112
  * @returns {never} Always throws.
@@ -553,7 +553,8 @@ export class CReader {
553
553
  const bindings = new Map(inherited)
554
554
 
555
555
  for (const statement of block.statements) {
556
- if (statement.kind == "LocalDeclaration") bindings.set(statement.name, statement.type.name)
556
+ if (statement.kind == "LocalDeclaration") bindings.set(statement.name,
557
+ /** @type {import("../semantic/types.js").TypeReference} */ (statement.type).name)
557
558
  if (statement.kind == "PrintStatement") {
558
559
  const expected = this.printTypes.get(statement)
559
560
 
@@ -567,7 +568,8 @@ export class CReader {
567
568
  }
568
569
  }
569
570
 
570
- for (const declaration of module.functions) visit(declaration.body, new Map(declaration.parameters.map((parameter) => [parameter.name, parameter.type.name])))
571
+ for (const declaration of module.functions) visit(declaration.body, new Map(declaration.parameters.map((parameter) => [parameter.name,
572
+ /** @type {import("../semantic/types.js").TypeReference} */ (parameter.type).name])))
571
573
  visit(module.entryPoint.body, new Map())
572
574
  }
573
575
 
@@ -585,7 +585,8 @@ export class CppReader {
585
585
  const bindings = new Map(inherited)
586
586
 
587
587
  for (const statement of block.statements) {
588
- if (statement.kind == "LocalDeclaration") bindings.set(statement.name, statement.type.name)
588
+ if (statement.kind == "LocalDeclaration") bindings.set(statement.name,
589
+ /** @type {import("../semantic/types.js").TypeReference} */ (statement.type).name)
589
590
  if (statement.kind == "PrintStatement") {
590
591
  const expected = this.printTypes.get(statement)
591
592
 
@@ -599,7 +600,8 @@ export class CppReader {
599
600
  }
600
601
  }
601
602
 
602
- for (const declaration of module.functions) visit(declaration.body, new Map(declaration.parameters.map((parameter) => [parameter.name, parameter.type.name])))
603
+ for (const declaration of module.functions) visit(declaration.body, new Map(declaration.parameters.map((parameter) => [parameter.name,
604
+ /** @type {import("../semantic/types.js").TypeReference} */ (parameter.type).name])))
603
605
  visit(module.entryPoint.body, new Map())
604
606
  }
605
607
 
@@ -663,9 +663,11 @@ function validateCheckedArithmetic(module) {
663
663
  */
664
664
  const visitBlock = (block) => block.statements.forEach((statement) => {
665
665
  if (statement.kind == "LocalDeclaration") visitExpression(statement.initializer)
666
- else if (statement.kind == "AssignmentStatement" || statement.kind == "PrintStatement" || statement.kind == "ReturnStatement") {
666
+ else if (statement.kind == "AssignmentStatement" || statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement") {
667
667
  visitExpression(statement.expression)
668
- } else {
668
+ } else if (statement.kind == "ReturnStatement") {
669
+ if (statement.expression) visitExpression(statement.expression)
670
+ } else if (statement.kind == "IfStatement") {
669
671
  visitExpression(statement.condition)
670
672
  visitBlock(statement.consequent)
671
673
  if (statement.alternate) visitBlock(statement.alternate)