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
@@ -30,6 +30,16 @@ export function withParserRanges(node, ranges) {
30
30
  return node
31
31
  }
32
32
 
33
+ /**
34
+ * Returns one parser-owned token range while frontend validation is still in progress.
35
+ * @param {object} node - Semantic node or type reference.
36
+ * @param {string} role - Exact semantic token role.
37
+ * @returns {import("./types.js").SourceLocation | undefined} Parser range when present.
38
+ */
39
+ export function parserRangeFor(node, role) {
40
+ return parserRanges.get(node)?.[role]
41
+ }
42
+
33
43
  /**
34
44
  * Adds deterministic provenance to a validated frontend module.
35
45
  * @param {import("./types.js").SemanticModule} module - Validated semantic module.
@@ -50,8 +60,14 @@ export function annotateParsedModule(module, {filename, language, source}) {
50
60
  for (const [index, entry] of entries.entries()) {
51
61
  const ranges = parserRanges.get(entry.node) ?? {}
52
62
  const location = "location" in entry.node ? entry.node.location : ranges.type ?? entry.ownerLocation
63
+ const related = {location, sourceId: "source:0"}
64
+ const origin = entry.path.startsWith("/capabilities/")
65
+ ? {kind: /** @type {const} */ ("synthetic"), reason: "compiler-authorized capability", relatedOrigins: [related]}
66
+ : entry.node.kind == "OwnedMoveExpression" || entry.node.kind == "OwnedBorrowExpression"
67
+ ? {kind: /** @type {const} */ ("derived"), origins: [related]}
68
+ : {kind: /** @type {const} */ ("source"), location, sourceId: "source:0"}
53
69
  const sourceProvenance = /** @type {import("./types.js").SemanticNodeSourceProvenance} */ ({
54
- origin: {kind: "source", location, sourceId: "source:0"},
70
+ origin,
55
71
  ranges,
56
72
  schema: "SemantifoldNodeProvenance",
57
73
  version: 1
@@ -66,7 +82,7 @@ export function annotateParsedModule(module, {filename, language, source}) {
66
82
 
67
83
  records.push(record)
68
84
  recordsByPath.set(entry.path, record)
69
- entry.node.sourceProvenance = sourceProvenance
85
+ if (Object.isExtensible(entry.node)) Reflect.set(entry.node, "sourceProvenance", sourceProvenance)
70
86
  }
71
87
 
72
88
  const symbols = resolveSymbols(module, recordsByPath)
@@ -121,13 +137,16 @@ export function createGenerationIndex(module, providedSources = []) {
121
137
 
122
138
  for (const [index, entry] of entries.entries()) {
123
139
  const located = "location" in entry.node ? entry.node.location : entry.ownerLocation
124
- const associated = usableNodeProvenance(entry.node.sourceProvenance)
140
+ const associated = usableNodeProvenance(Reflect.get(entry.node, "sourceProvenance"))
125
141
  const ranges = associated ? validRanges(associated.ranges, verifiableSources) : {}
126
142
  const normalizedOrigin = associated
127
143
  ? normalizeOrigin(associated.origin, priorSourcesById, verifiableSources)
128
144
  : undefined
129
145
  const fallbackSource = sourceForLocation(located, sources)
130
- const origin = normalizedOrigin ?? sourceOrigin(fallbackSource, located)
146
+ const origin = entry.path.startsWith("/capabilities/")
147
+ ? {kind: /** @type {const} */ ("synthetic"), reason: "compiler-authorized capability",
148
+ relatedOrigins: [{location: located, sourceId: fallbackSource.id}]}
149
+ : normalizedOrigin ?? sourceOrigin(fallbackSource, located)
131
150
 
132
151
  const record = {
133
152
  id: `node:${index}`,
@@ -185,7 +204,7 @@ export function createGenerationIndex(module, providedSources = []) {
185
204
  */
186
205
  function addSource(filename, content, language) {
187
206
  if (typeof filename != "string" || content !== null && typeof content != "string" ||
188
- language !== null && !["php", "ruby", "javascript", "typescript", "java", "python", "csharp", "go", "c", "cpp"].includes(language)) {
207
+ language !== null && !["php", "ruby", "javascript", "typescript", "java", "kotlin", "python", "csharp", "go", "c", "cpp", "rust", "swift", "dart"].includes(language)) {
189
208
  throw new TypeError("Malformed semantic source registry entry.")
190
209
  }
191
210
 
@@ -242,7 +261,7 @@ function usableSourceProvenance(provenance) {
242
261
  if (!source || typeof source.id != "string" || sourceIds.has(source.id) || typeof source.filename != "string" ||
243
262
  source.filename.length == 0 ||
244
263
  source.content !== null && typeof source.content != "string" || source.language !== null &&
245
- !["php", "ruby", "javascript", "typescript", "java", "python", "csharp", "go", "c", "cpp"].includes(source.language)) return undefined
264
+ !["php", "ruby", "javascript", "typescript", "java", "kotlin", "python", "csharp", "go", "c", "cpp", "rust", "swift", "dart"].includes(source.language)) return undefined
246
265
  sourceIds.add(source.id)
247
266
  }
248
267
 
@@ -445,7 +464,7 @@ function requireProvenance(module) {
445
464
 
446
465
  /**
447
466
  * Traverses public semantic nodes in one stable order.
448
- * @param {import("./types.js").SemanticModule} module - Semantic module.
467
+ * @param {import("./types.js").SemanticModule | import("./types.js").SemanticProgramModule} module - Semantic module.
449
468
  * @returns {{node: import("./types.js").SemanticNode, ownerLocation: import("./types.js").SourceLocation, path: string}[]} Entries.
450
469
  */
451
470
  export function semanticEntries(module) {
@@ -469,9 +488,47 @@ export function semanticEntries(module) {
469
488
  entries.push({node, ownerLocation: location, path})
470
489
 
471
490
  if (node.kind == "Module") {
491
+ if ("imports" in node) {
492
+ node.imports.forEach((child, index) => visit(child, `/imports/${index}`, location))
493
+ }
494
+ ;(node.records ?? []).forEach((child, index) => visit(child, `/records/${index}`, location))
495
+ if (!("sourceFilename" in node) || Reflect.get(node, "stdlibFacade") !== undefined) {
496
+ ;(node.classes ?? []).forEach((child, index) => visit(child, `/classes/${index}`, location))
497
+ }
498
+ ;(node.errors ?? []).forEach((child, index) => visit(child, `/errors/${index}`, location))
499
+ ;(node.capabilities ?? []).forEach((child, index) => visit(child, `/capabilities/${index}`, location))
472
500
  node.functions.forEach((child, index) => visit(child, `/functions/${index}`, location))
473
- visit(node.entryPoint, "/entryPoint", location)
501
+ if ("exports" in node) {
502
+ node.exports.forEach((child, index) => visit(child, `/exports/${index}`, location))
503
+ }
504
+ if (node.entryPoint) visit(node.entryPoint, "/entryPoint", location)
505
+ } else if (node.kind == "RecordDeclaration") {
506
+ ;(node.typeParameters ?? []).forEach((child, index) => visit(child, `${path}/typeParameters/${index}`, location))
507
+ node.fields.forEach((child, index) => visit(child, `${path}/fields/${index}`, location))
508
+ } else if (node.kind == "EffectCapabilityDeclaration") {
509
+ node.resources.forEach((child, index) => visit(child, `${path}/resources/${index}`, location))
510
+ node.failures.forEach((child, index) => visit(child, `${path}/failures/${index}`, location))
511
+ node.operations.forEach((child, index) => visit(child, `${path}/operations/${index}`, location))
512
+ } else if (node.kind == "EffectOperationDeclaration") {
513
+ node.parameters.forEach((child, index) => visit(child.type, `${path}/parameters/${index}/type`, location))
514
+ visit(node.returnType, `${path}/returnType`, location)
515
+ } else if (node.kind == "ClassDeclaration") {
516
+ node.fields.forEach((child, index) => visit(child, `${path}/fields/${index}`, location))
517
+ visit(node.constructor, `${path}/constructor`, location)
518
+ node.methods.forEach((child, index) => visit(child, `${path}/methods/${index}`, location))
519
+ } else if (node.kind == "PrivateField") {
520
+ visit(node.type, `${path}/type`, location)
521
+ } else if (node.kind == "ConstructorDeclaration") {
522
+ node.parameters.forEach((child, index) => visit(child, `${path}/parameters/${index}`, location))
523
+ visit(node.body, `${path}/body`, location)
524
+ } else if (node.kind == "MethodDeclaration") {
525
+ node.parameters.forEach((child, index) => visit(child, `${path}/parameters/${index}`, location))
526
+ visit(node.returnType, `${path}/returnType`, location)
527
+ visit(node.body, `${path}/body`, location)
528
+ } else if (node.kind == "RecordField") {
529
+ visit(node.type, `${path}/type`, location)
474
530
  } else if (node.kind == "FunctionDeclaration") {
531
+ ;(node.typeParameters ?? []).forEach((child, index) => visit(child, `${path}/typeParameters/${index}`, location))
475
532
  node.parameters.forEach((child, index) => visit(child, `${path}/parameters/${index}`, location))
476
533
  visit(node.returnType, `${path}/returnType`, location)
477
534
  visit(node.body, `${path}/body`, location)
@@ -479,18 +536,55 @@ export function semanticEntries(module) {
479
536
  node.statements.forEach((child, index) => visit(child, `${path}/statements/${index}`, location))
480
537
  } else if (node.kind == "Parameter") {
481
538
  visit(node.type, `${path}/type`, location)
539
+ } else if (node.kind == "ValueBinding") {
540
+ visit(node.type, `${path}/type`, location)
541
+ } else if (node.kind == "CatchBinding") {
542
+ visit(node.type, `${path}/type`, location)
543
+ } else if (node.kind == "ListType") {
544
+ visit(node.elementType, `${path}/elementType`, location)
545
+ } else if (node.kind == "MapType" || node.kind == "OrderedMapType") {
546
+ visit(node.keyType, `${path}/keyType`, location)
547
+ visit(node.valueType, `${path}/valueType`, location)
548
+ } else if (node.kind == "OptionalType") {
549
+ visit(node.valueType, `${path}/valueType`, location)
550
+ } else if (node.kind == "RecordType") {
551
+ ;(node.arguments ?? []).forEach((child, index) => visit(child, `${path}/arguments/${index}`, location))
482
552
  } else if (node.kind == "LocalDeclaration") {
483
553
  visit(node.type, `${path}/type`, location)
484
554
  visit(node.initializer, `${path}/initializer`, location)
485
555
  } else if (node.kind == "AssignmentStatement") {
486
556
  visit(node.target, `${path}/target`, location)
487
557
  visit(node.expression, `${path}/expression`, location)
488
- } else if (node.kind == "ReturnStatement" || node.kind == "PrintStatement") {
558
+ } else if (node.kind == "PrivateFieldWriteStatement") {
559
+ visit(node.receiver, `${path}/receiver`, location)
560
+ visit(node.expression, `${path}/expression`, location)
561
+ } else if (node.kind == "ReturnStatement") {
562
+ if (node.expression) visit(node.expression, `${path}/expression`, location)
563
+ } else if (node.kind == "ExpressionStatement" || node.kind == "PrintStatement") {
489
564
  visit(node.expression, `${path}/expression`, location)
490
565
  } else if (node.kind == "IfStatement") {
491
566
  visit(node.condition, `${path}/condition`, location)
492
567
  visit(node.consequent, `${path}/consequent`, location)
493
568
  if (node.alternate) visit(node.alternate, `${path}/alternate`, location)
569
+ } else if (node.kind == "ForEachStatement") {
570
+ visit(node.list, `${path}/list`, location)
571
+ visit(node.valueBinding, `${path}/valueBinding`, location)
572
+ visit(node.body, `${path}/body`, location)
573
+ } else if (node.kind == "ForEachMapStatement") {
574
+ visit(node.map, `${path}/map`, location)
575
+ visit(node.keyBinding, `${path}/keyBinding`, location)
576
+ visit(node.valueBinding, `${path}/valueBinding`, location)
577
+ visit(node.body, `${path}/body`, location)
578
+ } else if (node.kind == "WhileStatement") {
579
+ visit(node.condition, `${path}/condition`, location)
580
+ visit(node.body, `${path}/body`, location)
581
+ } else if (node.kind == "RaiseStatement") {
582
+ visit(node.error, `${path}/error`, location)
583
+ } else if (node.kind == "TryStatement") {
584
+ visit(node.body, `${path}/body`, location)
585
+ visit(node.catchType, `${path}/catchType`, location)
586
+ visit(node.catchBinding, `${path}/catchBinding`, location)
587
+ visit(node.catchBody, `${path}/catchBody`, location)
494
588
  } else if (node.kind == "EntryPoint") {
495
589
  visit(node.body, `${path}/body`, location)
496
590
  } else if (node.kind == "UnaryExpression") {
@@ -498,8 +592,47 @@ export function semanticEntries(module) {
498
592
  } else if (node.kind == "BinaryExpression") {
499
593
  visit(node.left, `${path}/left`, location)
500
594
  visit(node.right, `${path}/right`, location)
501
- } else if (node.kind == "CallExpression") {
595
+ } else if (node.kind == "CallExpression" || node.kind == "EffectCallExpression") {
502
596
  node.arguments.forEach((child, index) => visit(child, `${path}/arguments/${index}`, location))
597
+ } else if (node.kind == "OwnedMoveExpression" || node.kind == "OwnedBorrowExpression") {
598
+ visit(node.expression, `${path}/expression`, location)
599
+ } else if (node.kind == "MethodCallExpression") {
600
+ visit(node.receiver, `${path}/receiver`, location)
601
+ node.arguments.forEach((child, index) => visit(child, `${path}/arguments/${index}`, location))
602
+ } else if (node.kind == "ReferenceConstruction") {
603
+ visit(node.reference, `${path}/reference`, location)
604
+ node.arguments.forEach((child, index) => visit(child, `${path}/arguments/${index}`, location))
605
+ } else if (node.kind == "RecordConstruction") {
606
+ visit(node.record, `${path}/record`, location)
607
+ node.arguments.forEach((child, index) => visit(child, `${path}/arguments/${index}`, location))
608
+ } else if (node.kind == "MemberRead") {
609
+ visit(node.receiver, `${path}/receiver`, location)
610
+ } else if (node.kind == "PrivateFieldRead") {
611
+ visit(node.receiver, `${path}/receiver`, location)
612
+ } else if (node.kind == "ErrorConstruction") {
613
+ visit(node.error, `${path}/error`, location)
614
+ visit(node.message, `${path}/message`, location)
615
+ } else if (node.kind == "ErrorMessageRead") {
616
+ visit(node.receiver, `${path}/receiver`, location)
617
+ } else if (node.kind == "ListLiteral") {
618
+ node.elements.forEach((child, index) => visit(child, `${path}/elements/${index}`, location))
619
+ } else if (node.kind == "MapLiteral" || node.kind == "OrderedMapLiteral") {
620
+ node.entries.forEach((child, index) => visit(child, `${path}/entries/${index}`, location))
621
+ } else if (node.kind == "MapEntry") {
622
+ visit(node.key, `${path}/key`, location)
623
+ visit(node.value, `${path}/value`, location)
624
+ } else if (node.kind == "ListIndexExpression") {
625
+ visit(node.collection, `${path}/collection`, location)
626
+ visit(node.index, `${path}/index`, location)
627
+ } else if (node.kind == "MapLookupExpression") {
628
+ visit(node.collection, `${path}/collection`, location)
629
+ visit(node.key, `${path}/key`, location)
630
+ } else if (node.kind == "CollectionSizeExpression") {
631
+ visit(node.collection, `${path}/collection`, location)
632
+ } else if (node.kind == "OptionalSome") {
633
+ visit(node.value, `${path}/value`, location)
634
+ } else if (node.kind == "OptionalIsPresent" || node.kind == "OptionalUnwrap") {
635
+ visit(node.operand, `${path}/operand`, location)
503
636
  }
504
637
  }
505
638
  }
@@ -515,9 +648,108 @@ function resolveSymbols(module, records) {
515
648
  const symbols = []
516
649
  /** @type {Map<string, string>} */
517
650
  const functions = new Map()
651
+ /** @type {Map<string, string>} */
652
+ const recordSymbols = new Map()
653
+ /** @type {Map<string, string>} */
654
+ const errorSymbols = new Map()
655
+ /** @type {Map<string, string>} */
656
+ const fieldSymbols = new Map()
657
+ /** @type {Map<string, string>} */
658
+ const classSymbols = new Map()
659
+ /** @type {Map<string, string>} */
660
+ const constructorSymbols = new Map()
661
+ /** @type {Map<string, string>} */
662
+ const methodSymbols = new Map()
663
+ /** @type {Map<string, string>} */
664
+ const typeParameterSymbols = new Map()
665
+ /** @type {Map<string, string>} */
666
+ const resourceSymbols = new Map()
667
+ /** @type {Map<string, string>} */
668
+ const operationSymbols = new Map()
669
+
670
+ for (const [capabilityIndex, capability] of (module.capabilities ?? []).entries()) {
671
+ const capabilityPath = `/capabilities/${capabilityIndex}`
672
+
673
+ declare(capability, capability.name, "capability", capabilityPath)
674
+ for (const [resourceIndex, resource] of capability.resources.entries()) {
675
+ resourceSymbols.set(resource.id, declare(resource, resource.name, "resource", `${capabilityPath}/resources/${resourceIndex}`))
676
+ }
677
+ for (const [failureIndex, failure] of capability.failures.entries()) {
678
+ errorSymbols.set(failure.id, declare(failure, failure.name, "failure", `${capabilityPath}/failures/${failureIndex}`))
679
+ }
680
+ for (const [operationIndex, operation] of capability.operations.entries()) {
681
+ operationSymbols.set(operation.id, declare(operation, operation.name, "operation", `${capabilityPath}/operations/${operationIndex}`))
682
+ }
683
+ }
684
+ for (const [capabilityIndex, capability] of (module.capabilities ?? []).entries()) {
685
+ for (const [operationIndex, operation] of capability.operations.entries()) {
686
+ const operationPath = `/capabilities/${capabilityIndex}/operations/${operationIndex}`
687
+ operation.parameters.forEach((parameter, parameterIndex) =>
688
+ visitType(parameter.type, `${operationPath}/parameters/${parameterIndex}/type`))
689
+ visitType(operation.returnType, `${operationPath}/returnType`)
690
+ }
691
+ }
692
+
693
+ for (const [index, declaration] of (module.records ?? []).entries()) {
694
+ const declarationPath = `/records/${index}`
695
+ const symbol = declare(declaration, declaration.name, "record", declarationPath)
696
+
697
+ if (declaration.id) recordSymbols.set(declaration.id, symbol)
698
+ for (const [parameterIndex, parameter] of (declaration.typeParameters ?? []).entries()) {
699
+ const parameterSymbol = declare(parameter, parameter.name, "typeParameter", `${declarationPath}/typeParameters/${parameterIndex}`)
700
+
701
+ if (parameter.id) typeParameterSymbols.set(parameter.id, parameterSymbol)
702
+ }
703
+ for (const [fieldIndex, field] of declaration.fields.entries()) {
704
+ const fieldPath = `${declarationPath}/fields/${fieldIndex}`
705
+ const fieldSymbol = declare(field, field.name, "field", fieldPath)
706
+
707
+ if (field.id) fieldSymbols.set(field.id, fieldSymbol)
708
+ }
709
+ }
710
+
711
+ for (const [index, declaration] of (module.errors ?? []).entries()) {
712
+ const symbol = declare(declaration, declaration.name, "error", `/errors/${index}`)
713
+
714
+ if (declaration.id) errorSymbols.set(declaration.id, symbol)
715
+ }
716
+
717
+ for (const [index, declaration] of (module.classes ?? []).entries()) {
718
+ const declarationPath = `/classes/${index}`
719
+ const classSymbol = declare(declaration, declaration.name, "class", declarationPath)
720
+
721
+ if (declaration.id) classSymbols.set(declaration.id, classSymbol)
722
+ for (const [fieldIndex, field] of declaration.fields.entries()) {
723
+ const symbol = declare(field, field.name, "field", `${declarationPath}/fields/${fieldIndex}`)
724
+
725
+ if (field.id) fieldSymbols.set(field.id, symbol)
726
+ visitType(field.type, `${declarationPath}/fields/${fieldIndex}/type`)
727
+ }
728
+ const constructorSymbol = declare(declaration.constructor, "constructor", "constructor", `${declarationPath}/constructor`)
729
+
730
+ if (declaration.constructor.id) constructorSymbols.set(declaration.constructor.id, constructorSymbol)
731
+ for (const [methodIndex, method] of declaration.methods.entries()) {
732
+ const symbol = declare(method, method.name, "method", `${declarationPath}/methods/${methodIndex}`)
733
+
734
+ if (method.id) methodSymbols.set(method.id, symbol)
735
+ }
736
+ }
737
+
738
+ for (const [index, declaration] of (module.records ?? []).entries()) {
739
+ for (const [fieldIndex, field] of declaration.fields.entries()) {
740
+ visitType(field.type, `/records/${index}/fields/${fieldIndex}/type`)
741
+ }
742
+ }
518
743
 
519
744
  for (const [index, declaration] of module.functions.entries()) {
520
- functions.set(declaration.name, declare(declaration, declaration.name, "function", `/functions/${index}`))
745
+ const declarationPath = `/functions/${index}`
746
+
747
+ functions.set(declaration.name, declare(declaration, declaration.name, "function", declarationPath))
748
+ for (const [parameterIndex, parameter] of (declaration.typeParameters ?? []).entries()) {
749
+ const parameterSymbol = declare(parameter, parameter.name, "typeParameter", `${declarationPath}/typeParameters/${parameterIndex}`)
750
+
751
+ if (parameter.id) typeParameterSymbols.set(parameter.id, parameterSymbol)
752
+ }
521
753
  }
522
754
 
523
755
  for (const [index, declaration] of module.functions.entries()) {
@@ -526,17 +758,45 @@ function resolveSymbols(module, records) {
526
758
 
527
759
  for (const [parameterIndex, parameter] of declaration.parameters.entries()) {
528
760
  scope.set(parameter.name, declare(parameter, parameter.name, "parameter", `${declarationPath}/parameters/${parameterIndex}`))
761
+ visitType(parameter.type, `${declarationPath}/parameters/${parameterIndex}/type`)
529
762
  }
763
+ visitType(declaration.returnType, `${declarationPath}/returnType`)
530
764
  visitBlock(declaration.body, scope, `${declarationPath}/body`)
531
765
  }
532
766
 
767
+ for (const [classIndex, declaration] of (module.classes ?? []).entries()) {
768
+ const declarationPath = `/classes/${classIndex}`
769
+ const constructorScope = new Map()
770
+
771
+ for (const [parameterIndex, parameter] of declaration.constructor.parameters.entries()) {
772
+ const path = `${declarationPath}/constructor/parameters/${parameterIndex}`
773
+
774
+ constructorScope.set(parameter.name, declare(parameter, parameter.name, "parameter", path))
775
+ visitType(parameter.type, `${path}/type`)
776
+ }
777
+ visitBlock(declaration.constructor.body, constructorScope, `${declarationPath}/constructor/body`)
778
+ for (const [methodIndex, method] of declaration.methods.entries()) {
779
+ const methodPath = `${declarationPath}/methods/${methodIndex}`
780
+ const scope = new Map()
781
+
782
+ for (const [parameterIndex, parameter] of method.parameters.entries()) {
783
+ const path = `${methodPath}/parameters/${parameterIndex}`
784
+
785
+ scope.set(parameter.name, declare(parameter, parameter.name, "parameter", path))
786
+ visitType(parameter.type, `${path}/type`)
787
+ }
788
+ visitType(method.returnType, `${methodPath}/returnType`)
789
+ visitBlock(method.body, scope, `${methodPath}/body`)
790
+ }
791
+ }
792
+
533
793
  visitBlock(module.entryPoint.body, new Map(), "/entryPoint/body")
534
794
 
535
795
  return symbols
536
796
 
537
797
  /**
538
798
  * Declares one canonical symbol.
539
- * @param {import("./types.js").FunctionDeclaration | import("./types.js").Parameter | import("./types.js").LocalDeclaration} node - Declaration.
799
+ * @param {import("./types.js").EffectCapabilityDeclaration | import("./types.js").EffectResourceDeclaration | import("./types.js").EffectFailureDeclaration | import("./types.js").EffectOperationDeclaration | import("./types.js").RecordDeclaration | import("./types.js").ClassDeclaration | import("./types.js").ErrorDeclaration | import("./types.js").RecordField | import("./types.js").PrivateField | import("./types.js").ConstructorDeclaration | import("./types.js").MethodDeclaration | import("./types.js").FunctionDeclaration | import("./types.js").TypeParameter | import("./types.js").Parameter | import("./types.js").LocalDeclaration | import("./types.js").ValueBinding | import("./types.js").CatchBinding} node - Declaration.
540
800
  * @param {string} name - Symbol name.
541
801
  * @param {import("./types.js").SemanticSymbolKind} kind - Symbol kind.
542
802
  * @param {string} path - Declaration occurrence path.
@@ -547,11 +807,21 @@ function resolveSymbols(module, records) {
547
807
 
548
808
  if (!record) throw new Error(`Missing provenance for ${node.kind}.`)
549
809
 
550
- const location = record.ranges.name ?? node.location
810
+ const location = record.ranges.name ?? ("location" in node ? node.location : primaryLocation(record.origin))
551
811
  const id = `symbol:${symbols.length}`
552
812
 
553
813
  record.symbolId = id
554
- symbols.push({declarationNodeId: record.id, id, kind, location, name, references: []})
814
+ symbols.push({
815
+ declarationNodeId: record.id,
816
+ id,
817
+ kind,
818
+ location,
819
+ name,
820
+ references: [],
821
+ ...(["capability", "resource", "failure", "operation", "record", "class", "error", "field", "constructor", "method", "function", "typeParameter"].includes(kind)
822
+ ? {semanticDeclarationId: /** @type {{id?: string}} */ (node).id}
823
+ : {})
824
+ })
555
825
 
556
826
  return id
557
827
  }
@@ -570,17 +840,70 @@ function resolveSymbols(module, records) {
570
840
  const statementPath = `${path}/statements/${index}`
571
841
 
572
842
  if (statement.kind == "LocalDeclaration") {
843
+ visitType(statement.type, `${statementPath}/type`)
573
844
  visitExpression(statement.initializer, scope, `${statementPath}/initializer`)
574
845
  scope.set(statement.name, declare(statement, statement.name, "local", statementPath))
575
846
  } else if (statement.kind == "AssignmentStatement") {
576
847
  reference(statement.target, scope.get(statement.target.name), "write", `${statementPath}/target`)
577
848
  visitExpression(statement.expression, scope, `${statementPath}/expression`)
578
- } else if (statement.kind == "ReturnStatement" || statement.kind == "PrintStatement") {
849
+ } else if (statement.kind == "PrivateFieldWriteStatement") {
850
+ reference(statement, fieldSymbols.get(statement.field), "write", statementPath)
851
+ visitExpression(statement.receiver, scope, `${statementPath}/receiver`)
852
+ visitExpression(statement.expression, scope, `${statementPath}/expression`)
853
+ } else if (statement.kind == "ReturnStatement") {
854
+ if (statement.expression) visitExpression(statement.expression, scope, `${statementPath}/expression`)
855
+ } else if (statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement") {
579
856
  visitExpression(statement.expression, scope, `${statementPath}/expression`)
580
857
  } else if (statement.kind == "IfStatement") {
581
858
  visitExpression(statement.condition, scope, `${statementPath}/condition`)
582
859
  visitBlock(statement.consequent, scope, `${statementPath}/consequent`)
583
860
  if (statement.alternate) visitBlock(statement.alternate, scope, `${statementPath}/alternate`)
861
+ } else if (statement.kind == "ForEachStatement") {
862
+ visitExpression(statement.list, scope, `${statementPath}/list`)
863
+ const bodyScope = new Map(scope)
864
+
865
+ visitType(statement.valueBinding.type, `${statementPath}/valueBinding/type`)
866
+
867
+ bodyScope.set(statement.valueBinding.name, declare(
868
+ statement.valueBinding,
869
+ statement.valueBinding.name,
870
+ "iteration",
871
+ `${statementPath}/valueBinding`
872
+ ))
873
+ visitBlock(statement.body, bodyScope, `${statementPath}/body`)
874
+ } else if (statement.kind == "ForEachMapStatement") {
875
+ visitExpression(statement.map, scope, `${statementPath}/map`)
876
+ const bodyScope = new Map(scope)
877
+
878
+ visitType(statement.keyBinding.type, `${statementPath}/keyBinding/type`)
879
+ visitType(statement.valueBinding.type, `${statementPath}/valueBinding/type`)
880
+ bodyScope.set(statement.keyBinding.name, declare(
881
+ statement.keyBinding, statement.keyBinding.name, "iteration", `${statementPath}/keyBinding`
882
+ ))
883
+ bodyScope.set(statement.valueBinding.name, declare(
884
+ statement.valueBinding, statement.valueBinding.name, "iteration", `${statementPath}/valueBinding`
885
+ ))
886
+ visitBlock(statement.body, bodyScope, `${statementPath}/body`)
887
+ } else if (statement.kind == "WhileStatement") {
888
+ visitExpression(statement.condition, scope, `${statementPath}/condition`)
889
+ visitBlock(statement.body, scope, `${statementPath}/body`)
890
+ } else if (statement.kind == "RaiseStatement") {
891
+ visitType(statement.error.error, `${statementPath}/error/error`)
892
+ reference(statement.error, errorSymbols.get(statement.error.error.declarationId), "construct", `${statementPath}/error`)
893
+ visitExpression(statement.error.message, scope, `${statementPath}/error/message`)
894
+ } else if (statement.kind == "TryStatement") {
895
+ visitBlock(statement.body, scope, `${statementPath}/body`)
896
+ visitType(statement.catchType, `${statementPath}/catchType`)
897
+ visitType(statement.catchBinding.type, `${statementPath}/catchBinding/type`)
898
+ const catchScope = new Map(scope)
899
+
900
+ catchScope.set(statement.catchBinding.name, declare(
901
+ statement.catchBinding,
902
+ statement.catchBinding.name,
903
+ "catch",
904
+ `${statementPath}/catchBinding`
905
+ ))
906
+ visitBlock(statement.catchBody, catchScope, `${statementPath}/catchBody`)
584
907
  }
585
908
  }
586
909
  }
@@ -594,22 +917,89 @@ function resolveSymbols(module, records) {
594
917
  */
595
918
  function visitExpression(expression, scope, path) {
596
919
  if (expression.kind == "IdentifierExpression") reference(expression, scope.get(expression.name), "read", path)
920
+ else if (expression.kind == "ReceiverExpression") reference(expression, classSymbols.get(expression.classId), "read", path)
597
921
  else if (expression.kind == "CallExpression") {
598
- reference(expression, functions.get(expression.callee), "call", path)
922
+ const declaration = module.functions.find((candidate) => candidate.id == expression.resolution?.declarationId)
923
+
924
+ reference(expression, declaration ? functions.get(declaration.name) : undefined, "call", path)
599
925
  for (const [index, argument] of expression.arguments.entries()) visitExpression(argument, scope, `${path}/arguments/${index}`)
926
+ } else if (expression.kind == "EffectCallExpression") {
927
+ reference(expression, operationSymbols.get(expression.operation), "call", path)
928
+ for (const [index, argument] of expression.arguments.entries()) visitExpression(argument, scope, `${path}/arguments/${index}`)
929
+ } else if (expression.kind == "OwnedMoveExpression" || expression.kind == "OwnedBorrowExpression") {
930
+ visitExpression(expression.expression, scope, `${path}/expression`)
931
+ } else if (expression.kind == "RecordConstruction") {
932
+ reference(expression, recordSymbols.get(expression.record.declarationId), "construct", path)
933
+ for (const [index, argument] of expression.arguments.entries()) visitExpression(argument, scope, `${path}/arguments/${index}`)
934
+ } else if (expression.kind == "ReferenceConstruction") {
935
+ reference(expression, constructorSymbols.get(/** @type {string} */ (expression.resolution?.declarationId)), "construct", path)
936
+ for (const [index, argument] of expression.arguments.entries()) visitExpression(argument, scope, `${path}/arguments/${index}`)
937
+ } else if (expression.kind == "MethodCallExpression") {
938
+ reference(expression, methodSymbols.get(expression.method), "call", path)
939
+ visitExpression(expression.receiver, scope, `${path}/receiver`)
940
+ for (const [index, argument] of expression.arguments.entries()) visitExpression(argument, scope, `${path}/arguments/${index}`)
941
+ } else if (expression.kind == "MemberRead") {
942
+ reference(expression, fieldSymbols.get(expression.field), "member", path)
943
+ visitExpression(expression.receiver, scope, `${path}/receiver`)
944
+ } else if (expression.kind == "PrivateFieldRead") {
945
+ reference(expression, fieldSymbols.get(expression.field), "member", path)
946
+ visitExpression(expression.receiver, scope, `${path}/receiver`)
947
+ } else if (expression.kind == "ErrorMessageRead") {
948
+ visitExpression(expression.receiver, scope, `${path}/receiver`)
600
949
  } else if (expression.kind == "UnaryExpression") {
601
950
  visitExpression(expression.operand, scope, `${path}/operand`)
602
951
  } else if (expression.kind == "BinaryExpression") {
603
952
  visitExpression(expression.left, scope, `${path}/left`)
604
953
  visitExpression(expression.right, scope, `${path}/right`)
954
+ } else if (expression.kind == "ListLiteral") {
955
+ for (const [index, element] of expression.elements.entries()) visitExpression(element, scope, `${path}/elements/${index}`)
956
+ } else if (expression.kind == "MapLiteral" || expression.kind == "OrderedMapLiteral") {
957
+ for (const [index, entry] of expression.entries.entries()) {
958
+ visitExpression(entry.key, scope, `${path}/entries/${index}/key`)
959
+ visitExpression(entry.value, scope, `${path}/entries/${index}/value`)
960
+ }
961
+ } else if (expression.kind == "ListIndexExpression") {
962
+ visitExpression(expression.collection, scope, `${path}/collection`)
963
+ visitExpression(expression.index, scope, `${path}/index`)
964
+ } else if (expression.kind == "MapLookupExpression") {
965
+ visitExpression(expression.collection, scope, `${path}/collection`)
966
+ visitExpression(expression.key, scope, `${path}/key`)
967
+ } else if (expression.kind == "CollectionSizeExpression") {
968
+ visitExpression(expression.collection, scope, `${path}/collection`)
969
+ } else if (expression.kind == "OptionalSome") {
970
+ visitExpression(expression.value, scope, `${path}/value`)
971
+ } else if (expression.kind == "OptionalIsPresent" || expression.kind == "OptionalUnwrap") {
972
+ visitExpression(expression.operand, scope, `${path}/operand`)
973
+ }
974
+ }
975
+
976
+ /**
977
+ * Resolves nominal references nested in a semantic type.
978
+ * @param {import("./types.js").SemanticFunctionReturnType | import("./types.js").ErrorType} type - Semantic type.
979
+ * @param {string} path - Type occurrence path.
980
+ * @returns {void}
981
+ */
982
+ function visitType(type, path) {
983
+ if (type.kind == "TypeVariableReference") reference(type, typeParameterSymbols.get(type.parameterId), "type", path)
984
+ else if (type.kind == "RecordType") {
985
+ reference(type, recordSymbols.get(type.declarationId), "type", path)
986
+ for (const [index, argument] of (type.arguments ?? []).entries()) visitType(argument, `${path}/arguments/${index}`)
605
987
  }
988
+ else if (type.kind == "ErrorType") reference(type, errorSymbols.get(type.declarationId), "type", path)
989
+ else if (type.kind == "ReferenceType" || type.kind == "OwnedReferenceType") reference(type, classSymbols.get(type.declarationId), "type", path)
990
+ else if (type.kind == "OwnedResourceType") reference(type, resourceSymbols.get(type.resourceId), "type", path)
991
+ else if (type.kind == "ListType") visitType(type.elementType, `${path}/elementType`)
992
+ else if (type.kind == "MapType" || type.kind == "OrderedMapType") {
993
+ visitType(type.keyType, `${path}/keyType`)
994
+ visitType(type.valueType, `${path}/valueType`)
995
+ } else if (type.kind == "OptionalType") visitType(type.valueType, `${path}/valueType`)
606
996
  }
607
997
 
608
998
  /**
609
999
  * Attaches one resolved symbol reference.
610
- * @param {import("./types.js").IdentifierExpression | import("./types.js").CallExpression} node - Reference node.
1000
+ * @param {import("./types.js").IdentifierExpression | import("./types.js").ReceiverExpression | import("./types.js").CallExpression | import("./types.js").EffectCallExpression | import("./types.js").MethodCallExpression | import("./types.js").TypeVariableReference | import("./types.js").RecordType | import("./types.js").ReferenceType | import("./types.js").OwnedReferenceType | import("./types.js").OwnedResourceType | import("./types.js").RecordConstruction | import("./types.js").ReferenceConstruction | import("./types.js").MemberRead | import("./types.js").PrivateFieldRead | import("./types.js").PrivateFieldWriteStatement | import("./types.js").ErrorType | import("./types.js").ErrorConstruction} node - Reference node.
611
1001
  * @param {string | undefined} symbolId - Resolved symbol.
612
- * @param {"read" | "write" | "call"} role - Reference role.
1002
+ * @param {"type" | "construct" | "member" | "read" | "write" | "call"} role - Reference role.
613
1003
  * @param {string} path - Reference occurrence path.
614
1004
  * @returns {void}
615
1005
  */
@@ -621,7 +1011,10 @@ function resolveSymbols(module, records) {
621
1011
 
622
1012
  if (!record || !symbol) throw new Error(`Missing provenance while resolving ${node.kind}.`)
623
1013
 
624
- const location = record.ranges[role == "call" ? "callee" : "name"] ?? node.location
1014
+ const rangeRole = role == "call" ? (node.kind == "MethodCallExpression" ? "member" : "callee") :
1015
+ role == "construct" ? (node.kind == "ErrorConstruction" ? "type" : node.kind == "ReferenceConstruction" ? "class" : "record") :
1016
+ role == "member" || role == "write" && node.kind == "PrivateFieldWriteStatement" ? "member" : role == "type" ? "type" : "name"
1017
+ const location = record.ranges[rangeRole] ?? ("location" in node ? node.location : primaryLocation(record.origin))
625
1018
 
626
1019
  record.symbolId = symbolId
627
1020
  symbol.references.push({location, nodeId: record.id, role})
@@ -21,6 +21,23 @@ export function isScalarTypeName(name) {
21
21
  return scalarTypeNames.some((candidate) => candidate == name)
22
22
  }
23
23
 
24
+ /**
25
+ * Checks a function return type name, including the non-value `void` result.
26
+ * @param {string} name - Candidate semantic return type name.
27
+ * @returns {name is import("./types.js").FunctionReturnTypeName} Whether the name is supported for a function return.
28
+ */
29
+ export function isFunctionReturnTypeName(name) {
30
+ return name == "void" || isScalarTypeName(name)
31
+ }
32
+
33
+ /**
34
+ * Returns the canonical semantic void return type reference.
35
+ * @returns {import("./types.js").FunctionReturnTypeReference} Void return type.
36
+ */
37
+ export function voidType() {
38
+ return {kind: "TypeReference", name: "void"}
39
+ }
40
+
24
41
  /**
25
42
  * Checks that a JavaScript string contains only complete Unicode scalar values.
26
43
  * @param {string} value - Candidate Unicode string.