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
@@ -1,7 +1,10 @@
1
1
  // @ts-check
2
2
 
3
- import {emitExpression} from "./shared.js"
4
- import {emitScalarType} from "./scalars.js"
3
+ import {emitExpression, emitType} from "./shared.js"
4
+ import {emitEffectPrefixes, emitEffectProviderEntries, emitEffectSupport} from "./effects.js"
5
+
6
+ /** @type {WeakMap<import("./writer.js").SourceWriter, Set<string>>} */
7
+ const generatedNames = new WeakMap()
5
8
 
6
9
  /**
7
10
  * Emits an independently executable Java `Main` program through the source-aware writer.
@@ -10,20 +13,144 @@ import {emitScalarType} from "./scalars.js"
10
13
  * @returns {void}
11
14
  */
12
15
  export function generateJava(module, writer) {
13
- writer.synthetic("public final class Main {\n", "Java class scaffolding", [module])
16
+ generatedNames.set(writer, collectNames(module))
17
+ const records = module.records ?? []
18
+ const classes = module.classes ?? []
19
+ const errors = module.errors ?? []
20
+ const programModule = writer.program?.modules.find(({id}) => id == Reflect.get(module, "id"))
21
+
22
+ if (programModule) {
23
+ writer.synthetic(`package semantifold.generated.${programModule.id};\n`, "Java program package", [module])
24
+ const imports = new Map(programModule.imports.map((imported) => {
25
+ const owner = /** @type {import("../semantic/types.js").SemanticProgramModule} */ (
26
+ writer.program?.modules.find(({id}) => id == imported.moduleId))
27
+ const record = owner.records?.find(({id}) => id == imported.declarationId)
28
+ const error = owner.errors?.find(({id}) => id == imported.declarationId)
29
+ const name = record?.name ?? error?.name ?? writer.programModuleName(owner.id)
30
+
31
+ return [`semantifold.generated.${owner.id}.${name}`, imported]
32
+ }))
33
+
34
+ for (const [name, imported] of imports) {
35
+ const importPath = `/imports/${programModule.imports.indexOf(imported)}`
36
+
37
+ writer.synthetic("import ", "Java program import", [imported], [importPath])
38
+ writer.mapped(name, {mappingKind: "anchor", node: imported, path: importPath, role: "path"})
39
+ writer.synthetic(";\n", "Java program import terminator", [imported], [importPath])
40
+ }
41
+ if (writer.program && writer.stdlibProviderOwnerModule !== undefined &&
42
+ writer.stdlibProviderOwnerModule != programModule.id) {
43
+ const owner = writer.stdlibProviderOwnerModule
44
+ const ownerClassName = writer.program.entryModule == owner ? "Main" : writer.programModuleName(owner)
45
+
46
+ for (const typeName of writer.stdlibProviderImports ?? []) {
47
+ writer.synthetic(`import semantifold.generated.${owner}.${ownerClassName}.${typeName};\n`, "Java stdlib capability type import", [module])
48
+ }
49
+ if (Object.keys(writer.stdlibProviderEntries ?? {}).length > 0) {
50
+ writer.synthetic(`import static semantifold.generated.${owner}.${ownerClassName}.*;\n`, "Java stdlib provider static import", [module])
51
+ }
52
+ }
53
+ writer.synthetic("\n", "Java program header separator", [module])
54
+ }
55
+
56
+ emitEffectSupport(writer, module, "java", "top")
57
+ errors.forEach((error, index) => {
58
+ const path = `/errors/${index}`
59
+
60
+ if (index > 0) writer.synthetic("\n\n", "error declaration separator", [error], [path])
61
+ writer.mapped(programModule && writer.isExported(error.id) ? "public final class" : "final class",
62
+ {mappingKind: "anchor", node: error, path})
63
+ writer.synthetic(" ", "error declaration spacing", [error], [path])
64
+ writer.mapped(error.name, {mappingKind: "exact", node: error, path, role: "name"})
65
+ writer.synthetic(" extends RuntimeException {\n ", "Java unchecked error scaffolding", [error], [path])
66
+ if (programModule) writer.synthetic("public ", "Java exported error constructor", [error], [path])
67
+ writer.mapped(error.name, {mappingKind: "exact", node: error, path, role: "name"})
68
+ writer.synthetic("(String message) {\n super(message);\n }\n}", "Java unchecked error scaffolding", [error], [path])
69
+ })
70
+ if (errors.length > 0) writer.synthetic("\n\n", "error/declaration separator", [module])
71
+
72
+ records.forEach((record, recordIndex) => {
73
+ const recordPath = `/records/${recordIndex}`
74
+
75
+ if (recordIndex > 0) writer.synthetic("\n\n", "record declaration separator", [record], [recordPath])
76
+ writer.mapped(programModule && writer.isExported(record.id) ? "public final class" : "final class",
77
+ {mappingKind: "anchor", node: record, path: recordPath})
78
+ writer.synthetic(" ", "record declaration spacing", [record], [recordPath])
79
+ writer.mapped(record.name, {mappingKind: "exact", node: record, path: recordPath, role: "name"})
80
+ emitTypeParameters(writer, record.typeParameters ?? [], `${recordPath}/typeParameters`)
81
+ writer.synthetic(" {\n", "Java record class scaffolding", [record], [recordPath])
82
+ record.fields.forEach((field, fieldIndex) => {
83
+ const fieldPath = `${recordPath}/fields/${fieldIndex}`
84
+
85
+ writer.synthetic(" private final ", "Java record storage scaffolding", [field], [fieldPath])
86
+ emitType(writer, field.type, `${fieldPath}/type`, "java")
87
+ writer.synthetic(" ", "Java record field spacing", [field], [fieldPath])
88
+ writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
89
+ writer.synthetic(";\n", "Java record storage scaffolding", [field], [fieldPath])
90
+ })
91
+ writer.synthetic(programModule ? "\n public " : "\n ", "Java record constructor spacing", [record], [recordPath])
92
+ writer.mapped(record.name, {mappingKind: "exact", node: record, path: recordPath, role: "name"})
93
+ writer.synthetic("(", "Java record constructor scaffolding", [record], [recordPath])
94
+ record.fields.forEach((field, fieldIndex) => {
95
+ const fieldPath = `${recordPath}/fields/${fieldIndex}`
96
+
97
+ if (fieldIndex) writer.synthetic(", ", "record field separator", [record], [recordPath])
98
+ emitType(writer, field.type, `${fieldPath}/type`, "java")
99
+ writer.synthetic(" ", "Java record field spacing", [field], [fieldPath])
100
+ writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
101
+ })
102
+ writer.synthetic(") {\n", "Java record constructor scaffolding", [record], [recordPath])
103
+ record.fields.forEach((field, fieldIndex) => {
104
+ const fieldPath = `${recordPath}/fields/${fieldIndex}`
105
+
106
+ writer.synthetic(" this.", "Java record initialization scaffolding", [field], [fieldPath])
107
+ writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
108
+ writer.synthetic(" = ", "Java record initialization scaffolding", [field], [fieldPath])
109
+ writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
110
+ writer.synthetic(";\n", "Java record initialization scaffolding", [field], [fieldPath])
111
+ })
112
+ writer.synthetic(" }\n", "Java record constructor scaffolding", [record], [recordPath])
113
+ record.fields.forEach((field, fieldIndex) => {
114
+ const fieldPath = `${recordPath}/fields/${fieldIndex}`
115
+
116
+ writer.synthetic(programModule ? "\n public " : "\n ", "Java record accessor spacing", [field], [fieldPath])
117
+ emitType(writer, field.type, `${fieldPath}/type`, "java")
118
+ writer.synthetic(" ", "Java record accessor spacing", [field], [fieldPath])
119
+ writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
120
+ writer.synthetic("() {\n return this.", "Java record accessor scaffolding", [field], [fieldPath])
121
+ writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
122
+ writer.synthetic(";\n }\n", "Java record accessor scaffolding", [field], [fieldPath])
123
+ })
124
+ writer.synthetic("}", "Java record class scaffolding", [record], [recordPath])
125
+ })
126
+ if (programModule && records.length + errors.length > 0) {
127
+ writer.synthetic("\n", "Java source terminator", [module])
128
+ return
129
+ }
130
+ classes.forEach((declaration, classIndex) => {
131
+ if (records.length > 0 || classIndex > 0) writer.synthetic("\n\n", "reference class separator", [declaration], [`/classes/${classIndex}`])
132
+ emitReferenceClass(writer, declaration, classIndex)
133
+ })
134
+ if (records.length + classes.length > 0) writer.synthetic("\n\n", "nominal/Main separator", [module])
135
+ const className = programModule
136
+ ? writer.isProgramEntry() ? "Main" : writer.programModuleName(programModule.id)
137
+ : "Main"
138
+
139
+ writer.synthetic(`public final class ${className} {\n`, "Java class scaffolding", [module])
140
+ emitEffectSupport(writer, module, "java", "members")
141
+ emitEffectProviderEntries(writer, module)
14
142
 
15
143
  module.functions.forEach((declaration, functionIndex) => {
16
144
  if (functionIndex > 0) writer.synthetic("\n\n", "declaration separator", [declaration])
17
145
 
18
146
  writer.synthetic(" ", "indentation", [declaration])
19
- writer.mapped("private static", {mappingKind: "anchor", node: declaration})
147
+ writer.mapped(programModule && writer.isExported(declaration.id) ? "public static" :
148
+ !programModule && classes.length > 0 ? "static" : "private static",
149
+ {mappingKind: "anchor", node: declaration})
20
150
  writer.synthetic(" ", "method spacing", [declaration])
21
- writer.mapped(emitScalarType("java", declaration.returnType), {
22
- mappingKind: "exact",
23
- node: declaration.returnType,
24
- path: `/functions/${functionIndex}/returnType`,
25
- role: "type"
26
- })
151
+ emitTypeParameters(writer, declaration.typeParameters ?? [], `/functions/${functionIndex}/typeParameters`)
152
+ if ((declaration.typeParameters?.length ?? 0) > 0) writer.synthetic(" ", "generic method spacing", [declaration])
153
+ emitType(writer, declaration.returnType, `/functions/${functionIndex}/returnType`, "java")
27
154
  writer.synthetic(" ", "method spacing", [declaration])
28
155
  writer.mapped(declaration.name, {mappingKind: "exact", node: declaration, role: "name"})
29
156
  writer.mapped("(", {mappingKind: "anchor", node: declaration})
@@ -31,12 +158,7 @@ export function generateJava(module, writer) {
31
158
  const parameterPath = `/functions/${functionIndex}/parameters/${index}`
32
159
 
33
160
  if (index > 0) writer.synthetic(", ", "parameter separator", [declaration])
34
- writer.mapped(emitScalarType("java", parameter.type), {
35
- mappingKind: "exact",
36
- node: parameter.type,
37
- path: `${parameterPath}/type`,
38
- role: "type"
39
- })
161
+ emitType(writer, parameter.type, `${parameterPath}/type`, "java")
40
162
  writer.synthetic(" ", "parameter spacing", [parameter], [parameterPath])
41
163
  writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: parameterPath, role: "name"})
42
164
  })
