semantifold 0.3.0 → 0.4.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 (297) hide show
  1. package/README.md +58 -15
  2. package/build/index.d.ts +48 -2
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +57 -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/c-validation.d.ts.map +1 -1
  11. package/build/src/backends/c-validation.js +7 -3
  12. package/build/src/backends/cpp-validation.d.ts.map +1 -1
  13. package/build/src/backends/cpp-validation.js +7 -3
  14. package/build/src/backends/csharp.js +7 -1
  15. package/build/src/backends/dart-runtime.d.ts +2 -0
  16. package/build/src/backends/dart-runtime.d.ts.map +1 -0
  17. package/build/src/backends/dart-runtime.js +41 -0
  18. package/build/src/backends/dart.d.ts +20 -0
  19. package/build/src/backends/dart.d.ts.map +1 -0
  20. package/build/src/backends/dart.js +321 -0
  21. package/build/src/backends/effects.d.ts +60 -0
  22. package/build/src/backends/effects.d.ts.map +1 -0
  23. package/build/src/backends/effects.js +746 -0
  24. package/build/src/backends/go.js +18 -4
  25. package/build/src/backends/identifiers.d.ts +36 -4
  26. package/build/src/backends/identifiers.d.ts.map +1 -1
  27. package/build/src/backends/identifiers.js +154 -10
  28. package/build/src/backends/index.d.ts.map +1 -1
  29. package/build/src/backends/index.js +27 -4
  30. package/build/src/backends/ios.d.ts +68 -0
  31. package/build/src/backends/ios.d.ts.map +1 -0
  32. package/build/src/backends/ios.js +1503 -0
  33. package/build/src/backends/java.d.ts.map +1 -1
  34. package/build/src/backends/java.js +429 -36
  35. package/build/src/backends/javascript.d.ts +6 -0
  36. package/build/src/backends/javascript.d.ts.map +1 -1
  37. package/build/src/backends/javascript.js +380 -24
  38. package/build/src/backends/kotlin-runtime.d.ts +3 -0
  39. package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
  40. package/build/src/backends/kotlin-runtime.js +29 -0
  41. package/build/src/backends/kotlin.d.ts +23 -0
  42. package/build/src/backends/kotlin.d.ts.map +1 -0
  43. package/build/src/backends/kotlin.js +136 -0
  44. package/build/src/backends/native-validation.d.ts +2 -2
  45. package/build/src/backends/native-validation.d.ts.map +1 -1
  46. package/build/src/backends/native-validation.js +2 -2
  47. package/build/src/backends/ordered-expressions.d.ts.map +1 -1
  48. package/build/src/backends/ordered-expressions.js +39 -7
  49. package/build/src/backends/php-stdlib-support.d.ts +19 -0
  50. package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
  51. package/build/src/backends/php-stdlib-support.js +227 -0
  52. package/build/src/backends/php.d.ts.map +1 -1
  53. package/build/src/backends/php.js +448 -33
  54. package/build/src/backends/program.d.ts +81 -0
  55. package/build/src/backends/program.d.ts.map +1 -0
  56. package/build/src/backends/program.js +1308 -0
  57. package/build/src/backends/python.js +7 -1
  58. package/build/src/backends/ruby.d.ts.map +1 -1
  59. package/build/src/backends/ruby.js +310 -24
  60. package/build/src/backends/rust-runtime.d.ts +7 -0
  61. package/build/src/backends/rust-runtime.d.ts.map +1 -0
  62. package/build/src/backends/rust-runtime.js +32 -0
  63. package/build/src/backends/rust-validation.d.ts +9 -0
  64. package/build/src/backends/rust-validation.d.ts.map +1 -0
  65. package/build/src/backends/rust-validation.js +78 -0
  66. package/build/src/backends/rust.d.ts +24 -0
  67. package/build/src/backends/rust.d.ts.map +1 -0
  68. package/build/src/backends/rust.js +344 -0
  69. package/build/src/backends/scalars.d.ts +14 -6
  70. package/build/src/backends/scalars.d.ts.map +1 -1
  71. package/build/src/backends/scalars.js +167 -17
  72. package/build/src/backends/shared.d.ts +23 -4
  73. package/build/src/backends/shared.d.ts.map +1 -1
  74. package/build/src/backends/shared.js +2158 -62
  75. package/build/src/backends/stdlib-support.d.ts +14 -0
  76. package/build/src/backends/stdlib-support.d.ts.map +1 -0
  77. package/build/src/backends/stdlib-support.js +237 -0
  78. package/build/src/backends/swift-runtime.d.ts +3 -0
  79. package/build/src/backends/swift-runtime.d.ts.map +1 -0
  80. package/build/src/backends/swift-runtime.js +14 -0
  81. package/build/src/backends/swift.d.ts +8 -0
  82. package/build/src/backends/swift.d.ts.map +1 -0
  83. package/build/src/backends/swift.js +127 -0
  84. package/build/src/backends/typescript.d.ts.map +1 -1
  85. package/build/src/backends/typescript.js +344 -24
  86. package/build/src/backends/wasm.d.ts +43 -0
  87. package/build/src/backends/wasm.d.ts.map +1 -0
  88. package/build/src/backends/wasm.js +2164 -0
  89. package/build/src/backends/writer.d.ts +235 -4
  90. package/build/src/backends/writer.d.ts.map +1 -1
  91. package/build/src/backends/writer.js +468 -3
  92. package/build/src/diagnostic.d.ts +4 -3
  93. package/build/src/diagnostic.d.ts.map +1 -1
  94. package/build/src/diagnostic.js +5 -3
  95. package/build/src/frontends/c.d.ts.map +1 -1
  96. package/build/src/frontends/c.js +5 -3
  97. package/build/src/frontends/cpp.d.ts.map +1 -1
  98. package/build/src/frontends/cpp.js +5 -3
  99. package/build/src/frontends/csharp.d.ts.map +1 -1
  100. package/build/src/frontends/csharp.js +7 -3
  101. package/build/src/frontends/dart.d.ts +10 -0
  102. package/build/src/frontends/dart.d.ts.map +1 -0
  103. package/build/src/frontends/dart.js +913 -0
  104. package/build/src/frontends/index.d.ts +3 -1
  105. package/build/src/frontends/index.d.ts.map +1 -1
  106. package/build/src/frontends/index.js +15 -5
  107. package/build/src/frontends/java.d.ts +110 -1
  108. package/build/src/frontends/java.d.ts.map +1 -1
  109. package/build/src/frontends/java.js +1725 -70
  110. package/build/src/frontends/javascript-typescript.d.ts +69 -1
  111. package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
  112. package/build/src/frontends/javascript-typescript.js +1825 -93
  113. package/build/src/frontends/kotlin.d.ts +10 -0
  114. package/build/src/frontends/kotlin.d.ts.map +1 -0
  115. package/build/src/frontends/kotlin.js +685 -0
  116. package/build/src/frontends/php.d.ts +118 -1
  117. package/build/src/frontends/php.d.ts.map +1 -1
  118. package/build/src/frontends/php.js +1583 -76
  119. package/build/src/frontends/program.d.ts +74 -0
  120. package/build/src/frontends/program.d.ts.map +1 -0
  121. package/build/src/frontends/program.js +989 -0
  122. package/build/src/frontends/ruby.d.ts +68 -1
  123. package/build/src/frontends/ruby.d.ts.map +1 -1
  124. package/build/src/frontends/ruby.js +1446 -101
  125. package/build/src/frontends/rust-parser.d.ts +11 -0
  126. package/build/src/frontends/rust-parser.d.ts.map +1 -0
  127. package/build/src/frontends/rust-parser.js +15 -0
  128. package/build/src/frontends/rust.d.ts +14 -0
  129. package/build/src/frontends/rust.d.ts.map +1 -0
  130. package/build/src/frontends/rust.js +715 -0
  131. package/build/src/frontends/scalars.d.ts +10 -0
  132. package/build/src/frontends/scalars.d.ts.map +1 -1
  133. package/build/src/frontends/scalars.js +28 -2
  134. package/build/src/frontends/swift.d.ts +10 -0
  135. package/build/src/frontends/swift.d.ts.map +1 -0
  136. package/build/src/frontends/swift.js +860 -0
  137. package/build/src/frontends/types.d.ts +186 -0
  138. package/build/src/frontends/types.d.ts.map +1 -0
  139. package/build/src/frontends/types.js +634 -0
  140. package/build/src/language-registry.d.ts +46 -4
  141. package/build/src/language-registry.d.ts.map +1 -1
  142. package/build/src/language-registry.js +167 -13
  143. package/build/src/mapping.d.ts +2 -2
  144. package/build/src/mapping.d.ts.map +1 -1
  145. package/build/src/mapping.js +31 -10
  146. package/build/src/semantic/capabilities.d.ts +66 -0
  147. package/build/src/semantic/capabilities.d.ts.map +1 -0
  148. package/build/src/semantic/capabilities.js +649 -0
  149. package/build/src/semantic/effects.d.ts +26 -0
  150. package/build/src/semantic/effects.d.ts.map +1 -0
  151. package/build/src/semantic/effects.js +764 -0
  152. package/build/src/semantic/generics.d.ts +23 -0
  153. package/build/src/semantic/generics.d.ts.map +1 -0
  154. package/build/src/semantic/generics.js +61 -0
  155. package/build/src/semantic/lifetime.d.ts +37 -0
  156. package/build/src/semantic/lifetime.d.ts.map +1 -0
  157. package/build/src/semantic/lifetime.js +527 -0
  158. package/build/src/semantic/provenance.d.ts +9 -2
  159. package/build/src/semantic/provenance.d.ts.map +1 -1
  160. package/build/src/semantic/provenance.js +462 -20
  161. package/build/src/semantic/scalars.d.ts +11 -0
  162. package/build/src/semantic/scalars.d.ts.map +1 -1
  163. package/build/src/semantic/scalars.js +16 -1
  164. package/build/src/semantic/stdlib.d.ts +254 -0
  165. package/build/src/semantic/stdlib.d.ts.map +1 -0
  166. package/build/src/semantic/stdlib.js +880 -0
  167. package/build/src/semantic/types.d.ts +2952 -202
  168. package/build/src/semantic/types.d.ts.map +1 -1
  169. package/build/src/semantic/types.js +688 -15
  170. package/build/src/semantic/validate.d.ts +85 -5
  171. package/build/src/semantic/validate.d.ts.map +1 -1
  172. package/build/src/semantic/validate.js +2576 -98
  173. package/build/src/stdlib-facades.d.ts +304 -0
  174. package/build/src/stdlib-facades.d.ts.map +1 -0
  175. package/build/src/stdlib-facades.js +1167 -0
  176. package/build/src/stdlib-negotiation.d.ts +69 -0
  177. package/build/src/stdlib-negotiation.d.ts.map +1 -0
  178. package/build/src/stdlib-negotiation.js +403 -0
  179. package/build/src/stdlib-providers.d.ts +72 -0
  180. package/build/src/stdlib-providers.d.ts.map +1 -0
  181. package/build/src/stdlib-providers.js +339 -0
  182. package/build/src/toolchains.d.ts +55 -1
  183. package/build/src/toolchains.d.ts.map +1 -1
  184. package/build/src/toolchains.js +15 -4
  185. package/docs/architecture.md +45 -13
  186. package/docs/dart.md +60 -0
  187. package/docs/goals.md +3 -3
  188. package/docs/ios.md +121 -0
  189. package/docs/kotlin.md +42 -0
  190. package/docs/language-support.md +231 -26
  191. package/docs/multi-file-modules.md +52 -0
  192. package/docs/parser-qualification.md +121 -8
  193. package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
  194. package/docs/rust.md +88 -0
  195. package/docs/source-maps.md +15 -7
  196. package/docs/standard-library-portability.md +39 -8
  197. package/docs/swift.md +44 -0
  198. package/docs/testing.md +366 -4
  199. package/docs/webassembly.md +52 -0
  200. package/index.js +63 -8
  201. package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
  202. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
  203. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
  204. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
  205. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
  206. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
  207. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
  208. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
  209. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
  210. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
  211. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
  212. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
  213. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
  214. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
  215. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
  216. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
  217. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
  218. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
  219. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
  220. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
  221. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
  222. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
  223. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
  224. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
  225. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
  226. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
  227. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
  228. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
  229. package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
  230. package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
  231. package/package.json +5 -2
  232. package/src/artifact-path.js +47 -2
  233. package/src/artifacts.js +67 -0
  234. package/src/backends/c-validation.js +6 -1
  235. package/src/backends/cpp-validation.js +6 -1
  236. package/src/backends/csharp.js +3 -0
  237. package/src/backends/dart-runtime.js +41 -0
  238. package/src/backends/dart.js +326 -0
  239. package/src/backends/effects.js +705 -0
  240. package/src/backends/go.js +14 -2
  241. package/src/backends/identifiers.js +160 -9
  242. package/src/backends/index.js +27 -2
  243. package/src/backends/ios.js +1612 -0
  244. package/src/backends/java.js +454 -36
  245. package/src/backends/javascript.js +389 -23
  246. package/src/backends/kotlin-runtime.js +29 -0
  247. package/src/backends/kotlin.js +141 -0
  248. package/src/backends/native-validation.js +1 -1
  249. package/src/backends/ordered-expressions.js +40 -6
  250. package/src/backends/php-stdlib-support.js +239 -0
  251. package/src/backends/php.js +469 -32
  252. package/src/backends/program.js +1407 -0
  253. package/src/backends/python.js +3 -0
  254. package/src/backends/ruby.js +326 -23
  255. package/src/backends/rust-runtime.js +34 -0
  256. package/src/backends/rust-validation.js +75 -0
  257. package/src/backends/rust.js +335 -0
  258. package/src/backends/scalars.js +141 -16
  259. package/src/backends/shared.js +2304 -124
  260. package/src/backends/stdlib-support.js +234 -0
  261. package/src/backends/swift-runtime.js +14 -0
  262. package/src/backends/swift.js +132 -0
  263. package/src/backends/typescript.js +349 -23
  264. package/src/backends/wasm.js +2208 -0
  265. package/src/backends/writer.js +520 -2
  266. package/src/diagnostic.js +4 -2
  267. package/src/frontends/c.js +4 -2
  268. package/src/frontends/cpp.js +4 -2
  269. package/src/frontends/csharp.js +4 -2
  270. package/src/frontends/dart.js +963 -0
  271. package/src/frontends/index.js +14 -4
  272. package/src/frontends/java.js +1977 -69
  273. package/src/frontends/javascript-typescript.js +2046 -102
  274. package/src/frontends/kotlin.js +713 -0
  275. package/src/frontends/php.js +1725 -79
  276. package/src/frontends/program.js +1062 -0
  277. package/src/frontends/ruby.js +1624 -98
  278. package/src/frontends/rust-parser.js +18 -0
  279. package/src/frontends/rust.js +714 -0
  280. package/src/frontends/scalars.js +31 -1
  281. package/src/frontends/swift.js +893 -0
  282. package/src/frontends/types.js +750 -0
  283. package/src/language-registry.js +172 -12
  284. package/src/mapping.js +33 -9
  285. package/src/semantic/capabilities.js +671 -0
  286. package/src/semantic/effects.js +737 -0
  287. package/src/semantic/generics.js +58 -0
  288. package/src/semantic/lifetime.js +517 -0
  289. package/src/semantic/provenance.js +412 -19
  290. package/src/semantic/scalars.js +17 -0
  291. package/src/semantic/stdlib.js +921 -0
  292. package/src/semantic/types.js +765 -14
  293. package/src/semantic/validate.js +2934 -209
  294. package/src/stdlib-facades.js +1211 -0
  295. package/src/stdlib-negotiation.js +446 -0
  296. package/src/stdlib-providers.js +377 -0
  297. package/src/toolchains.js +16 -3
