semantifold 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -15
- package/build/index.d.ts +48 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +57 -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/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 +154 -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 +23 -0
- package/build/src/backends/kotlin.d.ts.map +1 -0
- package/build/src/backends/kotlin.js +136 -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 +81 -0
- package/build/src/backends/program.d.ts.map +1 -0
- package/build/src/backends/program.js +1308 -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 +2158 -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 +235 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +468 -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 +167 -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 +2952 -202
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +688 -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/architecture.md +45 -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 +231 -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 +15 -7
- package/docs/standard-library-portability.md +39 -8
- package/docs/swift.md +44 -0
- package/docs/testing.md +366 -4
- package/docs/webassembly.md +52 -0
- package/index.js +63 -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/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 +160 -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 +141 -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 +1407 -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 +2304 -124
- 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 +520 -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 +172 -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 +765 -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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
import {emitExpression, requiresCanonicalZeroRendering} from "./shared.js"
|
|
4
|
-
import {
|
|
3
|
+
import {emitExpression, emitType, requiresCanonicalZeroRendering} from "./shared.js"
|
|
4
|
+
import {emitEffectPrefixes, emitEffectSupport} from "./effects.js"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Emits an independently executable JavaScript program with JSDoc types.
|
|
@@ -11,33 +11,93 @@ import {emitScalarType} from "./scalars.js"
|
|
|
11
11
|
*/
|
|
12
12
|
export function generateJavaScript(module, writer) {
|
|
13
13
|
const canonicalizeZero = requiresCanonicalZeroRendering(module)
|
|
14
|
+
const records = module.records ?? []
|
|
15
|
+
const classes = module.classes ?? []
|
|
16
|
+
const errors = module.errors ?? []
|
|
17
|
+
|
|
18
|
+
emitProgramImports(module, writer)
|
|
19
|
+
emitEffectSupport(writer, module, "javascript")
|
|
20
|
+
|
|
21
|
+
errors.forEach((error, errorIndex) => {
|
|
22
|
+
const path = `/errors/${errorIndex}`
|
|
23
|
+
|
|
24
|
+
if (errorIndex > 0) writer.synthetic("\n\n", "error declaration separator", [error], [path])
|
|
25
|
+
if (writer.isDirectlyExported(error.id)) writer.synthetic("export ", "ESM error export", [error], [path])
|
|
26
|
+
writer.mapped("class", {mappingKind: "anchor", node: error, path})
|
|
27
|
+
writer.synthetic(" ", "error declaration spacing", [error], [path])
|
|
28
|
+
writer.mapped(error.name, {mappingKind: "exact", node: error, path, role: "name"})
|
|
29
|
+
writer.synthetic(" extends Error {}", "JavaScript unchecked error scaffolding", [error], [path])
|
|
30
|
+
})
|
|
31
|
+
if (errors.length > 0) writer.synthetic("\n\n", "error/declaration separator", [module])
|
|
32
|
+
|
|
33
|
+
records.forEach((record, recordIndex) => {
|
|
34
|
+
const recordPath = `/records/${recordIndex}`
|
|
35
|
+
|
|
36
|
+
if (recordIndex > 0) writer.synthetic("\n\n", "record declaration separator", [record], [recordPath])
|
|
37
|
+
emitTemplateDocumentation(writer, record.typeParameters ?? [], `${recordPath}/typeParameters`, "JavaScript")
|
|
38
|
+
if (writer.isDirectlyExported(record.id)) writer.synthetic("export ", "ESM record export", [record], [recordPath])
|
|
39
|
+
writer.mapped("class", {mappingKind: "anchor", node: record, path: recordPath})
|
|
40
|
+
writer.synthetic(" ", "record declaration spacing", [record], [recordPath])
|
|
41
|
+
writer.mapped(record.name, {mappingKind: "exact", node: record, path: recordPath, role: "name"})
|
|
42
|
+
writer.synthetic(" {\n /**\n", "JavaScript record constructor scaffolding", [record], [recordPath])
|
|
43
|
+
record.fields.forEach((field, fieldIndex) => {
|
|
44
|
+
const fieldPath = `${recordPath}/fields/${fieldIndex}`
|
|
45
|
+
|
|
46
|
+
writer.synthetic(" * @param {", "JavaScript record field type scaffolding", [field], [fieldPath])
|
|
47
|
+
emitType(writer, field.type, `${fieldPath}/type`, "javascript")
|
|
48
|
+
writer.synthetic("} ", "JavaScript record field type scaffolding", [field], [fieldPath])
|
|
49
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
50
|
+
writer.synthetic("\n", "line break", [field], [fieldPath])
|
|
51
|
+
})
|
|
52
|
+
writer.synthetic(" */\n constructor(", "JavaScript record constructor scaffolding", [record], [recordPath])
|
|
53
|
+
record.fields.forEach((field, fieldIndex) => {
|
|
54
|
+
if (fieldIndex) writer.synthetic(", ", "record field separator", [record], [recordPath])
|
|
55
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: `${recordPath}/fields/${fieldIndex}`, role: "name"})
|
|
56
|
+
})
|
|
57
|
+
writer.synthetic(") {\n", "JavaScript record constructor scaffolding", [record], [recordPath])
|
|
58
|
+
record.fields.forEach((field, fieldIndex) => {
|
|
59
|
+
const fieldPath = `${recordPath}/fields/${fieldIndex}`
|
|
60
|
+
|
|
61
|
+
writer.synthetic(" /** @readonly */\n this.", "JavaScript readonly field scaffolding", [field], [fieldPath])
|
|
62
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
63
|
+
writer.synthetic(" = ", "JavaScript record assignment scaffolding", [field], [fieldPath])
|
|
64
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
65
|
+
writer.synthetic(";\n", "JavaScript record assignment terminator", [field], [fieldPath])
|
|
66
|
+
})
|
|
67
|
+
writer.synthetic(" ({}).constructor.freeze(this)\n }\n}", "JavaScript record immutability scaffolding", [record], [recordPath])
|
|
68
|
+
})
|
|
69
|
+
if (records.length > 0) writer.synthetic("\n\n", "record/function separator", [module])
|
|
70
|
+
|
|
71
|
+
classes.forEach((declaration, classIndex) => {
|
|
72
|
+
if (classIndex > 0) writer.synthetic("\n\n", "reference class separator", [declaration], [`/classes/${classIndex}`])
|
|
73
|
+
emitReferenceClass(writer, declaration, classIndex, canonicalizeZero)
|
|
74
|
+
})
|
|
75
|
+
if (classes.length > 0) writer.synthetic("\n\n", "reference class/function separator", [module])
|
|
14
76
|
|
|
15
77
|
module.functions.forEach((declaration, functionIndex) => {
|
|
16
78
|
if (functionIndex > 0) writer.synthetic("\n\n", "declaration separator", [declaration])
|
|
17
79
|
|
|
18
80
|
writer.synthetic("/**\n * Generated semantic function.\n", "JavaScript type scaffolding", [declaration])
|
|
81
|
+
for (const [parameterIndex, parameter] of (declaration.typeParameters ?? []).entries()) {
|
|
82
|
+
writer.synthetic(" * @template ", "JavaScript type parameter scaffolding", [parameter], [`/functions/${functionIndex}/typeParameters/${parameterIndex}`])
|
|
83
|
+
writer.mapped(parameter.name, {
|
|
84
|
+
mappingKind: "exact", node: parameter, path: `/functions/${functionIndex}/typeParameters/${parameterIndex}`, role: "name"
|
|
85
|
+
})
|
|
86
|
+
writer.synthetic("\n", "line break", [parameter])
|
|
87
|
+
}
|
|
19
88
|
for (const [parameterIndex, parameter] of declaration.parameters.entries()) {
|
|
20
89
|
const parameterPath = `/functions/${functionIndex}/parameters/${parameterIndex}`
|
|
21
90
|
|
|
22
91
|
writer.synthetic(" * @param {", "JavaScript type scaffolding", [parameter], [parameterPath])
|
|
23
|
-
writer
|
|
24
|
-
mappingKind: "exact",
|
|
25
|
-
node: parameter.type,
|
|
26
|
-
path: `${parameterPath}/type`,
|
|
27
|
-
role: "type"
|
|
28
|
-
})
|
|
92
|
+
emitType(writer, parameter.type, `${parameterPath}/type`, "javascript")
|
|
29
93
|
writer.synthetic("} ", "JavaScript type scaffolding", [parameter], [parameterPath])
|
|
30
94
|
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: parameterPath, role: "name"})
|
|
31
95
|
writer.synthetic(" - Semantic parameter.\n", "JavaScript type scaffolding", [parameter], [parameterPath])
|
|
32
96
|
}
|
|
33
97
|
writer.synthetic(" * @returns {", "JavaScript type scaffolding", [declaration])
|
|
34
|
-
writer
|
|
35
|
-
mappingKind: "exact",
|
|
36
|
-
node: declaration.returnType,
|
|
37
|
-
path: `/functions/${functionIndex}/returnType`,
|
|
38
|
-
role: "type"
|
|
39
|
-
})
|
|
98
|
+
emitType(writer, declaration.returnType, `/functions/${functionIndex}/returnType`, "javascript")
|
|
40
99
|
writer.synthetic("} Semantic result.\n */\n", "JavaScript type scaffolding", [declaration])
|
|
100
|
+
if (writer.isDirectlyExported(declaration.id)) writer.synthetic("export ", "ESM function export", [declaration])
|
|
41
101
|
writer.mapped("function", {mappingKind: "anchor", node: declaration})
|
|
42
102
|
writer.synthetic(" ", "function spacing", [declaration])
|
|
43
103
|
writer.mapped(declaration.name, {mappingKind: "exact", node: declaration, role: "name"})
|
|
@@ -60,8 +120,203 @@ export function generateJavaScript(module, writer) {
|
|
|
60
120
|
writer.mapped("}", {mappingKind: "anchor", node: declaration})
|
|
61
121
|
})
|
|
62
122
|
|
|
63
|
-
|
|
64
|
-
|
|
123
|
+
emitAliasedExports(module, writer)
|
|
124
|
+
if (!writer.program || writer.isProgramEntry()) {
|
|
125
|
+
writer.synthetic("\n\n", "entry-point separator", [module.entryPoint])
|
|
126
|
+
emitBlock(writer, module.entryPoint.body, "", "/entryPoint/body", canonicalizeZero)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Emits one native JavaScript private-field reference class.
|
|
132
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
133
|
+
* @param {import("../semantic/types.js").ClassDeclaration} declaration - Reference class.
|
|
134
|
+
* @param {number} classIndex - Module class index.
|
|
135
|
+
* @param {boolean} canonicalizeZero - Whether scalar output canonicalizes zero.
|
|
136
|
+
* @returns {void}
|
|
137
|
+
*/
|
|
138
|
+
function emitReferenceClass(writer, declaration, classIndex, canonicalizeZero) {
|
|
139
|
+
const path = `/classes/${classIndex}`
|
|
140
|
+
|
|
141
|
+
writer.mapped("class", {mappingKind: "anchor", node: declaration, path})
|
|
142
|
+
writer.synthetic(" ", "reference class spacing", [declaration], [path])
|
|
143
|
+
writer.mapped(declaration.name, {mappingKind: "exact", node: declaration, path, role: "name"})
|
|
144
|
+
writer.synthetic(" {\n", "reference class open", [declaration], [path])
|
|
145
|
+
declaration.fields.forEach((field, index) => {
|
|
146
|
+
const fieldPath = `${path}/fields/${index}`
|
|
147
|
+
|
|
148
|
+
writer.synthetic(" /** @type {", "private field type scaffolding", [field], [fieldPath])
|
|
149
|
+
emitType(writer, field.type, `${fieldPath}/type`, "javascript")
|
|
150
|
+
writer.synthetic("} */\n #", "private field scaffolding", [field], [fieldPath])
|
|
151
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
152
|
+
writer.synthetic("\n", "line break", [field], [fieldPath])
|
|
153
|
+
})
|
|
154
|
+
const constructor = declaration.constructor
|
|
155
|
+
const constructorPath = `${path}/constructor`
|
|
156
|
+
|
|
157
|
+
emitJsdoc(writer, constructor.parameters, undefined, `${constructorPath}/parameters`, undefined)
|
|
158
|
+
writer.synthetic(" ", "constructor indentation", [constructor], [constructorPath])
|
|
159
|
+
writer.mapped("constructor", {mappingKind: "exact", node: constructor, path: constructorPath, role: "constructor"})
|
|
160
|
+
emitBareParameters(writer, constructor.parameters, `${constructorPath}/parameters`)
|
|
161
|
+
writer.synthetic(" {\n", "constructor open", [constructor], [constructorPath])
|
|
162
|
+
emitBlock(writer, constructor.body, " ", `${constructorPath}/body`, canonicalizeZero)
|
|
163
|
+
writer.synthetic(" }", "constructor close", [constructor], [constructorPath])
|
|
164
|
+
declaration.methods.forEach((method, index) => {
|
|
165
|
+
const methodPath = `${path}/methods/${index}`
|
|
166
|
+
|
|
167
|
+
writer.synthetic("\n\n", "method spacing", [method], [methodPath])
|
|
168
|
+
emitJsdoc(writer, method.parameters, method.returnType, `${methodPath}/parameters`, `${methodPath}/returnType`)
|
|
169
|
+
writer.synthetic(" ", "method indentation", [method], [methodPath])
|
|
170
|
+
writer.mapped(method.name, {mappingKind: "exact", node: method, path: methodPath, role: "name"})
|
|
171
|
+
emitBareParameters(writer, method.parameters, `${methodPath}/parameters`)
|
|
172
|
+
writer.synthetic(" {\n", "method open", [method], [methodPath])
|
|
173
|
+
emitBlock(writer, method.body, " ", `${methodPath}/body`, canonicalizeZero)
|
|
174
|
+
writer.synthetic(" }", "method close", [method], [methodPath])
|
|
175
|
+
})
|
|
176
|
+
writer.synthetic("\n", "line break", [declaration], [path])
|
|
177
|
+
writer.mapped("}", {mappingKind: "anchor", node: declaration, path})
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Emits exact JavaScript callable type documentation.
|
|
182
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
183
|
+
* @param {import("../semantic/types.js").Parameter[]} parameters - Ordered parameters.
|
|
184
|
+
* @param {import("../semantic/types.js").SemanticFunctionReturnType | undefined} returnType - Optional return type.
|
|
185
|
+
* @param {string} parameterPath - Parameter collection path.
|
|
186
|
+
* @param {string | undefined} returnPath - Return type path.
|
|
187
|
+
* @returns {void}
|
|
188
|
+
*/
|
|
189
|
+
function emitJsdoc(writer, parameters, returnType, parameterPath, returnPath) {
|
|
190
|
+
writer.synthetic("\n /**\n", "JavaScript callable documentation", parameters)
|
|
191
|
+
for (const [index, parameter] of parameters.entries()) {
|
|
192
|
+
writer.synthetic(" * @param {", "parameter type scaffolding", [parameter], [`${parameterPath}/${index}`])
|
|
193
|
+
emitType(writer, parameter.type, `${parameterPath}/${index}/type`, "javascript")
|
|
194
|
+
writer.synthetic("} ", "parameter documentation", [parameter], [`${parameterPath}/${index}`])
|
|
195
|
+
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: `${parameterPath}/${index}`, role: "name"})
|
|
196
|
+
writer.synthetic("\n", "line break", [parameter])
|
|
197
|
+
}
|
|
198
|
+
if (returnType && returnPath) {
|
|
199
|
+
writer.synthetic(" * @returns {", "return type scaffolding", [])
|
|
200
|
+
emitType(writer, returnType, returnPath, "javascript")
|
|
201
|
+
writer.synthetic("}\n", "line break", [])
|
|
202
|
+
}
|
|
203
|
+
writer.synthetic(" */\n", "JavaScript callable documentation close", parameters)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Emits one untyped JavaScript parameter list.
|
|
208
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
209
|
+
* @param {import("../semantic/types.js").Parameter[]} parameters - Ordered parameters.
|
|
210
|
+
* @param {string} path - Parameter collection path.
|
|
211
|
+
* @returns {void}
|
|
212
|
+
*/
|
|
213
|
+
function emitBareParameters(writer, parameters, path) {
|
|
214
|
+
writer.synthetic("(", "parameter list open", parameters)
|
|
215
|
+
parameters.forEach((parameter, index) => {
|
|
216
|
+
if (index) writer.synthetic(", ", "parameter separator", parameters)
|
|
217
|
+
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: `${path}/${index}`, role: "name"})
|
|
218
|
+
})
|
|
219
|
+
writer.synthetic(")", "parameter list close", parameters)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Emits a standalone JSDoc template block.
|
|
224
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
225
|
+
* @param {import("../semantic/types.js").TypeParameter[]} parameters - Ordered type parameters.
|
|
226
|
+
* @param {string} path - Type-parameter collection path.
|
|
227
|
+
* @param {string} target - Target label.
|
|
228
|
+
*/
|
|
229
|
+
function emitTemplateDocumentation(writer, parameters, path, target) {
|
|
230
|
+
if (parameters.length == 0) return
|
|
231
|
+
writer.synthetic("/**\n", `${target} type parameter scaffolding`, parameters)
|
|
232
|
+
parameters.forEach((parameter, index) => {
|
|
233
|
+
writer.synthetic(" * @template ", `${target} type parameter scaffolding`, [parameter], [`${path}/${index}`])
|
|
234
|
+
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: `${path}/${index}`, role: "name"})
|
|
235
|
+
writer.synthetic("\n", "line break", [parameter])
|
|
236
|
+
})
|
|
237
|
+
writer.synthetic(" */\n", `${target} type parameter scaffolding`, parameters)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Emits grouped named ESM imports for a program module.
|
|
242
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Current module.
|
|
243
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
244
|
+
*/
|
|
245
|
+
function emitProgramImports(module, writer) {
|
|
246
|
+
if (!writer.program) return
|
|
247
|
+
const imports = /** @type {import("../semantic/types.js").SemanticProgramModule} */ (/** @type {unknown} */ (module)).imports
|
|
248
|
+
const moduleIds = [...new Set(imports.map(({moduleId}) => moduleId))]
|
|
249
|
+
|
|
250
|
+
for (const moduleId of moduleIds) {
|
|
251
|
+
const selected = imports.filter((item) => item.moduleId == moduleId)
|
|
252
|
+
|
|
253
|
+
writer.synthetic("import {", "ESM import declaration", selected)
|
|
254
|
+
selected.forEach((item, index) => {
|
|
255
|
+
const itemPath = `/imports/${imports.indexOf(item)}`
|
|
256
|
+
const localName = writer.importNameFor(item)
|
|
257
|
+
|
|
258
|
+
if (index) writer.synthetic(", ", "ESM import separator", selected)
|
|
259
|
+
writer.mapped(item.importedName, {mappingKind: "exact", node: item, path: itemPath, role: "importedName"})
|
|
260
|
+
if (localName != item.importedName) {
|
|
261
|
+
writer.synthetic(" as ", "ESM import alias", [item], [itemPath])
|
|
262
|
+
writer.mapped(localName, {mappingKind: "exact", node: item, path: itemPath, role: "localName"})
|
|
263
|
+
}
|
|
264
|
+
})
|
|
265
|
+
writer.synthetic("} from ", "ESM import source", selected)
|
|
266
|
+
writer.mapped(JSON.stringify(writer.relativeModuleSpecifier(moduleId, ".js")), {
|
|
267
|
+
mappingKind: "anchor", node: selected[0], path: `/imports/${imports.indexOf(selected[0])}`, role: "path"
|
|
268
|
+
})
|
|
269
|
+
writer.synthetic("\n", "ESM import terminator", selected)
|
|
270
|
+
}
|
|
271
|
+
if (moduleIds.length > 0) writer.synthetic("\n", "ESM import separator", [module])
|
|
272
|
+
emitStdlibProviderImports(module, writer)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Emits the grouped named ESM import for one linked stdlib provider.
|
|
277
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Current module.
|
|
278
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
279
|
+
*/
|
|
280
|
+
export function emitStdlibProviderImports(module, writer) {
|
|
281
|
+
const names = writer.stdlibProviderImports
|
|
282
|
+
|
|
283
|
+
if (!writer.program || !names || names.length == 0) return
|
|
284
|
+
|
|
285
|
+
writer.synthetic("import {", "ESM stdlib provider import declaration", [module])
|
|
286
|
+
names.forEach((name, index) => {
|
|
287
|
+
if (index) writer.synthetic(", ", "ESM stdlib provider import separator", [module])
|
|
288
|
+
writer.synthetic(name, "ESM stdlib provider import name", [module])
|
|
289
|
+
})
|
|
290
|
+
writer.synthetic("} from ", "ESM stdlib provider import source", [module])
|
|
291
|
+
writer.synthetic(JSON.stringify(writer.stdlibProviderSpecifier(".js")), "ESM stdlib provider import path", [module])
|
|
292
|
+
writer.synthetic("\n", "ESM stdlib provider import terminator", [module])
|
|
293
|
+
writer.synthetic("\n", "ESM stdlib provider import separator", [module])
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Emits explicit ESM export clauses for source aliases.
|
|
298
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Current module.
|
|
299
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
300
|
+
*/
|
|
301
|
+
function emitAliasedExports(module, writer) {
|
|
302
|
+
if (!writer.program) return
|
|
303
|
+
const programModule = /** @type {import("../semantic/types.js").SemanticProgramModule} */ (/** @type {unknown} */ (module))
|
|
304
|
+
const aliases = programModule.exports.filter((item) => !writer.isDirectExport(item))
|
|
305
|
+
|
|
306
|
+
if (aliases.length == 0) return
|
|
307
|
+
writer.synthetic("\n\nexport {", "ESM aliased exports", [module])
|
|
308
|
+
aliases.forEach((item, index) => {
|
|
309
|
+
if (index) writer.synthetic(", ", "ESM export separator", [module])
|
|
310
|
+
const declaration = [...programModule.functions, ...programModule.records ?? [], ...programModule.errors ?? []].find(({id}) => id == item.declarationId)
|
|
311
|
+
|
|
312
|
+
if (!declaration) throw new RangeError(`Unknown exported declaration '${item.declarationId}'.`)
|
|
313
|
+
const exportPath = `/exports/${programModule.exports.indexOf(item)}`
|
|
314
|
+
|
|
315
|
+
writer.mapped(declaration.name, {mappingKind: "exact", name: declaration.name, node: item, path: exportPath, role: "localName"})
|
|
316
|
+
writer.synthetic(" as ", "ESM aliased export operator", [item], [exportPath])
|
|
317
|
+
writer.mapped(item.exportedName, {mappingKind: "exact", name: item.exportedName, node: item, path: exportPath, role: "exportedName"})
|
|
318
|
+
})
|
|
319
|
+
writer.synthetic("}", "ESM aliased export close", [module])
|
|
65
320
|
}
|
|
66
321
|
|
|
67
322
|
/**
|
|
@@ -89,12 +344,128 @@ function emitBlock(writer, block, indent, blockPath, canonicalizeZero) {
|
|
|
89
344
|
* @returns {void}
|
|
90
345
|
*/
|
|
91
346
|
function emitStatement(writer, statement, indent, path, canonicalizeZero) {
|
|
347
|
+
emitEffectPrefixes(writer, statement, indent, path, "javascript",
|
|
348
|
+
(expression, expressionPath) => emitExpression(writer, expression, expressionPath, "javascript", identity))
|
|
92
349
|
if (statement.kind == "LocalDeclaration" || statement.kind == "AssignmentStatement") return emitLocal(writer, statement, indent, path)
|
|
93
350
|
|
|
94
351
|
writer.synthetic(indent, "indentation", [statement], [path])
|
|
352
|
+
if (statement.kind == "PrivateFieldWriteStatement") {
|
|
353
|
+
emitExpression(writer, statement.receiver, `${path}/receiver`, "javascript", identity)
|
|
354
|
+
const field = writer.privateFieldForId(statement.field)
|
|
355
|
+
|
|
356
|
+
writer.mapped(`.#${field.name}`, {mappingKind: "exact", name: field.name, node: statement, path, role: "member"})
|
|
357
|
+
writer.synthetic(" = ", "private field assignment", [statement], [path])
|
|
358
|
+
emitExpression(writer, statement.expression, `${path}/expression`, "javascript", identity)
|
|
359
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
360
|
+
return
|
|
361
|
+
}
|
|
362
|
+
if (statement.kind == "BreakStatement" || statement.kind == "ContinueStatement") {
|
|
363
|
+
writer.mapped(statement.kind == "BreakStatement" ? "break" : "continue", {mappingKind: "exact", node: statement, path})
|
|
364
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
365
|
+
return
|
|
366
|
+
}
|
|
367
|
+
if (statement.kind == "WhileStatement") {
|
|
368
|
+
writer.mapped("while", {mappingKind: "exact", node: statement, path})
|
|
369
|
+
writer.synthetic(" (", "condition-controlled loop spacing", [statement], [path])
|
|
370
|
+
emitExpression(writer, statement.condition, `${path}/condition`, "javascript", identity)
|
|
371
|
+
writer.synthetic(") ", "condition-controlled loop spacing", [statement], [path])
|
|
372
|
+
writer.mapped("{", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
373
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
374
|
+
emitBlock(writer, statement.body, `${indent} `, `${path}/body`, canonicalizeZero)
|
|
375
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
376
|
+
writer.mapped("}", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
377
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
378
|
+
return
|
|
379
|
+
}
|
|
380
|
+
if (statement.kind == "ForEachStatement") {
|
|
381
|
+
writer.mapped("for", {mappingKind: "anchor", node: statement, path})
|
|
382
|
+
writer.synthetic(" (const ", "loop scaffolding", [statement], [path])
|
|
383
|
+
writer.mapped(statement.valueBinding.name, {
|
|
384
|
+
mappingKind: "exact", node: statement.valueBinding, path: `${path}/valueBinding`, role: "name"
|
|
385
|
+
})
|
|
386
|
+
writer.synthetic(" of ", "loop scaffolding", [statement], [path])
|
|
387
|
+
emitExpression(writer, statement.list, `${path}/list`, "javascript", identity)
|
|
388
|
+
writer.synthetic(") ", "loop scaffolding", [statement], [path])
|
|
389
|
+
writer.mapped("{", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
390
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
391
|
+
emitBlock(writer, statement.body, `${indent} `, `${path}/body`, canonicalizeZero)
|
|
392
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
393
|
+
writer.mapped("}", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
394
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
395
|
+
return
|
|
396
|
+
}
|
|
397
|
+
if (statement.kind == "ForEachMapStatement") {
|
|
398
|
+
writer.mapped("for", {mappingKind: "anchor", node: statement, path})
|
|
399
|
+
writer.synthetic(" (const [", "map loop scaffolding", [statement], [path])
|
|
400
|
+
writer.mapped(statement.keyBinding.name, {
|
|
401
|
+
mappingKind: "exact", node: statement.keyBinding, path: `${path}/keyBinding`, role: "name"
|
|
402
|
+
})
|
|
403
|
+
writer.synthetic(", ", "map iteration binding separator", [statement], [path])
|
|
404
|
+
writer.mapped(statement.valueBinding.name, {
|
|
405
|
+
mappingKind: "exact", node: statement.valueBinding, path: `${path}/valueBinding`, role: "name"
|
|
406
|
+
})
|
|
407
|
+
writer.synthetic("] of ", "map loop scaffolding", [statement], [path])
|
|
408
|
+
emitExpression(writer, statement.map, `${path}/map`, "javascript", identity)
|
|
409
|
+
writer.synthetic(") ", "map loop scaffolding", [statement], [path])
|
|
410
|
+
writer.mapped("{", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
411
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
412
|
+
emitBlock(writer, statement.body, `${indent} `, `${path}/body`, canonicalizeZero)
|
|
413
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
414
|
+
writer.mapped("}", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
415
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
416
|
+
return
|
|
417
|
+
}
|
|
418
|
+
if (statement.kind == "RaiseStatement") {
|
|
419
|
+
const type = statement.error.error
|
|
420
|
+
const error = writer.errorForId(type.declarationId)
|
|
421
|
+
|
|
422
|
+
writer.mapped("throw", {mappingKind: "anchor", node: statement, path})
|
|
423
|
+
writer.synthetic(" new ", "error construction scaffolding", [statement.error], [`${path}/error`])
|
|
424
|
+
writer.mapped(writer.errorNameForId(type.declarationId), {mappingKind: "exact", name: error.name, node: statement.error, path: `${path}/error`, role: "type"})
|
|
425
|
+
writer.synthetic("(", "error construction open", [statement.error], [`${path}/error`])
|
|
426
|
+
emitExpression(writer, statement.error.message, `${path}/error/message`, "javascript", identity)
|
|
427
|
+
writer.synthetic(")\n", "error construction close", [statement.error], [`${path}/error`])
|
|
428
|
+
return
|
|
429
|
+
}
|
|
430
|
+
if (statement.kind == "TryStatement") {
|
|
431
|
+
const caught = writer.errorForId(statement.catchType.declarationId)
|
|
432
|
+
const targetName = writer.errorNameForId(statement.catchType.declarationId)
|
|
433
|
+
|
|
434
|
+
writer.mapped("try", {mappingKind: "anchor", node: statement, path})
|
|
435
|
+
writer.synthetic(" ", "try spacing", [statement], [path])
|
|
436
|
+
writer.mapped("{", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
437
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
438
|
+
emitBlock(writer, statement.body, `${indent} `, `${path}/body`, canonicalizeZero)
|
|
439
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
440
|
+
writer.mapped("}", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
441
|
+
writer.synthetic(" ", "catch spacing", [statement], [path])
|
|
442
|
+
writer.mapped("catch", {mappingKind: "anchor", node: statement, path, role: "catch"})
|
|
443
|
+
writer.synthetic(" (", "catch binding scaffolding", [statement.catchBinding], [`${path}/catchBinding`])
|
|
444
|
+
writer.mapped(statement.catchBinding.name, {mappingKind: "exact", node: statement.catchBinding, path: `${path}/catchBinding`, role: "name"})
|
|
445
|
+
writer.synthetic(") {\n", "catch binding scaffolding", [statement.catchBinding], [`${path}/catchBinding`])
|
|
446
|
+
writer.synthetic(`${indent} if (!(`, "exact catch guard", [statement], [path])
|
|
447
|
+
writer.mapped(statement.catchBinding.name, {mappingKind: "exact", node: statement.catchBinding, path: `${path}/catchBinding`, role: "name"})
|
|
448
|
+
writer.synthetic(" instanceof ", "exact catch guard", [statement], [path])
|
|
449
|
+
writer.mapped(targetName, {mappingKind: "exact", name: caught.name, node: statement.catchType, path: `${path}/catchType`, role: "type"})
|
|
450
|
+
writer.synthetic(`)) {\n${indent} throw `, "unmatched error propagation", [statement], [path])
|
|
451
|
+
writer.mapped(statement.catchBinding.name, {mappingKind: "exact", node: statement.catchBinding, path: `${path}/catchBinding`, role: "name"})
|
|
452
|
+
writer.synthetic(`\n${indent} }\n`, "unmatched error propagation", [statement], [path])
|
|
453
|
+
emitBlock(writer, statement.catchBody, `${indent} `, `${path}/catchBody`, canonicalizeZero)
|
|
454
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
455
|
+
writer.mapped("}", {mappingKind: "anchor", node: statement.catchBody, path: `${path}/catchBody`})
|
|
456
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
457
|
+
return
|
|
458
|
+
}
|
|
95
459
|
if (statement.kind == "ReturnStatement") {
|
|
96
460
|
writer.mapped("return", {mappingKind: "anchor", node: statement, path})
|
|
97
|
-
|
|
461
|
+
if (statement.expression) {
|
|
462
|
+
writer.synthetic(" ", "return spacing", [statement], [path])
|
|
463
|
+
emitExpression(writer, statement.expression, `${path}/expression`, "javascript", identity)
|
|
464
|
+
}
|
|
465
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
466
|
+
return
|
|
467
|
+
}
|
|
468
|
+
if (statement.kind == "ExpressionStatement") {
|
|
98
469
|
emitExpression(writer, statement.expression, `${path}/expression`, "javascript", identity)
|
|
99
470
|
writer.synthetic("\n", "line break", [statement], [path])
|
|
100
471
|
return
|
|
@@ -156,12 +527,7 @@ function emitLocal(writer, statement, indent, statementPath) {
|
|
|
156
527
|
}
|
|
157
528
|
|
|
158
529
|
writer.synthetic("/** @type {", "JavaScript local type scaffolding", [statement], [statementPath])
|
|
159
|
-
writer
|
|
160
|
-
mappingKind: "exact",
|
|
161
|
-
node: statement.type,
|
|
162
|
-
path: `${statementPath}/type`,
|
|
163
|
-
role: "type"
|
|
164
|
-
})
|
|
530
|
+
emitType(writer, statement.type, `${statementPath}/type`, "javascript")
|
|
165
531
|
writer.synthetic("} */\n", "JavaScript local type scaffolding", [statement], [statementPath])
|
|
166
532
|
writer.synthetic(indent, "indentation", [statement], [statementPath])
|
|
167
533
|
writer.mapped(statement.mutable ? "let" : "const", {mappingKind: "anchor", node: statement, path: statementPath})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** Exact target-only checked arithmetic support for Semantifold safe integers. */
|
|
4
|
+
export const kotlinRuntime = `private const val SEMANTIFOLD_MAX_SAFE_INTEGER: Long = 9007199254740991L
|
|
5
|
+
private const val SEMANTIFOLD_MIN_SAFE_INTEGER: Long = -9007199254740991L
|
|
6
|
+
|
|
7
|
+
private fun semantifold_integer(value: Long): Long {
|
|
8
|
+
if (value < SEMANTIFOLD_MIN_SAFE_INTEGER || value > SEMANTIFOLD_MAX_SAFE_INTEGER) {
|
|
9
|
+
throw ArithmeticException("Semantifold safe integer overflow")
|
|
10
|
+
}
|
|
11
|
+
return value
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private fun semantifold_integer_add(left: Long, right: Long): Long {
|
|
15
|
+
return semantifold_integer(Math.addExact(left, right))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private fun semantifold_integer_subtract(left: Long, right: Long): Long {
|
|
19
|
+
return semantifold_integer(Math.subtractExact(left, right))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private fun semantifold_integer_multiply(left: Long, right: Long): Long {
|
|
23
|
+
return semantifold_integer(Math.multiplyExact(left, right))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private fun semantifold_integer_negate(value: Long): Long {
|
|
27
|
+
return semantifold_integer(Math.negateExact(value))
|
|
28
|
+
}
|
|
29
|
+
`
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import {emitExpression} from "./shared.js"
|
|
4
|
+
import {emitScalarType} from "./scalars.js"
|
|
5
|
+
import {kotlinRuntime} from "./kotlin-runtime.js"
|
|
6
|
+
|
|
7
|
+
export const kotlinArtifactMetadata = Object.freeze({
|
|
8
|
+
compiler: Object.freeze({
|
|
9
|
+
apiVersion: "2.4",
|
|
10
|
+
arguments: Object.freeze(["-language-version", "2.4", "-api-version", "2.4", "-jvm-target", "25", "-Werror",
|
|
11
|
+
"-include-runtime", "Program.kt", "-d", "Program.jar"]),
|
|
12
|
+
jvmTarget: "25",
|
|
13
|
+
languageVersion: "2.4",
|
|
14
|
+
output: "Program.jar",
|
|
15
|
+
toolchain: "kotlinc",
|
|
16
|
+
version: "2.4.20"
|
|
17
|
+
}),
|
|
18
|
+
run: Object.freeze({arguments: Object.freeze(["-jar", "Program.jar"]), toolchain: "java25", version: "25.0.4+7"})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Emits one deterministic Kotlin/JVM program through the source-aware writer.
|
|
23
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Validated semantic module.
|
|
24
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
25
|
+
*/
|
|
26
|
+
export function generateKotlin(module, writer) {
|
|
27
|
+
writer.synthetic(kotlinRuntime, "Checked Kotlin/JVM safe-integer support", [module], [""])
|
|
28
|
+
|
|
29
|
+
module.functions.forEach((declaration, functionIndex) => {
|
|
30
|
+
const path = `/functions/${functionIndex}`
|
|
31
|
+
|
|
32
|
+
writer.synthetic("\n", "declaration separator", [declaration], [path])
|
|
33
|
+
writer.mapped("fun", {mappingKind: "anchor", node: declaration, path})
|
|
34
|
+
writer.synthetic(" ", "declaration spacing", [declaration], [path])
|
|
35
|
+
writer.mapped(declaration.name, {mappingKind: "exact", node: declaration, path, role: "name"})
|
|
36
|
+
writer.synthetic("(", "function parameter scaffold", [declaration], [path])
|
|
37
|
+
declaration.parameters.forEach((parameter, parameterIndex) => {
|
|
38
|
+
const parameterPath = `${path}/parameters/${parameterIndex}`
|
|
39
|
+
|
|
40
|
+
if (parameterIndex) writer.synthetic(", ", "parameter separator", [parameter], [parameterPath])
|
|
41
|
+
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: parameterPath, role: "name"})
|
|
42
|
+
writer.synthetic(": ", "parameter annotation scaffold", [parameter], [parameterPath])
|
|
43
|
+
writer.mapped(emitScalarType("kotlin", parameter.type), {mappingKind: "exact", node: parameter.type,
|
|
44
|
+
path: `${parameterPath}/type`, role: "type"})
|
|
45
|
+
})
|
|
46
|
+
writer.synthetic("): ", "function return scaffold", [declaration], [path])
|
|
47
|
+
writer.mapped(emitScalarType("kotlin", declaration.returnType), {mappingKind: "exact", node: declaration.returnType,
|
|
48
|
+
path: `${path}/returnType`, role: "type"})
|
|
49
|
+
writer.synthetic(" {\n", "Kotlin function body scaffold", [declaration], [path])
|
|
50
|
+
emitBlock(writer, declaration.body, " ", `${path}/body`)
|
|
51
|
+
writer.synthetic("}\n", "Kotlin function body scaffold", [declaration], [path])
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
writer.synthetic("\nfun main() {\n", "Kotlin generated main scaffold", [module.entryPoint], ["/entryPoint"])
|
|
55
|
+
emitBlock(writer, module.entryPoint.body, " ", "/entryPoint/body")
|
|
56
|
+
writer.synthetic("}\n", "Kotlin generated main scaffold", [module.entryPoint], ["/entryPoint"])
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Emits one Kotlin statement block.
|
|
61
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
62
|
+
* @param {import("../semantic/types.js").Block} block - Semantic block.
|
|
63
|
+
* @param {string} indent - Current indentation.
|
|
64
|
+
* @param {string} path - Semantic block path.
|
|
65
|
+
* @returns {void}
|
|
66
|
+
*/
|
|
67
|
+
function emitBlock(writer, block, indent, path) {
|
|
68
|
+
block.statements.forEach((statement, index) => emitStatement(writer, statement, indent, `${path}/statements/${index}`))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Emits one Kotlin statement.
|
|
73
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
74
|
+
* @param {import("../semantic/types.js").Statement} statement - Semantic statement.
|
|
75
|
+
* @param {string} indent - Current indentation.
|
|
76
|
+
* @param {string} path - Semantic statement path.
|
|
77
|
+
* @returns {void}
|
|
78
|
+
*/
|
|
79
|
+
function emitStatement(writer, statement, indent, path) {
|
|
80
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
81
|
+
if (statement.kind == "LocalDeclaration") {
|
|
82
|
+
writer.mapped(statement.mutable ? "var" : "val", {mappingKind: "anchor", node: statement, path})
|
|
83
|
+
writer.synthetic(" ", "declaration spacing", [statement], [path])
|
|
84
|
+
writer.mapped(statement.name, {mappingKind: "exact", node: statement, path, role: "name"})
|
|
85
|
+
writer.synthetic(": ", "local annotation scaffold", [statement], [path])
|
|
86
|
+
writer.mapped(emitScalarType("kotlin", statement.type), {mappingKind: "exact", node: statement.type,
|
|
87
|
+
path: `${path}/type`, role: "type"})
|
|
88
|
+
writer.synthetic(" ", "assignment spacing", [statement], [path])
|
|
89
|
+
writer.mapped("=", {mappingKind: "exact", node: statement, path, role: "operator"})
|
|
90
|
+
writer.synthetic(" ", "assignment spacing", [statement], [path])
|
|
91
|
+
emitExpression(writer, statement.initializer, `${path}/initializer`, "kotlin", identity)
|
|
92
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
if (statement.kind == "AssignmentStatement") {
|
|
96
|
+
writer.mapped(statement.target.name, {mappingKind: "exact", node: statement.target, path: `${path}/target`, role: "name"})
|
|
97
|
+
writer.synthetic(" ", "assignment spacing", [statement], [path])
|
|
98
|
+
writer.mapped("=", {mappingKind: "exact", node: statement, path, role: "operator"})
|
|
99
|
+
writer.synthetic(" ", "assignment spacing", [statement], [path])
|
|
100
|
+
emitExpression(writer, statement.expression, `${path}/expression`, "kotlin", identity)
|
|
101
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
if (statement.kind == "ExpressionStatement") throw new TypeError("Kotlin Task 005 expression statement reached emission.")
|
|
105
|
+
if (statement.kind == "ReturnStatement") {
|
|
106
|
+
if (!statement.expression) throw new TypeError("Kotlin bare return reached emission.")
|
|
107
|
+
writer.mapped("return", {mappingKind: "anchor", node: statement, path})
|
|
108
|
+
writer.synthetic(" ", "return spacing", [statement], [path])
|
|
109
|
+
emitExpression(writer, statement.expression, `${path}/expression`, "kotlin", identity)
|
|
110
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
if (statement.kind == "PrintStatement") {
|
|
114
|
+
writer.synthetic("println(", "Kotlin println plumbing", [statement], [path])
|
|
115
|
+
emitExpression(writer, statement.expression, `${path}/expression`, "kotlin", identity)
|
|
116
|
+
writer.synthetic(")\n", "Kotlin println plumbing", [statement], [path])
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
if (statement.kind != "IfStatement") throw new TypeError("Unsupported Kotlin statement reached emission.")
|
|
120
|
+
writer.mapped("if", {mappingKind: "anchor", node: statement, path})
|
|
121
|
+
writer.synthetic(" (", "Kotlin conditional scaffold", [statement], [path])
|
|
122
|
+
emitExpression(writer, statement.condition, `${path}/condition`, "kotlin", identity)
|
|
123
|
+
writer.synthetic(") {\n", "Kotlin conditional scaffold", [statement.consequent], [`${path}/consequent`])
|
|
124
|
+
emitBlock(writer, statement.consequent, `${indent} `, `${path}/consequent`)
|
|
125
|
+
writer.synthetic(`${indent}}`, "Kotlin conditional scaffold", [statement.consequent], [`${path}/consequent`])
|
|
126
|
+
if (statement.alternate) {
|
|
127
|
+
writer.synthetic(" else {\n", "Kotlin alternate scaffold", [statement.alternate], [`${path}/alternate`])
|
|
128
|
+
emitBlock(writer, statement.alternate, `${indent} `, `${path}/alternate`)
|
|
129
|
+
writer.synthetic(`${indent}}`, "Kotlin alternate scaffold", [statement.alternate], [`${path}/alternate`])
|
|
130
|
+
}
|
|
131
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Preserves an emitted Kotlin identifier.
|
|
136
|
+
* @param {string} name - Identifier spelling.
|
|
137
|
+
* @returns {string} Unchanged spelling.
|
|
138
|
+
*/
|
|
139
|
+
function identity(name) {
|
|
140
|
+
return name
|
|
141
|
+
}
|
|
@@ -10,7 +10,7 @@ const semanticEdges = new Set(["functions", "entryPoint", "body", "parameters",
|
|
|
10
10
|
/**
|
|
11
11
|
* Bounds a native occurrence plan and rejects cycles before recursive shared validation.
|
|
12
12
|
* @param {unknown} module - Untrusted backend request.
|
|
13
|
-
* @param {"c" | "cpp"} [language] -
|
|
13
|
+
* @param {"c" | "cpp" | "kotlin" | "rust" | "swift" | "wasm"} [language] - Backend diagnostic language.
|
|
14
14
|
* @returns {void}
|
|
15
15
|
*/
|
|
16
16
|
export function validateNativeGraph(module, language = "c") {
|