@@ -50,22 +172,118 @@ export function generateJava(module, writer) {
50
172
  writer.mapped("}", {mappingKind: "anchor", node: declaration})
51
173
  })
52
174
 
53
- writer.synthetic("\n\n", "entry-point separator", [module.entryPoint])
54
- writer.synthetic(" ", "indentation", [module.entryPoint])
55
- writer.mapped("public static void main", {mappingKind: "anchor", node: module.entryPoint})
56
- writer.mapped("(", {mappingKind: "anchor", node: module.entryPoint})
57
- writer.synthetic("String[] args", "Java entry-point signature", [module.entryPoint])
58
- writer.mapped(")", {mappingKind: "anchor", node: module.entryPoint})
59
- writer.synthetic(" ", "method spacing", [module.entryPoint])
60
- writer.mapped("{", {mappingKind: "anchor", node: module.entryPoint})
61
- writer.synthetic("\n", "line break", [module.entryPoint])
62
-
63
- emitBlock(writer, module.entryPoint.body, " ", "/entryPoint/body")
64
- writer.synthetic(" ", "indentation", [module.entryPoint])
65
- writer.mapped("}", {mappingKind: "anchor", node: module.entryPoint})
175
+ if (!programModule || writer.isProgramEntry()) {
176
+ writer.synthetic("\n\n", "entry-point separator", [module.entryPoint])
177
+ writer.synthetic(" ", "indentation", [module.entryPoint])
178
+ writer.mapped("public static void main", {mappingKind: "anchor", node: module.entryPoint})
179
+ writer.mapped("(", {mappingKind: "anchor", node: module.entryPoint})
180
+ writer.synthetic("String[] args", "Java entry-point signature", [module.entryPoint])
181
+ writer.mapped(")", {mappingKind: "anchor", node: module.entryPoint})
182
+ writer.synthetic(" ", "method spacing", [module.entryPoint])
183
+ writer.mapped("{", {mappingKind: "anchor", node: module.entryPoint})
184
+ writer.synthetic("\n", "line break", [module.entryPoint])
185
+
186
+ emitBlock(writer, module.entryPoint.body, " ", "/entryPoint/body")
187
+ writer.synthetic(" ", "indentation", [module.entryPoint])
188
+ writer.mapped("}", {mappingKind: "anchor", node: module.entryPoint})
189
+ }
66
190
  writer.synthetic("\n}\n", "Java class scaffolding", [module])
