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.
- package/README.md +61 -15
- package/build/index.d.ts +52 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +60 -8
- package/build/src/artifact-path.d.ts +23 -1
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +45 -3
- package/build/src/artifacts.d.ts.map +1 -1
- package/build/src/artifacts.js +66 -1
- package/build/src/backends/android.d.ts +49 -0
- package/build/src/backends/android.d.ts.map +1 -0
- package/build/src/backends/android.js +1274 -0
- package/build/src/backends/c-validation.d.ts.map +1 -1
- package/build/src/backends/c-validation.js +7 -3
- package/build/src/backends/cpp-validation.d.ts.map +1 -1
- package/build/src/backends/cpp-validation.js +7 -3
- package/build/src/backends/csharp.js +7 -1
- package/build/src/backends/dart-runtime.d.ts +2 -0
- package/build/src/backends/dart-runtime.d.ts.map +1 -0
- package/build/src/backends/dart-runtime.js +41 -0
- package/build/src/backends/dart.d.ts +20 -0
- package/build/src/backends/dart.d.ts.map +1 -0
- package/build/src/backends/dart.js +321 -0
- package/build/src/backends/effects.d.ts +60 -0
- package/build/src/backends/effects.d.ts.map +1 -0
- package/build/src/backends/effects.js +746 -0
- package/build/src/backends/go.js +18 -4
- package/build/src/backends/identifiers.d.ts +36 -4
- package/build/src/backends/identifiers.d.ts.map +1 -1
- package/build/src/backends/identifiers.js +160 -10
- package/build/src/backends/index.d.ts.map +1 -1
- package/build/src/backends/index.js +27 -4
- package/build/src/backends/ios.d.ts +68 -0
- package/build/src/backends/ios.d.ts.map +1 -0
- package/build/src/backends/ios.js +1503 -0
- package/build/src/backends/java.d.ts.map +1 -1
- package/build/src/backends/java.js +429 -36
- package/build/src/backends/javascript.d.ts +6 -0
- package/build/src/backends/javascript.d.ts.map +1 -1
- package/build/src/backends/javascript.js +380 -24
- package/build/src/backends/kotlin-runtime.d.ts +3 -0
- package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
- package/build/src/backends/kotlin-runtime.js +29 -0
- package/build/src/backends/kotlin.d.ts +33 -0
- package/build/src/backends/kotlin.d.ts.map +1 -0
- package/build/src/backends/kotlin.js +138 -0
- package/build/src/backends/native-validation.d.ts +2 -2
- package/build/src/backends/native-validation.d.ts.map +1 -1
- package/build/src/backends/native-validation.js +2 -2
- package/build/src/backends/ordered-expressions.d.ts.map +1 -1
- package/build/src/backends/ordered-expressions.js +39 -7
- package/build/src/backends/php-stdlib-support.d.ts +19 -0
- package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
- package/build/src/backends/php-stdlib-support.js +227 -0
- package/build/src/backends/php.d.ts.map +1 -1
- package/build/src/backends/php.js +448 -33
- package/build/src/backends/program.d.ts +83 -0
- package/build/src/backends/program.d.ts.map +1 -0
- package/build/src/backends/program.js +1309 -0
- package/build/src/backends/python.js +7 -1
- package/build/src/backends/ruby.d.ts.map +1 -1
- package/build/src/backends/ruby.js +310 -24
- package/build/src/backends/rust-runtime.d.ts +7 -0
- package/build/src/backends/rust-runtime.d.ts.map +1 -0
- package/build/src/backends/rust-runtime.js +32 -0
- package/build/src/backends/rust-validation.d.ts +9 -0
- package/build/src/backends/rust-validation.d.ts.map +1 -0
- package/build/src/backends/rust-validation.js +78 -0
- package/build/src/backends/rust.d.ts +24 -0
- package/build/src/backends/rust.d.ts.map +1 -0
- package/build/src/backends/rust.js +344 -0
- package/build/src/backends/scalars.d.ts +14 -6
- package/build/src/backends/scalars.d.ts.map +1 -1
- package/build/src/backends/scalars.js +167 -17
- package/build/src/backends/shared.d.ts +23 -4
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +2174 -62
- package/build/src/backends/stdlib-support.d.ts +14 -0
- package/build/src/backends/stdlib-support.d.ts.map +1 -0
- package/build/src/backends/stdlib-support.js +237 -0
- package/build/src/backends/swift-runtime.d.ts +3 -0
- package/build/src/backends/swift-runtime.d.ts.map +1 -0
- package/build/src/backends/swift-runtime.js +14 -0
- package/build/src/backends/swift.d.ts +8 -0
- package/build/src/backends/swift.d.ts.map +1 -0
- package/build/src/backends/swift.js +127 -0
- package/build/src/backends/typescript.d.ts.map +1 -1
- package/build/src/backends/typescript.js +344 -24
- package/build/src/backends/wasm.d.ts +43 -0
- package/build/src/backends/wasm.d.ts.map +1 -0
- package/build/src/backends/wasm.js +2164 -0
- package/build/src/backends/writer.d.ts +255 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +491 -3
- package/build/src/diagnostic.d.ts +4 -3
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +5 -3
- package/build/src/frontends/c.d.ts.map +1 -1
- package/build/src/frontends/c.js +5 -3
- package/build/src/frontends/cpp.d.ts.map +1 -1
- package/build/src/frontends/cpp.js +5 -3
- package/build/src/frontends/csharp.d.ts.map +1 -1
- package/build/src/frontends/csharp.js +7 -3
- package/build/src/frontends/dart.d.ts +10 -0
- package/build/src/frontends/dart.d.ts.map +1 -0
- package/build/src/frontends/dart.js +913 -0
- package/build/src/frontends/index.d.ts +3 -1
- package/build/src/frontends/index.d.ts.map +1 -1
- package/build/src/frontends/index.js +15 -5
- package/build/src/frontends/java.d.ts +110 -1
- package/build/src/frontends/java.d.ts.map +1 -1
- package/build/src/frontends/java.js +1725 -70
- package/build/src/frontends/javascript-typescript.d.ts +69 -1
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
- package/build/src/frontends/javascript-typescript.js +1825 -93
- package/build/src/frontends/kotlin.d.ts +10 -0
- package/build/src/frontends/kotlin.d.ts.map +1 -0
- package/build/src/frontends/kotlin.js +685 -0
- package/build/src/frontends/php.d.ts +118 -1
- package/build/src/frontends/php.d.ts.map +1 -1
- package/build/src/frontends/php.js +1583 -76
- package/build/src/frontends/program.d.ts +74 -0
- package/build/src/frontends/program.d.ts.map +1 -0
- package/build/src/frontends/program.js +989 -0
- package/build/src/frontends/ruby.d.ts +68 -1
- package/build/src/frontends/ruby.d.ts.map +1 -1
- package/build/src/frontends/ruby.js +1446 -101
- package/build/src/frontends/rust-parser.d.ts +11 -0
- package/build/src/frontends/rust-parser.d.ts.map +1 -0
- package/build/src/frontends/rust-parser.js +15 -0
- package/build/src/frontends/rust.d.ts +14 -0
- package/build/src/frontends/rust.d.ts.map +1 -0
- package/build/src/frontends/rust.js +715 -0
- package/build/src/frontends/scalars.d.ts +10 -0
- package/build/src/frontends/scalars.d.ts.map +1 -1
- package/build/src/frontends/scalars.js +28 -2
- package/build/src/frontends/swift.d.ts +10 -0
- package/build/src/frontends/swift.d.ts.map +1 -0
- package/build/src/frontends/swift.js +860 -0
- package/build/src/frontends/types.d.ts +186 -0
- package/build/src/frontends/types.d.ts.map +1 -0
- package/build/src/frontends/types.js +634 -0
- package/build/src/language-registry.d.ts +46 -4
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +177 -13
- package/build/src/mapping.d.ts +2 -2
- package/build/src/mapping.d.ts.map +1 -1
- package/build/src/mapping.js +31 -10
- package/build/src/semantic/capabilities.d.ts +66 -0
- package/build/src/semantic/capabilities.d.ts.map +1 -0
- package/build/src/semantic/capabilities.js +649 -0
- package/build/src/semantic/effects.d.ts +26 -0
- package/build/src/semantic/effects.d.ts.map +1 -0
- package/build/src/semantic/effects.js +764 -0
- package/build/src/semantic/generics.d.ts +23 -0
- package/build/src/semantic/generics.d.ts.map +1 -0
- package/build/src/semantic/generics.js +61 -0
- package/build/src/semantic/lifetime.d.ts +37 -0
- package/build/src/semantic/lifetime.d.ts.map +1 -0
- package/build/src/semantic/lifetime.js +527 -0
- package/build/src/semantic/provenance.d.ts +9 -2
- package/build/src/semantic/provenance.d.ts.map +1 -1
- package/build/src/semantic/provenance.js +462 -20
- package/build/src/semantic/scalars.d.ts +11 -0
- package/build/src/semantic/scalars.d.ts.map +1 -1
- package/build/src/semantic/scalars.js +16 -1
- package/build/src/semantic/stdlib.d.ts +254 -0
- package/build/src/semantic/stdlib.d.ts.map +1 -0
- package/build/src/semantic/stdlib.js +880 -0
- package/build/src/semantic/types.d.ts +3108 -178
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +730 -15
- package/build/src/semantic/validate.d.ts +85 -5
- package/build/src/semantic/validate.d.ts.map +1 -1
- package/build/src/semantic/validate.js +2576 -98
- package/build/src/stdlib-facades.d.ts +304 -0
- package/build/src/stdlib-facades.d.ts.map +1 -0
- package/build/src/stdlib-facades.js +1167 -0
- package/build/src/stdlib-negotiation.d.ts +69 -0
- package/build/src/stdlib-negotiation.d.ts.map +1 -0
- package/build/src/stdlib-negotiation.js +403 -0
- package/build/src/stdlib-providers.d.ts +72 -0
- package/build/src/stdlib-providers.d.ts.map +1 -0
- package/build/src/stdlib-providers.js +339 -0
- package/build/src/toolchains.d.ts +55 -1
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +15 -4
- package/docs/android.md +79 -0
- package/docs/architecture.md +47 -13
- package/docs/dart.md +60 -0
- package/docs/goals.md +3 -3
- package/docs/ios.md +121 -0
- package/docs/kotlin.md +42 -0
- package/docs/language-support.md +238 -26
- package/docs/multi-file-modules.md +52 -0
- package/docs/parser-qualification.md +121 -8
- package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
- package/docs/rust.md +88 -0
- package/docs/source-maps.md +17 -7
- package/docs/specification.md +5 -0
- package/docs/standard-library-portability.md +39 -8
- package/docs/swift.md +44 -0
- package/docs/testing.md +381 -4
- package/docs/webassembly.md +52 -0
- package/index.js +66 -8
- package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
- package/package.json +5 -2
- package/src/artifact-path.js +47 -2
- package/src/artifacts.js +67 -0
- package/src/backends/android.js +1370 -0
- package/src/backends/c-validation.js +6 -1
- package/src/backends/cpp-validation.js +6 -1
- package/src/backends/csharp.js +3 -0
- package/src/backends/dart-runtime.js +41 -0
- package/src/backends/dart.js +326 -0
- package/src/backends/effects.js +705 -0
- package/src/backends/go.js +14 -2
- package/src/backends/identifiers.js +166 -9
- package/src/backends/index.js +27 -2
- package/src/backends/ios.js +1612 -0
- package/src/backends/java.js +454 -36
- package/src/backends/javascript.js +389 -23
- package/src/backends/kotlin-runtime.js +29 -0
- package/src/backends/kotlin.js +144 -0
- package/src/backends/native-validation.js +1 -1
- package/src/backends/ordered-expressions.js +40 -6
- package/src/backends/php-stdlib-support.js +239 -0
- package/src/backends/php.js +469 -32
- package/src/backends/program.js +1408 -0
- package/src/backends/python.js +3 -0
- package/src/backends/ruby.js +326 -23
- package/src/backends/rust-runtime.js +34 -0
- package/src/backends/rust-validation.js +75 -0
- package/src/backends/rust.js +335 -0
- package/src/backends/scalars.js +141 -16
- package/src/backends/shared.js +2314 -115
- package/src/backends/stdlib-support.js +234 -0
- package/src/backends/swift-runtime.js +14 -0
- package/src/backends/swift.js +132 -0
- package/src/backends/typescript.js +349 -23
- package/src/backends/wasm.js +2208 -0
- package/src/backends/writer.js +545 -2
- package/src/diagnostic.js +4 -2
- package/src/frontends/c.js +4 -2
- package/src/frontends/cpp.js +4 -2
- package/src/frontends/csharp.js +4 -2
- package/src/frontends/dart.js +963 -0
- package/src/frontends/index.js +14 -4
- package/src/frontends/java.js +1977 -69
- package/src/frontends/javascript-typescript.js +2046 -102
- package/src/frontends/kotlin.js +713 -0
- package/src/frontends/php.js +1725 -79
- package/src/frontends/program.js +1062 -0
- package/src/frontends/ruby.js +1624 -98
- package/src/frontends/rust-parser.js +18 -0
- package/src/frontends/rust.js +714 -0
- package/src/frontends/scalars.js +31 -1
- package/src/frontends/swift.js +893 -0
- package/src/frontends/types.js +750 -0
- package/src/language-registry.js +182 -12
- package/src/mapping.js +33 -9
- package/src/semantic/capabilities.js +671 -0
- package/src/semantic/effects.js +737 -0
- package/src/semantic/generics.js +58 -0
- package/src/semantic/lifetime.js +517 -0
- package/src/semantic/provenance.js +412 -19
- package/src/semantic/scalars.js +17 -0
- package/src/semantic/stdlib.js +921 -0
- package/src/semantic/types.js +810 -14
- package/src/semantic/validate.js +2934 -209
- package/src/stdlib-facades.js +1211 -0
- package/src/stdlib-negotiation.js +446 -0
- package/src/stdlib-providers.js +377 -0
- package/src/toolchains.js +16 -3
package/src/backends/java.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
import {emitExpression} from "./shared.js"
|
|
4
|
-
import {
|
|
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
|
-
|
|
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(
|
|
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
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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
|
|
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.
|