@@ -2,22 +2,131 @@
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.
14
83
  */
15
- constructor({filename, language, module, sources}) {
84
+ constructor({filename, language, module, program, programPaths, sources, stdlibProviderEntries, stdlibProviderPath,
85
+ stdlibProviderPaths, stdlibProviderImports, stdlibProviderOwnerModule, stdlibProviderShims}) {
16
86
  const index = createGenerationIndex(module, sources)
17
87
 
18
88
  this.filename = filename
19
89
  this.language = language
90
+ this.module = module
91
+ this.program = program
92
+ this.programPaths = programPaths
20
93
  this.index = index
94
+ this.stdlibProviderEntries = stdlibProviderEntries
95
+ this.stdlibProviderPath = stdlibProviderPath
96
+ this.stdlibProviderPaths = stdlibProviderPaths ?? (stdlibProviderPath ? [stdlibProviderPath] : undefined)
97
+ this.stdlibProviderImports = stdlibProviderImports
98
+ this.stdlibProviderOwnerModule = stdlibProviderOwnerModule
99
+ this.stdlibProviderShims = stdlibProviderShims
100
+ const programRecords = program?.modules.flatMap((programModule) => programModule.records ?? []) ?? module.records ?? []
101
+ const programClasses = program?.modules.flatMap((programModule) => programModule.classes ?? []) ?? module.classes ?? []
102
+ const capabilityFailures = module.capabilities?.flatMap(({failures}) => failures) ?? []
103
+ const programErrors = program?.modules.flatMap((programModule) => [
104
+ ...(programModule.errors ?? []),
105
+ ...(programModule.capabilities?.flatMap(({failures}) => failures) ?? [])
106
+ ]) ?? [...module.errors ?? [], ...capabilityFailures]
107
+ const programFunctions = program?.modules.flatMap((programModule) => programModule.functions) ?? module.functions
108
+
109
+ this.records = new Map(programRecords.map((record) => [record.id, record]))
110
+ this.classes = new Map(programClasses.map((declaration) => [declaration.id, declaration]))
111
+ this.errors = new Map(programErrors.map((error) => [error.id, error]))
112
+ this.resources = new Map((module.capabilities?.flatMap(({resources}) => resources) ?? []).map((resource) => [resource.id, resource]))
113
+ this.effectOperations = new Map((module.capabilities?.flatMap(({operations}) => operations) ?? []).map((operation) => [operation.id, operation]))
114
+ this.effectOperationModules = new Map((module.capabilities?.flatMap((capability) =>
115
+ capability.operations.map((operation) => [operation.id, capability.authorityId])) ?? []))
116
+ this.fields = new Map(programRecords.flatMap((record) => record.fields.map((field) => [field.id, field])))
117
+ this.fieldRecords = new Map(programRecords.flatMap((record) => record.fields.map((field) => [field.id, record])))
118
+ this.privateFields = new Map(programClasses.flatMap((declaration) => declaration.fields.map((field) => [field.id, field])))
119
+ this.methods = new Map(programClasses.flatMap((declaration) => declaration.methods.map((method) => [method.id, method])))
120
+ this.typeParameters = new Map([...programRecords, ...programFunctions].flatMap((declaration) =>
121
+ (declaration.typeParameters ?? []).map((parameter) => [parameter.id, parameter])))
122
+ this.referenceClassEmissionDepth = 0
123
+ /** @type {Map<string, import("../semantic/types.js").SemanticProgramModule>} */
124
+ this.declarationModules = new Map(program?.modules.flatMap((programModule) => [
125
+ ...(programModule.records ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
126
+ ...(programModule.classes ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
127
+ ...(programModule.errors ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
128
+ ...programModule.functions.map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule]))
129
+ ]) ?? [])
21
130
  /** @type {string[]} */
22
131
  this.parts = []
23
132
  /** @type {import("../semantic/types.js").SemantifoldMappingSpan[]} */
@@ -25,6 +134,65 @@ export class SourceWriter {
25
134
  this.offset = 0
26
135
  this.line = 1
27
136
  this.column = 1
137
+ /** @type {Map<import("../semantic/types.js").Expression, string>} */
138
+ this.effectTemporaryNames = new Map()
139
+ /** @type {Map<import("../semantic/types.js").Expression, string>} */
140
+ this.effectReplacementNames = new Map()
141
+ /** @type {import("../semantic/types.js").Expression | undefined} */
142
+ this.effectDefinition = undefined
143
+ this.usedBindingNames = collectBindingNames(module)
144
+ }
145
+
146
+ /**
147
+ * Installs the effect expressions lowered immediately before the current statement.
148
+ * @param {import("../semantic/types.js").Expression[]} expressions - Ordered expressions.
149
+ * @returns {void}
150
+ */
151
+ planEffectReplacements(expressions) {
152
+ this.effectReplacementNames = new Map(expressions.map((expression) => [expression, this.effectTemporaryName(expression)]))
153
+ }
154
+
155
+ /**
156
+ * Allocates a collision-safe name for one deterministic effect site.
157
+ * @param {import("../semantic/types.js").Expression} expression - Effectful expression.
158
+ * @returns {string} Stable temporary name.
159
+ */
160
+ effectTemporaryName(expression) {
161
+ const known = this.effectTemporaryNames.get(expression)
162
+ if (known) return known
163
+ const site = typeof Reflect.get(expression, "effectSiteId") == "string"
164
+ ? Reflect.get(expression, "effectSiteId").slice("effect:".length) : String(this.effectTemporaryNames.size)
165
+ let name = `__semantifold_effect_${site}`
166
+
167
+ while (this.usedBindingNames.has(name)) name = `${name}_`
168
+ this.usedBindingNames.add(name)
169
+ this.effectTemporaryNames.set(expression, name)
170
+ return name
171
+ }
172
+
173
+ /**
174
+ * Returns the planned temporary replacement outside its own definition.
175
+ * @param {import("../semantic/types.js").Expression} expression - Candidate expression.
176
+ * @returns {string | undefined} Temporary name.
177
+ */
178
+ effectReplacementName(expression) {
179
+ return this.effectDefinition === expression ? undefined : this.effectReplacementNames.get(expression)
180
+ }
181
+
182
+ /**
183
+ * Emits one effect definition without recursively replacing itself.
184
+ * @param {import("../semantic/types.js").Expression} expression - Defined expression.
185
+ * @param {() => void} emit - Target expression emitter.
186
+ * @returns {void}
187
+ */
188
+ emitEffectDefinition(expression, emit) {
189
+ const previous = this.effectDefinition
190
+ this.effectDefinition = expression
191
+ try {
192
+ emit()
193
+ } finally {
194
+ this.effectDefinition = previous
195
+ }
28
196
  }
29
197
 
30
198
  /**
@@ -44,6 +212,356 @@ export class SourceWriter {
44
212
  return this.index.recordFor(node).path
45
213
  }
46
214
 
215
+ /**
216
+ * Resolves a validated nominal declaration identity for target emission.
217
+ * @param {string} declarationId - Semantic record identity.
218
+ * @returns {import("../semantic/types.js").RecordDeclaration} Record declaration.
219
+ */
220
+ recordForId(declarationId) {
221
+ const record = this.records.get(declarationId)
222
+
223
+ if (!record) throw new RangeError(`Unknown validated record identity '${declarationId}'.`)
224
+
225
+ return record
226
+ }
227
+
228
+ /**
229
+ * Returns the target spelling for a nominal record identity.
230
+ * @param {string} declarationId - Stable record declaration identity.
231
+ * @param {boolean} [valuePosition] - Whether the binding must exist at runtime.
232
+ * @returns {string} Target record spelling.
233
+ */
234
+ recordNameForId(declarationId, valuePosition = false) {
235
+ const record = this.recordForId(declarationId)
236
+ const owner = this.declarationModules.get(declarationId)
237
+ const imported = this.#programModule()?.imports.find((item) =>
238
+ item.declarationId == declarationId && (!valuePosition || !item.typeOnly))
239
+
240
+ if (this.program && owner && owner.id != Reflect.get(this.module, "id") && this.language == "ruby") {
241
+ return `${moduleClassName(owner.id)}::${record.name}`
242
+ }
243
+ if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
244
+ return this.importNameFor(imported)
245
+ }
246
+
247
+ return record.name
248
+ }
249
+
250
+ /**
251
+ * Resolves one validated reference class.
252
+ * @param {string} declarationId - Stable class identity.
253
+ * @returns {import("../semantic/types.js").ClassDeclaration} Class declaration.
254
+ */
255
+ classForId(declarationId) {
256
+ const declaration = this.classes.get(declarationId)
257
+
258
+ if (!declaration) throw new RangeError(`Unknown validated reference class identity '${declarationId}'.`)
259
+
260
+ return declaration
261
+ }
262
+
263
+ /**
264
+ * Returns the target spelling of one reference class.
265
+ * @param {string} declarationId - Stable class identity.
266
+ * @returns {string} Target spelling.
267
+ */
268
+ classNameForId(declarationId) {
269
+ const declaration = this.classForId(declarationId)
270
+ const imported = this.#programModule()?.imports.find((item) => item.declarationId == declarationId)
271
+
272
+ if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
273
+ return this.importNameFor(imported)
274
+ }
275
+ return declaration.name
276
+ }
277
+
278
+ /**
279
+ * Resolves one validated owned-resource declaration.
280
+ * @param {string} resourceId - Stable resource identity.
281
+ * @returns {import("../semantic/types.js").EffectResourceDeclaration} Resource declaration.
282
+ */
283
+ resourceForId(resourceId) {
284
+ const resource = this.resources.get(resourceId)
285
+ if (!resource) throw new RangeError(`Unknown validated resource identity '${resourceId}'.`)
286
+ return resource
287
+ }
288
+
289
+ /**
290
+ * Resolves one validated capability operation declaration.
291
+ * @param {string} operationId - Stable operation identity.
292
+ * @returns {import("../semantic/types.js").EffectOperationDeclaration} Operation declaration.
293
+ */
294
+ effectOperationForId(operationId) {
295
+ const operation = this.effectOperations.get(operationId)
296
+ if (!operation) throw new RangeError(`Unknown validated effect operation identity '${operationId}'.`)
297
+ return operation
298
+ }
299
+
300
+ /**
301
+ * Resolves one validated private field.
302
+ * @param {string} fieldId - Stable private-field identity.
303
+ * @returns {import("../semantic/types.js").PrivateField} Field declaration.
304
+ */
305
+ privateFieldForId(fieldId) {
306
+ const field = this.privateFields.get(fieldId)
307
+
308
+ if (!field) throw new RangeError(`Unknown validated private field identity '${fieldId}'.`)
309
+
310
+ return field
311
+ }
312
+
313
+ /**
314
+ * Resolves one validated receiver method.
315
+ * @param {string} methodId - Stable method identity.
316
+ * @returns {import("../semantic/types.js").MethodDeclaration} Method declaration.
317
+ */
318
+ methodForId(methodId) {
319
+ const method = this.methods.get(methodId)
320
+
321
+ if (!method) throw new RangeError(`Unknown validated method identity '${methodId}'.`)
322
+
323
+ return method
324
+ }
325
+
326
+ /**
327
+ * Resolves one validated declaration-scoped type parameter.
328
+ * @param {string} parameterId - Stable type-parameter identity.
329
+ * @returns {import("../semantic/types.js").TypeParameter} Type parameter.
330
+ */
331
+ typeParameterForId(parameterId) {
332
+ const parameter = this.typeParameters.get(parameterId)
333
+
334
+ if (!parameter) throw new RangeError(`Unknown validated type parameter identity '${parameterId}'.`)
335
+
336
+ return parameter
337
+ }
338
+
339
+ /**
340
+ * Returns the validated nominal error declaration for an identity.
341
+ * @param {string} declarationId - Stable error identity.
342
+ * @returns {import("../semantic/types.js").ErrorDeclaration | import("../semantic/types.js").EffectFailureDeclaration} Error declaration.
343
+ */
344
+ errorForId(declarationId) {
345
+ const error = this.errors.get(declarationId)
346
+
347
+ if (!error) throw new RangeError(`Unknown validated error identity '${declarationId}'.`)
348
+
349
+ return error
350
+ }
351
+
352
+ /**
353
+ * Returns the target-visible spelling for one nominal error identity.
354
+ * @param {string} declarationId - Stable error identity.
355
+ * @returns {string} Target-visible name.
356
+ */
357
+ errorNameForId(declarationId) {
358
+ const error = this.errorForId(declarationId)
359
+ const owner = this.declarationModules.get(declarationId)
360
+ const imported = this.#programModule()?.imports.find((item) => item.declarationId == declarationId)
361
+
362
+ if (this.program && owner && owner.id != Reflect.get(this.module, "id") && this.language == "ruby") {
363
+ return `${moduleClassName(owner.id)}::${error.name}`
364
+ }
365
+ if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
366
+ return this.importNameFor(imported)
367
+ }
368
+
369
+ return owner ? error.name : this.capabilityNominalName(error.name)
370
+ }
371
+
372
+ /**
373
+ * Returns the target spelling for a nominal name owned by a compiler-authorized capability.
374
+ * PHP program entries live in a generated namespace while stdlib provider classes remain
375
+ * global, so PHP program mode fully qualifies capability names.
376
+ * @param {string} name - Declared nominal name.
377
+ * @returns {string} Target spelling.
378
+ */
379
+ capabilityNominalName(name) {
380
+ return this.program && this.language == "php" ? `\\${name}` : name
381
+ }
382
+
383
+ /**
384
+ * Returns the target spelling for a resolved function call.
385
+ * @param {import("../semantic/types.js").CallExpression} expression - Resolved call.
386
+ * @returns {string} Target call name.
387
+ */
388
+ callNameFor(expression) {
389
+ const declarationId = expression.resolution?.declarationId
390
+ const owner = declarationId ? this.declarationModules.get(declarationId) : undefined
391
+ const imported = declarationId ? this.#programModule()?.imports.find((item) => item.declarationId == declarationId) : undefined
392
+
393
+ if (this.language == "java" && !this.program && this.referenceClassEmissionDepth > 0) return `Main.${expression.callee}`
394
+ if (!declarationId || !this.program || !owner || owner.id == Reflect.get(this.module, "id")) return expression.callee
395
+ if (this.language == "ruby" || this.language == "java") return `${moduleClassName(owner.id)}.${declarationName(owner, declarationId)}`
396
+ if (imported) return this.importNameFor(imported)
397
+
398
+ return declarationName(owner, declarationId)
399
+ }
400
+
401
+ /** Marks emission as occurring inside one top-level reference class. */
402
+ beginReferenceClassEmission() {
403
+ this.referenceClassEmissionDepth += 1
404
+ }
405
+
406
+ /** Ends one balanced top-level reference-class emission scope. */
407
+ endReferenceClassEmission() {
408
+ if (this.referenceClassEmissionDepth == 0) throw new RangeError("Reference-class emission scope is not active.")
409
+ this.referenceClassEmissionDepth -= 1
410
+ }
411
+
412
+ /**
413
+ * Returns the target-local binding for one resolved import.
414
+ * @param {import("../semantic/types.js").SemanticImport} imported - Resolved import.
415
+ * @returns {string} Emitted import name.
416
+ */
417
+ importNameFor(imported) {
418
+ const module = this.#programModule()
419
+
420
+ if (!this.program || !module) throw new RangeError("Import names require a validated semantic program.")
421
+
422
+ return programImportName(this.program, module, imported)
423
+ }
424
+
425
+ /**
426
+ * Reports whether one local declaration is exported by the current program module.
427
+ * @param {string | undefined} declarationId - Declaration identity.
428
+ * @returns {boolean} Whether it has a same-name program export.
429
+ */
430
+ isDirectlyExported(declarationId) {
431
+ const module = /** @type {Partial<import("../semantic/types.js").SemanticProgramModule>} */ (this.module)
432
+
433
+ return typeof declarationId == "string" && Boolean(module.exports?.some((item) =>
434
+ item.declarationId == declarationId && item.exportedName == declarationName(module, declarationId)))
435
+ }
436
+
437
+ /**
438
+ * Reports whether one export edge uses its declaration's emitted name.
439
+ * @param {import("../semantic/types.js").SemanticExport} exported - Current export edge.
440
+ * @returns {boolean} Whether this edge is represented by the declaration prefix.
441
+ */
442
+ isDirectExport(exported) {
443
+ return exported.exportedName == declarationName(this.module, exported.declarationId)
444
+ }
445
+
446
+ /**
447
+ * Reports whether one local declaration has any public program export.
448
+ * @param {string | undefined} declarationId - Declaration identity.
449
+ * @returns {boolean} Whether the declaration is exported.
450
+ */
451
+ isExported(declarationId) {
452
+ const module = /** @type {Partial<import("../semantic/types.js").SemanticProgramModule>} */ (this.module)
453
+
454
+ return typeof declarationId == "string" && Boolean(module.exports?.some((item) => item.declarationId == declarationId))
455
+ }
456
+
457
+ /**
458
+ * Returns whether this is the selected program entry module.
459
+ * @returns {boolean} Whether this writer owns the selected entry.
460
+ */
461
+ isProgramEntry() {
462
+ return this.program?.entryModule == Reflect.get(this.module, "id")
463
+ }
464
+
465
+ /**
466
+ * Returns the canonical class/module segment for a logical module identity.
467
+ * @param {string} moduleId - Logical module identity.
468
+ * @returns {string} Target class/module name.
469
+ */
470
+ programModuleName(moduleId) {
471
+ if (!this.program?.modules.some(({id}) => id == moduleId)) throw new RangeError(`Unknown program module '${moduleId}'.`)
472
+
473
+ return moduleClassName(moduleId)
474
+ }
475
+
476
+ /**
477
+ * Finds the current module in the complete program.
478
+ * @returns {import("../semantic/types.js").SemanticProgramModule | undefined} Current program module.
479
+ */
480
+ #programModule() {
481
+ if (!this.program) return undefined
482
+
483
+ return this.program.modules.find(({id}) => id == Reflect.get(this.module, "id"))
484
+ }
485
+
486
+ /**
487
+ * Returns a relative ESM/require specifier for a planned dependency artifact.
488
+ * @param {string} moduleId - Dependency module identity.
489
+ * @param {string} [extension] - Optional replacement extension.
490
+ * @returns {string} Relative POSIX specifier.
491
+ */
492
+ relativeModuleSpecifier(moduleId, extension) {
493
+ const targetPath = this.programPaths?.get(moduleId)
494
+
495
+ if (!targetPath) throw new RangeError(`Unknown planned module path '${moduleId}'.`)
496
+ const adjustedTarget = extension ? targetPath.replace(/\.[^./]+$/u, extension) : targetPath
497
+ const from = this.filename.split("/").slice(0, -1)
498
+ const to = adjustedTarget.split("/")
499
+ let common = 0
500
+
501
+ while (common < from.length && common < to.length && from[common] == to[common]) common++
502
+ const relative = [...from.slice(common).map(() => ".."), ...to.slice(common)].join("/")
503
+
504
+ return relative.startsWith(".") ? relative : `./${relative}`
505
+ }
506
+
507
+ /**
508
+ * Returns the protected native entry for one used stdlib provider operation.
509
+ * @param {import("../semantic/types.js").EffectOperationDeclaration} operation - Canonical operation declaration.
510
+ * @returns {string | undefined} Linked protected entry, or undefined when the operation stays inlined.
511
+ */
512
+ stdlibProviderEntryFor(operation) {
513
+ const module = this.effectOperationModules.get(operation.id)
514
+
515
+ return module === undefined ? undefined : this.stdlibProviderEntries?.[`${module}\u0000${operation.name}`]
516
+ }
517
+
518
+ /**
519
+ * Returns a relative specifier for the planned stdlib provider artifact.
520
+ * @param {string} [extension] - Optional replacement extension.
521
+ * @param {string} [providerPath] - One selected provider artifact path.
522
+ * @returns {string} Relative POSIX specifier.
523
+ */
524
+ stdlibProviderSpecifier(extension, providerPath) {
525
+ const targetPath = providerPath ?? this.stdlibProviderPath ?? this.stdlibProviderPaths?.[0]
526
+
527
+ if (!targetPath) throw new RangeError("A stdlib provider specifier requires a planned provider path.")
528
+ const adjustedTarget = extension ? targetPath.replace(/\.[^./]+$/u, extension) : targetPath
529
+ const from = this.filename.split("/").slice(0, -1)
530
+ const to = adjustedTarget.split("/")
531
+ let common = 0
532
+
533
+ while (common < from.length && common < to.length && from[common] == to[common]) common++
534
+ const relative = [...from.slice(common).map(() => ".."), ...to.slice(common)].join("/")
535
+
536
+ return relative.startsWith(".") ? relative : `./${relative}`
537
+ }
538
+
539
+ /**
540
+ * Resolves a validated field identity for target emission.
541
+ * @param {string} fieldId - Semantic field identity.
542
+ * @returns {import("../semantic/types.js").RecordField} Record field.
543
+ */
544
+ fieldForId(fieldId) {
545
+ const field = this.fields.get(fieldId)
546
+
547
+ if (!field) throw new RangeError(`Unknown validated field identity '${fieldId}'.`)
548
+
549
+ return field
550
+ }
551
+
552
+ /**
553
+ * Resolves the record declaration that owns a validated field identity.
554
+ * @param {string} fieldId - Semantic field identity.
555
+ * @returns {import("../semantic/types.js").RecordDeclaration} Owning record.
556
+ */
557
+ recordForFieldId(fieldId) {
558
+ const record = this.fieldRecords.get(fieldId)
559
+
560
+ if (!record) throw new RangeError(`Unknown validated field identity '${fieldId}'.`)
561
+
562
+ return record
563
+ }
564
+
47
565
  /**
48
566
  * Reports whether an exact parser-owned role range is available.
49
567
  * @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)