67
191
  }
68
192
 
193
+ /**
194
+ * Emits one package-private final Java reference class.
195
+ * @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
196
+ * @param {import("../semantic/types.js").ClassDeclaration} declaration - Reference class.
197
+ * @param {number} classIndex - Module class index.
198
+ * @returns {void}
199
+ */
200
+ function emitReferenceClass(writer, declaration, classIndex) {
201
+ const path = `/classes/${classIndex}`
202
+
203
+ writer.mapped("final class", {mappingKind: "anchor", node: declaration, path})
204
+ writer.synthetic(" ", "reference class spacing", [declaration], [path])
205
+ writer.mapped(declaration.name, {mappingKind: "exact", node: declaration, path, role: "name"})
206
+ writer.synthetic(" {\n", "reference class open", [declaration], [path])
207
+ declaration.fields.forEach((field, index) => {
208
+ const fieldPath = `${path}/fields/${index}`
209
+
210
+ writer.synthetic(" private ", "private field scaffolding", [field], [fieldPath])
211
+ emitType(writer, field.type, `${fieldPath}/type`, "java")
212
+ writer.synthetic(" ", "private field spacing", [field], [fieldPath])
213
+ writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
214
+ writer.synthetic(";\n", "line break", [field], [fieldPath])
215
+ })
216
+ const constructor = declaration.constructor
217
+ const constructorPath = `${path}/constructor`
218
+
219
+ writer.synthetic("\n ", "constructor spacing", [constructor], [constructorPath])
220
+ writer.mapped(declaration.name, {mappingKind: "exact", node: constructor, path: constructorPath, role: "constructor"})
221
+ emitJavaParameters(writer, constructor.parameters, `${constructorPath}/parameters`)
222
+ writer.synthetic(" {\n", "constructor open", [constructor], [constructorPath])
223
+ writer.beginReferenceClassEmission()
224
+ try {
225
+ emitBlock(writer, constructor.body, " ", `${constructorPath}/body`)
226
+ } finally {
227
+ writer.endReferenceClassEmission()
228
+ }
229
+ writer.synthetic(" }", "constructor close", [constructor], [constructorPath])
230
+ declaration.methods.forEach((method, index) => {
231
+ const methodPath = `${path}/methods/${index}`
232
+
233
+ writer.synthetic("\n\n ", "method spacing", [method], [methodPath])
234
+ emitType(writer, method.returnType, `${methodPath}/returnType`, "java")
235
+ writer.synthetic(" ", "method spacing", [method], [methodPath])
236
+ writer.mapped(method.name, {mappingKind: "exact", node: method, path: methodPath, role: "name"})
237
+ emitJavaParameters(writer, method.parameters, `${methodPath}/parameters`)
238
+ writer.synthetic(" {\n", "method open", [method], [methodPath])
239
+ writer.beginReferenceClassEmission()
240
+ try {
241
+ emitBlock(writer, method.body, " ", `${methodPath}/body`)
242
+ } finally {
243
+ writer.endReferenceClassEmission()
244
+ }
245
+ writer.synthetic(" }", "method close", [method], [methodPath])
246
+ })
247
+ writer.synthetic("\n", "line break", [declaration], [path])
248
+ writer.mapped("}", {mappingKind: "anchor", node: declaration, path})
249
+ }
250
+
251
+ /**
252
+ * Emits one Java parameter list.
253
+ * @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
254
+ * @param {import("../semantic/types.js").Parameter[]} parameters - Ordered parameters.
255
+ * @param {string} path - Parameter collection path.
256
+ * @returns {void}
257
+ */
258
+ function emitJavaParameters(writer, parameters, path) {
259
+ writer.synthetic("(", "parameter list open", parameters)
260
+ parameters.forEach((parameter, index) => {
261
+ const parameterPath = `${path}/${index}`
262
+
263
+ if (index) writer.synthetic(", ", "parameter separator", parameters)
264
+ emitType(writer, parameter.type, `${parameterPath}/type`, "java")
265
+ writer.synthetic(" ", "parameter spacing", [parameter], [parameterPath])
266
+ writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: parameterPath, role: "name"})
267
+ })
268
+ writer.synthetic(")", "parameter list close", parameters)
269
+ }
270
+
271
+ /**
272
+ * Emits native invariant Java declaration parameters.
273
+ * @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
274
+ * @param {import("../semantic/types.js").TypeParameter[]} parameters - Ordered type parameters.
275
+ * @param {string} path - Type-parameter collection path.
276
+ */
277
+ function emitTypeParameters(writer, parameters, path) {
278
+ if (parameters.length == 0) return
279
+ writer.synthetic("<", "Java type parameter open", parameters)
280
+ parameters.forEach((parameter, index) => {
281
+ if (index) writer.synthetic(", ", "Java type parameter separator", parameters)
282
+ writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: `${path}/${index}`, role: "name"})
283
+ })
284
+ writer.synthetic(">", "Java type parameter close", parameters)
285
+ }
286
+
69
287
  /**
70
288
  * Emits one ordered Java block body.
71
289
  * @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
@@ -87,11 +305,128 @@ function emitBlock(writer, block, indent, path) {
87
305
  * @returns {void}
88
306
  */
89
307
  function emitStatement(writer, statement, indent, path) {
308
+ emitEffectPrefixes(writer, statement, indent, path, "java",
309
+ (expression, expressionPath) => emitExpression(writer, expression, expressionPath, "java", identity))
90
310
  if (statement.kind == "LocalDeclaration" || statement.kind == "AssignmentStatement") return emitLocal(writer, statement, indent, path)
91
311
  writer.synthetic(indent, "indentation", [statement], [path])
312
+ if (statement.kind == "PrivateFieldWriteStatement") {
313
+ emitExpression(writer, statement.receiver, `${path}/receiver`, "java", identity)
314
+ const field = writer.privateFieldForId(statement.field)
315
+
316
+ writer.mapped(`.${field.name}`, {mappingKind: "exact", name: field.name, node: statement, path, role: "member"})
317
+ writer.synthetic(" = ", "private field assignment", [statement], [path])
318
+ emitExpression(writer, statement.expression, `${path}/expression`, "java", identity)
319
+ writer.mapped(";", {mappingKind: "anchor", node: statement, path})
320
+ writer.synthetic("\n", "line break", [statement], [path])
321
+ return
322
+ }
323
+ if (statement.kind == "BreakStatement" || statement.kind == "ContinueStatement") {
324
+ writer.mapped(statement.kind == "BreakStatement" ? "break" : "continue", {mappingKind: "exact", node: statement, path})
325
+ writer.mapped(";", {mappingKind: "anchor", node: statement, path})
326
+ writer.synthetic("\n", "line break", [statement], [path])
327
+ return
328
+ }
329
+ if (statement.kind == "WhileStatement") {
330
+ writer.mapped("while", {mappingKind: "exact", node: statement, path})
331
+ writer.synthetic(" (", "condition-controlled loop spacing", [statement], [path])
332
+ emitExpression(writer, statement.condition, `${path}/condition`, "java", identity)
333
+ writer.synthetic(") ", "condition-controlled loop spacing", [statement], [path])
334
+ writer.mapped("{", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
335
+ writer.synthetic("\n", "line break", [statement], [path])
336
+ emitBlock(writer, statement.body, `${indent} `, `${path}/body`)
337
+ writer.synthetic(indent, "indentation", [statement], [path])
338
+ writer.mapped("}", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
339
+ writer.synthetic("\n", "line break", [statement], [path])
340
+ return
341
+ }
342
+ if (statement.kind == "ForEachStatement") {
343
+ writer.mapped("for", {mappingKind: "anchor", node: statement, path})
344
+ writer.synthetic(" (", "loop scaffolding", [statement], [path])
345
+ emitType(writer, statement.valueBinding.type, `${path}/valueBinding/type`, "java", true)
346
+ writer.synthetic(" ", "iteration binding spacing", [statement.valueBinding], [`${path}/valueBinding`])
347
+ writer.mapped(statement.valueBinding.name, {
348
+ mappingKind: "exact", node: statement.valueBinding, path: `${path}/valueBinding`, role: "name"
349
+ })
350
+ writer.synthetic(" : ", "loop scaffolding", [statement], [path])
351
+ emitExpression(writer, statement.list, `${path}/list`, "java", identity)
352
+ writer.synthetic(") ", "loop scaffolding", [statement], [path])
353
+ writer.mapped("{", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
354
+ writer.synthetic("\n", "line break", [statement], [path])
355
+ emitBlock(writer, statement.body, `${indent} `, `${path}/body`)
356
+ writer.synthetic(indent, "indentation", [statement], [path])
357
+ writer.mapped("}", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
358
+ writer.synthetic("\n", "line break", [statement], [path])
359
+ return
360
+ }
361
+ if (statement.kind == "ForEachMapStatement") {
362
+ const entryName = freshGeneratedName(writer, "__semantifold_entry")
363
+
364
+ writer.mapped("for", {mappingKind: "anchor", node: statement, path})
365
+ writer.synthetic(" (java.util.Map.Entry<", "ordered-map loop scaffolding", [statement], [path])
366
+ emitType(writer, statement.keyBinding.type, `${path}/keyBinding/type`, "java", true)
367
+ writer.synthetic(",", "ordered-map entry type separator", [statement], [path])
368
+ emitType(writer, statement.valueBinding.type, `${path}/valueBinding/type`, "java", true)
369
+ writer.synthetic(`> ${entryName} : `, "ordered-map loop scaffolding", [statement], [path])
370
+ emitExpression(writer, statement.map, `${path}/map`, "java", identity)
371
+ writer.synthetic(".sequencedEntrySet()) ", "ordered-map loop scaffolding", [statement], [path])
372
+ writer.mapped("{", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
373
+ writer.synthetic("\n", "line break", [statement], [path])
374
+ emitJavaMapPairBinding(writer, statement.keyBinding, `${indent} `, `${path}/keyBinding`, entryName, "getKey")
375
+ emitJavaMapPairBinding(writer, statement.valueBinding, `${indent} `, `${path}/valueBinding`, entryName, "getValue")
376
+ emitBlock(writer, statement.body, `${indent} `, `${path}/body`)
377
+ writer.synthetic(indent, "indentation", [statement], [path])
378
+ writer.mapped("}", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
379
+ writer.synthetic("\n", "line break", [statement], [path])
380
+ return
381
+ }
382
+ if (statement.kind == "RaiseStatement") {
383
+ const type = statement.error.error
384
+ const error = writer.errorForId(type.declarationId)
385
+
386
+ writer.mapped("throw", {mappingKind: "anchor", node: statement, path})
387
+ writer.synthetic(" new ", "error construction scaffolding", [statement.error], [`${path}/error`])
388
+ writer.mapped(writer.errorNameForId(type.declarationId), {mappingKind: "exact", name: error.name, node: statement.error, path: `${path}/error`, role: "type"})
389
+ writer.synthetic("(", "error construction open", [statement.error], [`${path}/error`])
390
+ emitExpression(writer, statement.error.message, `${path}/error/message`, "java", identity)
391
+ writer.synthetic(");\n", "error construction close", [statement.error], [`${path}/error`])
392
+ return
393
+ }
394
+ if (statement.kind == "TryStatement") {
395
+ const caught = writer.errorForId(statement.catchType.declarationId)
396
+
397
+ writer.mapped("try", {mappingKind: "anchor", node: statement, path})
398
+ writer.synthetic(" ", "try spacing", [statement], [path])
399
+ writer.mapped("{", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
400
+ writer.synthetic("\n", "line break", [statement], [path])
401
+ emitBlock(writer, statement.body, `${indent} `, `${path}/body`)
402
+ writer.synthetic(indent, "indentation", [statement], [path])
403
+ writer.mapped("}", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
404
+ writer.synthetic(" ", "catch spacing", [statement], [path])
405
+ writer.mapped("catch", {mappingKind: "anchor", node: statement, path, role: "catch"})
406
+ writer.synthetic(" (", "catch binding scaffolding", [statement.catchBinding], [`${path}/catchBinding`])
407
+ writer.mapped(writer.errorNameForId(statement.catchType.declarationId), {mappingKind: "exact", name: caught.name, node: statement.catchType, path: `${path}/catchType`, role: "type"})
408
+ writer.synthetic(" ", "catch binding spacing", [statement.catchBinding], [`${path}/catchBinding`])
409
+ writer.mapped(statement.catchBinding.name, {mappingKind: "exact", node: statement.catchBinding, path: `${path}/catchBinding`, role: "name"})
410
+ writer.synthetic(") ", "catch binding scaffolding", [statement.catchBinding], [`${path}/catchBinding`])
411
+ writer.mapped("{", {mappingKind: "anchor", node: statement.catchBody, path: `${path}/catchBody`})
412
+ writer.synthetic("\n", "line break", [statement], [path])
413
+ emitBlock(writer, statement.catchBody, `${indent} `, `${path}/catchBody`)
414
+ writer.synthetic(indent, "indentation", [statement], [path])
415
+ writer.mapped("}", {mappingKind: "anchor", node: statement.catchBody, path: `${path}/catchBody`})
416
+ writer.synthetic("\n", "line break", [statement], [path])
417
+ return
418
+ }
92
419
  if (statement.kind == "ReturnStatement") {
93
420
  writer.mapped("return", {mappingKind: "anchor", node: statement, path})
94
- writer.synthetic(" ", "return spacing", [statement], [path])
421
+ if (statement.expression) {
422
+ writer.synthetic(" ", "return spacing", [statement], [path])
423
+ emitExpression(writer, statement.expression, `${path}/expression`, "java", identity)
424
+ }
425
+ writer.mapped(";", {mappingKind: "anchor", node: statement, path})
426
+ writer.synthetic("\n", "line break", [statement], [path])
427
+ return
428
+ }
429
+ if (statement.kind == "ExpressionStatement") {
95
430
  emitExpression(writer, statement.expression, `${path}/expression`, "java", identity)
96
431
  writer.mapped(";", {mappingKind: "anchor", node: statement, path})
97
432
  writer.synthetic("\n", "line break", [statement], [path])
@@ -139,6 +474,38 @@ function emitStatement(writer, statement, indent, path) {
139
474
  * @returns {void}
140
475
  */
141
476
  function emitLocal(writer, statement, indent, statementPath) {
477
+ if (statement.kind == "LocalDeclaration" && statement.initializer.kind == "OrderedMapLiteral" &&
478
+ statement.type.kind == "OrderedMapType") {
479
+ const backingName = freshGeneratedName(writer, `__semantifold_${statement.name}_backing`)
480
+
481
+ writer.synthetic(`${indent}final java.util.LinkedHashMap<`, "ordered-map backing declaration", [statement], [statementPath])
482
+ emitType(writer, statement.type.keyType, `${statementPath}/type/keyType`, "java", true)
483
+ writer.synthetic(",", "ordered-map backing type separator", [statement], [statementPath])
484
+ emitType(writer, statement.type.valueType, `${statementPath}/type/valueType`, "java", true)
485
+ writer.synthetic(`> ${backingName} = new java.util.LinkedHashMap<>();\n`, "ordered-map backing construction", [statement], [statementPath])
486
+ statement.initializer.entries.forEach((entry, index) => {
487
+ const entryPath = `${statementPath}/initializer/entries/${index}`
488
+
489
+ writer.synthetic(`${indent}${backingName}.`, "ordered-map insertion receiver", [entry], [entryPath])
490
+ writer.mapped("put", {mappingKind: "anchor", node: entry, path: entryPath, role: "operator"})
491
+ writer.synthetic("(", "ordered-map insertion open", [entry], [entryPath])
492
+ emitExpression(writer, entry.key, `${entryPath}/key`, "java", identity)
493
+ writer.synthetic(", ", "ordered-map insertion separator", [entry], [entryPath])
494
+ emitExpression(writer, entry.value, `${entryPath}/value`, "java", identity)
495
+ writer.synthetic(");\n", "ordered-map insertion close", [entry], [entryPath])
496
+ })
497
+ writer.synthetic(indent, "indentation", [statement], [statementPath])
498
+ writer.mapped("final", {mappingKind: "anchor", node: statement, path: statementPath})
499
+ writer.synthetic(" ", "modifier spacing", [statement], [statementPath])
500
+ emitType(writer, statement.type, `${statementPath}/type`, "java")
501
+ writer.synthetic(" ", "declaration spacing", [statement], [statementPath])
502
+ writer.mapped(statement.name, {mappingKind: "exact", node: statement, path: statementPath, role: "name"})
503
+ writer.synthetic(" ", "assignment spacing", [statement], [statementPath])
504
+ writer.mapped("=", {mappingKind: "exact", node: statement, path: statementPath, role: "operator"})
505
+ writer.synthetic(` java.util.Collections.unmodifiableSequencedMap(${backingName});\n`,
506
+ "ordered-map immutable boundary", [statement.initializer], [`${statementPath}/initializer`])
507
+ return
508
+ }
142
509
  writer.synthetic(indent, "indentation", [statement], [statementPath])
143
510
 
144
511
  if (statement.kind == "AssignmentStatement") {
@@ -156,12 +523,7 @@ function emitLocal(writer, statement, indent, statementPath) {
156
523
  writer.mapped("final", {mappingKind: "anchor", node: statement, path: statementPath})
157
524
  writer.synthetic(" ", "modifier spacing", [statement], [statementPath])
158
525
  }
159
- writer.mapped(emitScalarType("java", statement.type), {
160
- mappingKind: "exact",
161
- node: statement.type,
162
- path: `${statementPath}/type`,
163
- role: "type"
164
- })
526
+ emitType(writer, statement.type, `${statementPath}/type`, "java")
165
527
  writer.synthetic(" ", "declaration spacing", [statement], [statementPath])
166
528
  writer.mapped(statement.name, {mappingKind: "exact", node: statement, path: statementPath, role: "name"})
167
529
  writer.synthetic(" ", "assignment spacing", [statement], [statementPath])
@@ -172,6 +534,62 @@ function emitLocal(writer, statement, indent, statementPath) {
172
534
  writer.synthetic("\n", "line break", [statement], [statementPath])
173
535
  }
174
536
 
537
+ /**
538
+ * Emits one immutable semantic map-loop binding from the hidden native entry.
539
+ * @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
540
+ * @param {import("../semantic/types.js").ValueBinding} binding - Semantic binding.
541
+ * @param {string} indent - Leading indentation.
542
+ * @param {string} path - Exact binding path.
543
+ * @param {string} entryName - Collision-safe hidden entry name.
544
+ * @param {"getKey" | "getValue"} accessor - Native accessor.
545
+ * @returns {void}
546
+ */
547
+ function emitJavaMapPairBinding(writer, binding, indent, path, entryName, accessor) {
548
+ writer.synthetic(`${indent}final `, "ordered-map binding declaration", [binding], [path])
549
+ emitType(writer, binding.type, `${path}/type`, "java")
550
+ writer.synthetic(" ", "ordered-map binding spacing", [binding], [path])
551
+ writer.mapped(binding.name, {mappingKind: "exact", node: binding, path, role: "name"})
552
+ writer.synthetic(` = ${entryName}.${accessor}();\n`, "ordered-map entry access", [binding], [path])
553
+ }
554
+
555
+ /**
556
+ * Allocates a Java identifier that cannot capture any semantic source name in this module.
557
+ * @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
558
+ * @param {string} preferred - Stable readable prefix.
559
+ * @returns {string} Fresh identifier.
560
+ */
561
+ function freshGeneratedName(writer, preferred) {
562
+ const names = generatedNames.get(writer) ?? new Set()
563
+ let name = preferred
564
+ let suffix = 2
565
+
566
+ while (names.has(name)) {
567
+ name = `${preferred}_${suffix}`
568
+ suffix += 1
569
+ }
570
+ names.add(name)
571
+ generatedNames.set(writer, names)
572
+ return name
573
+ }
574
+
575
+ /**
576
+ * Collects every semantic name so generated Java temporaries remain hygienic.
577
+ * @param {unknown} value - Semantic subtree.
578
+ * @param {Set<object>} [seen] - Cycle protection.
579
+ * @param {Set<string>} [names] - Accumulated names.
580
+ * @returns {Set<string>} All explicit names.
581
+ */
582
+ function collectNames(value, seen = new Set(), names = new Set()) {
583
+ if (!value || typeof value != "object" || seen.has(value)) return names
584
+ seen.add(value)
585
+ if (!Array.isArray(value) && typeof Reflect.get(value, "name") == "string") {
586
+ names.add(/** @type {string} */ (Reflect.get(value, "name")))
587
+ }
588
+ for (const child of Array.isArray(value) ? value : Object.values(value)) collectNames(child, seen, names)
589
+
590
+ return names
591
+ }
592
+
175
593
  /**
176
594
  * Returns an unchanged Java identifier.
177
595
  * @param {string} name - Identifier.