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/writer.js
CHANGED
|
@@ -2,22 +2,138 @@
|
|
|
2
2
|
|
|
3
3
|
import {createGenerationIndex} from "../semantic/provenance.js"
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Collects every caller-controlled binding spelling before synthetic names are chosen.
|
|
7
|
+
* @param {unknown} root - Semantic graph.
|
|
8
|
+
* @returns {Set<string>} Used source names.
|
|
9
|
+
*/
|
|
10
|
+
function collectBindingNames(root) {
|
|
11
|
+
const names = new Set()
|
|
12
|
+
const pending = [root]
|
|
13
|
+
const seen = new Set()
|
|
14
|
+
|
|
15
|
+
while (pending.length > 0) {
|
|
16
|
+
const value = pending.pop()
|
|
17
|
+
if (!value || typeof value != "object" || seen.has(value)) continue
|
|
18
|
+
seen.add(value)
|
|
19
|
+
if (!Array.isArray(value) && typeof Reflect.get(value, "name") == "string") names.add(Reflect.get(value, "name"))
|
|
20
|
+
for (const child of Array.isArray(value) ? value : Object.values(value)) {
|
|
21
|
+
if (child && typeof child == "object") pending.push(child)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return names
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Converts a logical module identity to its canonical target type segment.
|
|
29
|
+
* @param {string} id - Logical module identity.
|
|
30
|
+
* @returns {string} Portable target class/module name.
|
|
31
|
+
*/
|
|
32
|
+
function moduleClassName(id) {
|
|
33
|
+
return id.split(/[._-]+/u).map((part) => `${part[0].toUpperCase()}${part.slice(1)}`).join("")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Looks up one declaration name in its owning program module.
|
|
38
|
+
* @param {Partial<import("../semantic/types.js").SemanticProgramModule>} module - Owning module.
|
|
39
|
+
* @param {string} declarationId - Stable declaration identity.
|
|
40
|
+
* @returns {string} Declaration name.
|
|
41
|
+
*/
|
|
42
|
+
function declarationName(module, declarationId) {
|
|
43
|
+
const declaration = [...module.functions ?? [], ...module.records ?? [], ...module.classes ?? [], ...module.errors ?? []]
|
|
44
|
+
.find(({id}) => id == declarationId)
|
|
45
|
+
|
|
46
|
+
if (!declaration) throw new RangeError(`Unknown program declaration '${declarationId}'.`)
|
|
47
|
+
|
|
48
|
+
return declaration.name
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Chooses an unqualified target binding without treating a source-profile qualifier as semantic identity.
|
|
53
|
+
* @param {import("../semantic/types.js").SemanticProgram} program - Owning program.
|
|
54
|
+
* @param {import("../semantic/types.js").SemanticProgramModule} module - Importing module.
|
|
55
|
+
* @param {import("../semantic/types.js").SemanticImport} imported - Resolved import.
|
|
56
|
+
* @returns {string} Target-local binding spelling.
|
|
57
|
+
*/
|
|
58
|
+
export function programImportName(program, module, imported) {
|
|
59
|
+
const source = program.sources.find(({filename}) => filename == module.sourceFilename)
|
|
60
|
+
|
|
61
|
+
if (!source) throw new RangeError(`Program module '${module.id}' has no registered source.`)
|
|
62
|
+
|
|
63
|
+
return source.language == "ruby" || source.language == "java" ? imported.importedName : imported.localName
|
|
64
|
+
}
|
|
65
|
+
|
|
5
66
|
/** Source-aware deterministic generated-output builder. */
|
|
6
67
|
export class SourceWriter {
|
|
7
68
|
/**
|
|
8
69
|
* Creates a source-aware writer.
|
|
9
70
|
* @param {object} options - Writer options.
|
|
10
71
|
* @param {string} options.filename - Output filename.
|
|
11
|
-
* @param {import("../semantic/types.js").
|
|
72
|
+
* @param {import("../semantic/types.js").GeneratedTextLanguage} options.language - Output text language.
|
|
12
73
|
* @param {import("../semantic/types.js").SemanticModule} options.module - Semantic module.
|
|
74
|
+
* @param {import("../semantic/types.js").SemanticProgram} [options.program] - Owning multi-file program.
|
|
75
|
+
* @param {Map<string, string>} [options.programPaths] - Planned artifact path by module identity.
|
|
13
76
|
* @param {{filename: string, content: string, language?: import("../semantic/types.js").SemanticLanguage}[]} [options.sources] - Caller-provided sources.
|
|
77
|
+
* @param {Record<string, string>} [options.stdlibProviderEntries] - Used operation to protected native entry for a linked stdlib provider.
|
|
78
|
+
* @param {string} [options.stdlibProviderPath] - Planned stdlib provider artifact path.
|
|
79
|
+
* @param {string[]} [options.stdlibProviderPaths] - Planned stdlib provider artifact paths.
|
|
80
|
+
* @param {string[]} [options.stdlibProviderImports] - Ordered provider names this module must import.
|
|
81
|
+
* @param {string} [options.stdlibProviderOwnerModule] - Java owner module identity hosting the shared support block and shims.
|
|
82
|
+
* @param {string[]} [options.stdlibProviderShims] - Java owner program-wide used operations exposed as public static shims.
|
|
83
|
+
* @param {(expression: import("../semantic/types.js").CallExpression) => string} [options.callNameResolver] - Target-container call spelling override.
|
|
84
|
+
* @param {string} [options.callArgumentSuffix] - Synthetic trailing argument for every semantic function call.
|
|
85
|
+
* @param {boolean} [options.methodStringEquality] - Emit string equality through the platform String method.
|
|
14
86
|
*/
|
|
15
|
-
constructor({filename, language, module, sources
|
|
87
|
+
constructor({callArgumentSuffix, callNameResolver, filename, language, methodStringEquality, module, program, programPaths, sources,
|
|
88
|
+
stdlibProviderEntries, stdlibProviderPath, stdlibProviderPaths, stdlibProviderImports, stdlibProviderOwnerModule,
|
|
89
|
+
stdlibProviderShims}) {
|
|
16
90
|
const index = createGenerationIndex(module, sources)
|
|
17
91
|
|
|
18
92
|
this.filename = filename
|
|
19
93
|
this.language = language
|
|
94
|
+
this.module = module
|
|
95
|
+
this.program = program
|
|
96
|
+
this.programPaths = programPaths
|
|
97
|
+
this.callArgumentSuffix = callArgumentSuffix
|
|
98
|
+
this.callNameResolver = callNameResolver
|
|
99
|
+
this.methodStringEquality = methodStringEquality ?? false
|
|
20
100
|
this.index = index
|
|
101
|
+
this.stdlibProviderEntries = stdlibProviderEntries
|
|
102
|
+
this.stdlibProviderPath = stdlibProviderPath
|
|
103
|
+
this.stdlibProviderPaths = stdlibProviderPaths ?? (stdlibProviderPath ? [stdlibProviderPath] : undefined)
|
|
104
|
+
this.stdlibProviderImports = stdlibProviderImports
|
|
105
|
+
this.stdlibProviderOwnerModule = stdlibProviderOwnerModule
|
|
106
|
+
this.stdlibProviderShims = stdlibProviderShims
|
|
107
|
+
const programRecords = program?.modules.flatMap((programModule) => programModule.records ?? []) ?? module.records ?? []
|
|
108
|
+
const programClasses = program?.modules.flatMap((programModule) => programModule.classes ?? []) ?? module.classes ?? []
|
|
109
|
+
const capabilityFailures = module.capabilities?.flatMap(({failures}) => failures) ?? []
|
|
110
|
+
const programErrors = program?.modules.flatMap((programModule) => [
|
|
111
|
+
...(programModule.errors ?? []),
|
|
112
|
+
...(programModule.capabilities?.flatMap(({failures}) => failures) ?? [])
|
|
113
|
+
]) ?? [...module.errors ?? [], ...capabilityFailures]
|
|
114
|
+
const programFunctions = program?.modules.flatMap((programModule) => programModule.functions) ?? module.functions
|
|
115
|
+
|
|
116
|
+
this.records = new Map(programRecords.map((record) => [record.id, record]))
|
|
117
|
+
this.classes = new Map(programClasses.map((declaration) => [declaration.id, declaration]))
|
|
118
|
+
this.errors = new Map(programErrors.map((error) => [error.id, error]))
|
|
119
|
+
this.resources = new Map((module.capabilities?.flatMap(({resources}) => resources) ?? []).map((resource) => [resource.id, resource]))
|
|
120
|
+
this.effectOperations = new Map((module.capabilities?.flatMap(({operations}) => operations) ?? []).map((operation) => [operation.id, operation]))
|
|
121
|
+
this.effectOperationModules = new Map((module.capabilities?.flatMap((capability) =>
|
|
122
|
+
capability.operations.map((operation) => [operation.id, capability.authorityId])) ?? []))
|
|
123
|
+
this.fields = new Map(programRecords.flatMap((record) => record.fields.map((field) => [field.id, field])))
|
|
124
|
+
this.fieldRecords = new Map(programRecords.flatMap((record) => record.fields.map((field) => [field.id, record])))
|
|
125
|
+
this.privateFields = new Map(programClasses.flatMap((declaration) => declaration.fields.map((field) => [field.id, field])))
|
|
126
|
+
this.methods = new Map(programClasses.flatMap((declaration) => declaration.methods.map((method) => [method.id, method])))
|
|
127
|
+
this.typeParameters = new Map([...programRecords, ...programFunctions].flatMap((declaration) =>
|
|
128
|
+
(declaration.typeParameters ?? []).map((parameter) => [parameter.id, parameter])))
|
|
129
|
+
this.referenceClassEmissionDepth = 0
|
|
130
|
+
/** @type {Map<string, import("../semantic/types.js").SemanticProgramModule>} */
|
|
131
|
+
this.declarationModules = new Map(program?.modules.flatMap((programModule) => [
|
|
132
|
+
...(programModule.records ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
|
|
133
|
+
...(programModule.classes ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
|
|
134
|
+
...(programModule.errors ?? []).map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule])),
|
|
135
|
+
...programModule.functions.map((declaration) => /** @type {const} */ ([/** @type {string} */ (declaration.id), programModule]))
|
|
136
|
+
]) ?? [])
|
|
21
137
|
/** @type {string[]} */
|
|
22
138
|
this.parts = []
|
|
23
139
|
/** @type {import("../semantic/types.js").SemantifoldMappingSpan[]} */
|
|
@@ -25,6 +141,65 @@ export class SourceWriter {
|
|
|
25
141
|
this.offset = 0
|
|
26
142
|
this.line = 1
|
|
27
143
|
this.column = 1
|
|
144
|
+
/** @type {Map<import("../semantic/types.js").Expression, string>} */
|
|
145
|
+
this.effectTemporaryNames = new Map()
|
|
146
|
+
/** @type {Map<import("../semantic/types.js").Expression, string>} */
|
|
147
|
+
this.effectReplacementNames = new Map()
|
|
148
|
+
/** @type {import("../semantic/types.js").Expression | undefined} */
|
|
149
|
+
this.effectDefinition = undefined
|
|
150
|
+
this.usedBindingNames = collectBindingNames(module)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Installs the effect expressions lowered immediately before the current statement.
|
|
155
|
+
* @param {import("../semantic/types.js").Expression[]} expressions - Ordered expressions.
|
|
156
|
+
* @returns {void}
|
|
157
|
+
*/
|
|
158
|
+
planEffectReplacements(expressions) {
|
|
159
|
+
this.effectReplacementNames = new Map(expressions.map((expression) => [expression, this.effectTemporaryName(expression)]))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Allocates a collision-safe name for one deterministic effect site.
|
|
164
|
+
* @param {import("../semantic/types.js").Expression} expression - Effectful expression.
|
|
165
|
+
* @returns {string} Stable temporary name.
|
|
166
|
+
*/
|
|
167
|
+
effectTemporaryName(expression) {
|
|
168
|
+
const known = this.effectTemporaryNames.get(expression)
|
|
169
|
+
if (known) return known
|
|
170
|
+
const site = typeof Reflect.get(expression, "effectSiteId") == "string"
|
|
171
|
+
? Reflect.get(expression, "effectSiteId").slice("effect:".length) : String(this.effectTemporaryNames.size)
|
|
172
|
+
let name = `__semantifold_effect_${site}`
|
|
173
|
+
|
|
174
|
+
while (this.usedBindingNames.has(name)) name = `${name}_`
|
|
175
|
+
this.usedBindingNames.add(name)
|
|
176
|
+
this.effectTemporaryNames.set(expression, name)
|
|
177
|
+
return name
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Returns the planned temporary replacement outside its own definition.
|
|
182
|
+
* @param {import("../semantic/types.js").Expression} expression - Candidate expression.
|
|
183
|
+
* @returns {string | undefined} Temporary name.
|
|
184
|
+
*/
|
|
185
|
+
effectReplacementName(expression) {
|
|
186
|
+
return this.effectDefinition === expression ? undefined : this.effectReplacementNames.get(expression)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Emits one effect definition without recursively replacing itself.
|
|
191
|
+
* @param {import("../semantic/types.js").Expression} expression - Defined expression.
|
|
192
|
+
* @param {() => void} emit - Target expression emitter.
|
|
193
|
+
* @returns {void}
|
|
194
|
+
*/
|
|
195
|
+
emitEffectDefinition(expression, emit) {
|
|
196
|
+
const previous = this.effectDefinition
|
|
197
|
+
this.effectDefinition = expression
|
|
198
|
+
try {
|
|
199
|
+
emit()
|
|
200
|
+
} finally {
|
|
201
|
+
this.effectDefinition = previous
|
|
202
|
+
}
|
|
28
203
|
}
|
|
29
204
|
|
|
30
205
|
/**
|
|
@@ -44,6 +219,374 @@ export class SourceWriter {
|
|
|
44
219
|
return this.index.recordFor(node).path
|
|
45
220
|
}
|
|
46
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Resolves a validated nominal declaration identity for target emission.
|
|
224
|
+
* @param {string} declarationId - Semantic record identity.
|
|
225
|
+
* @returns {import("../semantic/types.js").RecordDeclaration} Record declaration.
|
|
226
|
+
*/
|
|
227
|
+
recordForId(declarationId) {
|
|
228
|
+
const record = this.records.get(declarationId)
|
|
229
|
+
|
|
230
|
+
if (!record) throw new RangeError(`Unknown validated record identity '${declarationId}'.`)
|
|
231
|
+
|
|
232
|
+
return record
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Returns the target spelling for a nominal record identity.
|
|
237
|
+
* @param {string} declarationId - Stable record declaration identity.
|
|
238
|
+
* @param {boolean} [valuePosition] - Whether the binding must exist at runtime.
|
|
239
|
+
* @returns {string} Target record spelling.
|
|
240
|
+
*/
|
|
241
|
+
recordNameForId(declarationId, valuePosition = false) {
|
|
242
|
+
const record = this.recordForId(declarationId)
|
|
243
|
+
const owner = this.declarationModules.get(declarationId)
|
|
244
|
+
const imported = this.#programModule()?.imports.find((item) =>
|
|
245
|
+
item.declarationId == declarationId && (!valuePosition || !item.typeOnly))
|
|
246
|
+
|
|
247
|
+
if (this.program && owner && owner.id != Reflect.get(this.module, "id") && this.language == "ruby") {
|
|
248
|
+
return `${moduleClassName(owner.id)}::${record.name}`
|
|
249
|
+
}
|
|
250
|
+
if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
|
|
251
|
+
return this.importNameFor(imported)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return record.name
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Resolves one validated reference class.
|
|
259
|
+
* @param {string} declarationId - Stable class identity.
|
|
260
|
+
* @returns {import("../semantic/types.js").ClassDeclaration} Class declaration.
|
|
261
|
+
*/
|
|
262
|
+
classForId(declarationId) {
|
|
263
|
+
const declaration = this.classes.get(declarationId)
|
|
264
|
+
|
|
265
|
+
if (!declaration) throw new RangeError(`Unknown validated reference class identity '${declarationId}'.`)
|
|
266
|
+
|
|
267
|
+
return declaration
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Returns the target spelling of one reference class.
|
|
272
|
+
* @param {string} declarationId - Stable class identity.
|
|
273
|
+
* @returns {string} Target spelling.
|
|
274
|
+
*/
|
|
275
|
+
classNameForId(declarationId) {
|
|
276
|
+
const declaration = this.classForId(declarationId)
|
|
277
|
+
const imported = this.#programModule()?.imports.find((item) => item.declarationId == declarationId)
|
|
278
|
+
|
|
279
|
+
if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
|
|
280
|
+
return this.importNameFor(imported)
|
|
281
|
+
}
|
|
282
|
+
return declaration.name
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Resolves one validated owned-resource declaration.
|
|
287
|
+
* @param {string} resourceId - Stable resource identity.
|
|
288
|
+
* @returns {import("../semantic/types.js").EffectResourceDeclaration} Resource declaration.
|
|
289
|
+
*/
|
|
290
|
+
resourceForId(resourceId) {
|
|
291
|
+
const resource = this.resources.get(resourceId)
|
|
292
|
+
if (!resource) throw new RangeError(`Unknown validated resource identity '${resourceId}'.`)
|
|
293
|
+
return resource
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Resolves one validated capability operation declaration.
|
|
298
|
+
* @param {string} operationId - Stable operation identity.
|
|
299
|
+
* @returns {import("../semantic/types.js").EffectOperationDeclaration} Operation declaration.
|
|
300
|
+
*/
|
|
301
|
+
effectOperationForId(operationId) {
|
|
302
|
+
const operation = this.effectOperations.get(operationId)
|
|
303
|
+
if (!operation) throw new RangeError(`Unknown validated effect operation identity '${operationId}'.`)
|
|
304
|
+
return operation
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Resolves one validated private field.
|
|
309
|
+
* @param {string} fieldId - Stable private-field identity.
|
|
310
|
+
* @returns {import("../semantic/types.js").PrivateField} Field declaration.
|
|
311
|
+
*/
|
|
312
|
+
privateFieldForId(fieldId) {
|
|
313
|
+
const field = this.privateFields.get(fieldId)
|
|
314
|
+
|
|
315
|
+
if (!field) throw new RangeError(`Unknown validated private field identity '${fieldId}'.`)
|
|
316
|
+
|
|
317
|
+
return field
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Resolves one validated receiver method.
|
|
322
|
+
* @param {string} methodId - Stable method identity.
|
|
323
|
+
* @returns {import("../semantic/types.js").MethodDeclaration} Method declaration.
|
|
324
|
+
*/
|
|
325
|
+
methodForId(methodId) {
|
|
326
|
+
const method = this.methods.get(methodId)
|
|
327
|
+
|
|
328
|
+
if (!method) throw new RangeError(`Unknown validated method identity '${methodId}'.`)
|
|
329
|
+
|
|
330
|
+
return method
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Resolves one validated declaration-scoped type parameter.
|
|
335
|
+
* @param {string} parameterId - Stable type-parameter identity.
|
|
336
|
+
* @returns {import("../semantic/types.js").TypeParameter} Type parameter.
|
|
337
|
+
*/
|
|
338
|
+
typeParameterForId(parameterId) {
|
|
339
|
+
const parameter = this.typeParameters.get(parameterId)
|
|
340
|
+
|
|
341
|
+
if (!parameter) throw new RangeError(`Unknown validated type parameter identity '${parameterId}'.`)
|
|
342
|
+
|
|
343
|
+
return parameter
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Returns the validated nominal error declaration for an identity.
|
|
348
|
+
* @param {string} declarationId - Stable error identity.
|
|
349
|
+
* @returns {import("../semantic/types.js").ErrorDeclaration | import("../semantic/types.js").EffectFailureDeclaration} Error declaration.
|
|
350
|
+
*/
|
|
351
|
+
errorForId(declarationId) {
|
|
352
|
+
const error = this.errors.get(declarationId)
|
|
353
|
+
|
|
354
|
+
if (!error) throw new RangeError(`Unknown validated error identity '${declarationId}'.`)
|
|
355
|
+
|
|
356
|
+
return error
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Returns the target-visible spelling for one nominal error identity.
|
|
361
|
+
* @param {string} declarationId - Stable error identity.
|
|
362
|
+
* @returns {string} Target-visible name.
|
|
363
|
+
*/
|
|
364
|
+
errorNameForId(declarationId) {
|
|
365
|
+
const error = this.errorForId(declarationId)
|
|
366
|
+
const owner = this.declarationModules.get(declarationId)
|
|
367
|
+
const imported = this.#programModule()?.imports.find((item) => item.declarationId == declarationId)
|
|
368
|
+
|
|
369
|
+
if (this.program && owner && owner.id != Reflect.get(this.module, "id") && this.language == "ruby") {
|
|
370
|
+
return `${moduleClassName(owner.id)}::${error.name}`
|
|
371
|
+
}
|
|
372
|
+
if (imported && (this.language == "javascript" || this.language == "typescript" || this.language == "php")) {
|
|
373
|
+
return this.importNameFor(imported)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return owner ? error.name : this.capabilityNominalName(error.name)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Returns the target spelling for a nominal name owned by a compiler-authorized capability.
|
|
381
|
+
* PHP program entries live in a generated namespace while stdlib provider classes remain
|
|
382
|
+
* global, so PHP program mode fully qualifies capability names.
|
|
383
|
+
* @param {string} name - Declared nominal name.
|
|
384
|
+
* @returns {string} Target spelling.
|
|
385
|
+
*/
|
|
386
|
+
capabilityNominalName(name) {
|
|
387
|
+
return this.program && this.language == "php" ? `\\${name}` : name
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Returns the target spelling for a resolved function call.
|
|
392
|
+
* @param {import("../semantic/types.js").CallExpression} expression - Resolved call.
|
|
393
|
+
* @returns {string} Target call name.
|
|
394
|
+
*/
|
|
395
|
+
callNameFor(expression) {
|
|
396
|
+
if (this.callNameResolver) return this.callNameResolver(expression)
|
|
397
|
+
const declarationId = expression.resolution?.declarationId
|
|
398
|
+
const owner = declarationId ? this.declarationModules.get(declarationId) : undefined
|
|
399
|
+
const imported = declarationId ? this.#programModule()?.imports.find((item) => item.declarationId == declarationId) : undefined
|
|
400
|
+
|
|
401
|
+
if (this.language == "java" && !this.program && this.referenceClassEmissionDepth > 0) return `Main.${expression.callee}`
|
|
402
|
+
if (!declarationId || !this.program || !owner || owner.id == Reflect.get(this.module, "id")) return expression.callee
|
|
403
|
+
if (this.language == "ruby" || this.language == "java") return `${moduleClassName(owner.id)}.${declarationName(owner, declarationId)}`
|
|
404
|
+
if (imported) return this.importNameFor(imported)
|
|
405
|
+
|
|
406
|
+
return declarationName(owner, declarationId)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Returns a target-container trailing argument for a semantic call.
|
|
411
|
+
* @param {import("../semantic/types.js").CallExpression} _expression - Resolved semantic call.
|
|
412
|
+
* @returns {string | undefined} Synthetic argument spelling, when configured.
|
|
413
|
+
*/
|
|
414
|
+
callArgumentSuffixFor(_expression) {
|
|
415
|
+
return this.callArgumentSuffix
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Reports whether string equality must avoid a target runtime helper.
|
|
420
|
+
* @returns {boolean} Whether to emit the platform String method.
|
|
421
|
+
*/
|
|
422
|
+
usesMethodStringEquality() {
|
|
423
|
+
return this.methodStringEquality
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/** Marks emission as occurring inside one top-level reference class. */
|
|
427
|
+
beginReferenceClassEmission() {
|
|
428
|
+
this.referenceClassEmissionDepth += 1
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** Ends one balanced top-level reference-class emission scope. */
|
|
432
|
+
endReferenceClassEmission() {
|
|
433
|
+
if (this.referenceClassEmissionDepth == 0) throw new RangeError("Reference-class emission scope is not active.")
|
|
434
|
+
this.referenceClassEmissionDepth -= 1
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Returns the target-local binding for one resolved import.
|
|
439
|
+
* @param {import("../semantic/types.js").SemanticImport} imported - Resolved import.
|
|
440
|
+
* @returns {string} Emitted import name.
|
|
441
|
+
*/
|
|
442
|
+
importNameFor(imported) {
|
|
443
|
+
const module = this.#programModule()
|
|
444
|
+
|
|
445
|
+
if (!this.program || !module) throw new RangeError("Import names require a validated semantic program.")
|
|
446
|
+
|
|
447
|
+
return programImportName(this.program, module, imported)
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Reports whether one local declaration is exported by the current program module.
|
|
452
|
+
* @param {string | undefined} declarationId - Declaration identity.
|
|
453
|
+
* @returns {boolean} Whether it has a same-name program export.
|
|
454
|
+
*/
|
|
455
|
+
isDirectlyExported(declarationId) {
|
|
456
|
+
const module = /** @type {Partial<import("../semantic/types.js").SemanticProgramModule>} */ (this.module)
|
|
457
|
+
|
|
458
|
+
return typeof declarationId == "string" && Boolean(module.exports?.some((item) =>
|
|
459
|
+
item.declarationId == declarationId && item.exportedName == declarationName(module, declarationId)))
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Reports whether one export edge uses its declaration's emitted name.
|
|
464
|
+
* @param {import("../semantic/types.js").SemanticExport} exported - Current export edge.
|
|
465
|
+
* @returns {boolean} Whether this edge is represented by the declaration prefix.
|
|
466
|
+
*/
|
|
467
|
+
isDirectExport(exported) {
|
|
468
|
+
return exported.exportedName == declarationName(this.module, exported.declarationId)
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Reports whether one local declaration has any public program export.
|
|
473
|
+
* @param {string | undefined} declarationId - Declaration identity.
|
|
474
|
+
* @returns {boolean} Whether the declaration is exported.
|
|
475
|
+
*/
|
|
476
|
+
isExported(declarationId) {
|
|
477
|
+
const module = /** @type {Partial<import("../semantic/types.js").SemanticProgramModule>} */ (this.module)
|
|
478
|
+
|
|
479
|
+
return typeof declarationId == "string" && Boolean(module.exports?.some((item) => item.declarationId == declarationId))
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Returns whether this is the selected program entry module.
|
|
484
|
+
* @returns {boolean} Whether this writer owns the selected entry.
|
|
485
|
+
*/
|
|
486
|
+
isProgramEntry() {
|
|
487
|
+
return this.program?.entryModule == Reflect.get(this.module, "id")
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Returns the canonical class/module segment for a logical module identity.
|
|
492
|
+
* @param {string} moduleId - Logical module identity.
|
|
493
|
+
* @returns {string} Target class/module name.
|
|
494
|
+
*/
|
|
495
|
+
programModuleName(moduleId) {
|
|
496
|
+
if (!this.program?.modules.some(({id}) => id == moduleId)) throw new RangeError(`Unknown program module '${moduleId}'.`)
|
|
497
|
+
|
|
498
|
+
return moduleClassName(moduleId)
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Finds the current module in the complete program.
|
|
503
|
+
* @returns {import("../semantic/types.js").SemanticProgramModule | undefined} Current program module.
|
|
504
|
+
*/
|
|
505
|
+
#programModule() {
|
|
506
|
+
if (!this.program) return undefined
|
|
507
|
+
|
|
508
|
+
return this.program.modules.find(({id}) => id == Reflect.get(this.module, "id"))
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Returns a relative ESM/require specifier for a planned dependency artifact.
|
|
513
|
+
* @param {string} moduleId - Dependency module identity.
|
|
514
|
+
* @param {string} [extension] - Optional replacement extension.
|
|
515
|
+
* @returns {string} Relative POSIX specifier.
|
|
516
|
+
*/
|
|
517
|
+
relativeModuleSpecifier(moduleId, extension) {
|
|
518
|
+
const targetPath = this.programPaths?.get(moduleId)
|
|
519
|
+
|
|
520
|
+
if (!targetPath) throw new RangeError(`Unknown planned module path '${moduleId}'.`)
|
|
521
|
+
const adjustedTarget = extension ? targetPath.replace(/\.[^./]+$/u, extension) : targetPath
|
|
522
|
+
const from = this.filename.split("/").slice(0, -1)
|
|
523
|
+
const to = adjustedTarget.split("/")
|
|
524
|
+
let common = 0
|
|
525
|
+
|
|
526
|
+
while (common < from.length && common < to.length && from[common] == to[common]) common++
|
|
527
|
+
const relative = [...from.slice(common).map(() => ".."), ...to.slice(common)].join("/")
|
|
528
|
+
|
|
529
|
+
return relative.startsWith(".") ? relative : `./${relative}`
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Returns the protected native entry for one used stdlib provider operation.
|
|
534
|
+
* @param {import("../semantic/types.js").EffectOperationDeclaration} operation - Canonical operation declaration.
|
|
535
|
+
* @returns {string | undefined} Linked protected entry, or undefined when the operation stays inlined.
|
|
536
|
+
*/
|
|
537
|
+
stdlibProviderEntryFor(operation) {
|
|
538
|
+
const module = this.effectOperationModules.get(operation.id)
|
|
539
|
+
|
|
540
|
+
return module === undefined ? undefined : this.stdlibProviderEntries?.[`${module}\u0000${operation.name}`]
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Returns a relative specifier for the planned stdlib provider artifact.
|
|
545
|
+
* @param {string} [extension] - Optional replacement extension.
|
|
546
|
+
* @param {string} [providerPath] - One selected provider artifact path.
|
|
547
|
+
* @returns {string} Relative POSIX specifier.
|
|
548
|
+
*/
|
|
549
|
+
stdlibProviderSpecifier(extension, providerPath) {
|
|
550
|
+
const targetPath = providerPath ?? this.stdlibProviderPath ?? this.stdlibProviderPaths?.[0]
|
|
551
|
+
|
|
552
|
+
if (!targetPath) throw new RangeError("A stdlib provider specifier requires a planned provider path.")
|
|
553
|
+
const adjustedTarget = extension ? targetPath.replace(/\.[^./]+$/u, extension) : targetPath
|
|
554
|
+
const from = this.filename.split("/").slice(0, -1)
|
|
555
|
+
const to = adjustedTarget.split("/")
|
|
556
|
+
let common = 0
|
|
557
|
+
|
|
558
|
+
while (common < from.length && common < to.length && from[common] == to[common]) common++
|
|
559
|
+
const relative = [...from.slice(common).map(() => ".."), ...to.slice(common)].join("/")
|
|
560
|
+
|
|
561
|
+
return relative.startsWith(".") ? relative : `./${relative}`
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Resolves a validated field identity for target emission.
|
|
566
|
+
* @param {string} fieldId - Semantic field identity.
|
|
567
|
+
* @returns {import("../semantic/types.js").RecordField} Record field.
|
|
568
|
+
*/
|
|
569
|
+
fieldForId(fieldId) {
|
|
570
|
+
const field = this.fields.get(fieldId)
|
|
571
|
+
|
|
572
|
+
if (!field) throw new RangeError(`Unknown validated field identity '${fieldId}'.`)
|
|
573
|
+
|
|
574
|
+
return field
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Resolves the record declaration that owns a validated field identity.
|
|
579
|
+
* @param {string} fieldId - Semantic field identity.
|
|
580
|
+
* @returns {import("../semantic/types.js").RecordDeclaration} Owning record.
|
|
581
|
+
*/
|
|
582
|
+
recordForFieldId(fieldId) {
|
|
583
|
+
const record = this.fieldRecords.get(fieldId)
|
|
584
|
+
|
|
585
|
+
if (!record) throw new RangeError(`Unknown validated field identity '${fieldId}'.`)
|
|
586
|
+
|
|
587
|
+
return record
|
|
588
|
+
}
|
|
589
|
+
|
|
47
590
|
/**
|
|
48
591
|
* Reports whether an exact parser-owned role range is available.
|
|
49
592
|
* @param {import("../semantic/types.js").SemanticNode} node - Semantic node occurrence.
|
package/src/diagnostic.js
CHANGED
|
@@ -45,15 +45,17 @@ export class SemantifoldDiagnostic extends Error {
|
|
|
45
45
|
* Throws a normalized parser diagnostic while preserving the parser error.
|
|
46
46
|
* @param {import("./semantic/types.js").SemanticLanguage} language - Frontend language.
|
|
47
47
|
* @param {unknown} error - Opaque parser error, narrowed immediately.
|
|
48
|
+
* @param {import("./semantic/types.js").SourceLocation | undefined} [location] - Normalized parser failure range.
|
|
48
49
|
* @returns {never} Always throws.
|
|
49
50
|
*/
|
|
50
|
-
export function parseFailure(language, error) {
|
|
51
|
+
export function parseFailure(language, error, location) {
|
|
51
52
|
const cause = error instanceof Error ? error : new Error(String(error))
|
|
52
53
|
|
|
53
54
|
throw new SemantifoldDiagnostic({
|
|
54
55
|
cause,
|
|
55
56
|
code: "PARSE_ERROR",
|
|
56
57
|
language,
|
|
58
|
+
location,
|
|
57
59
|
message: cause.message
|
|
58
60
|
})
|
|
59
61
|
}
|
|
@@ -104,7 +106,7 @@ export function semanticFailure(language, code, detail, location) {
|
|
|
104
106
|
|
|
105
107
|
/**
|
|
106
108
|
* Throws an unsupported backend-capability diagnostic.
|
|
107
|
-
* @param {import("./semantic/types.js").
|
|
109
|
+
* @param {import("./semantic/types.js").BackendLanguage} language - Backend language or binary target.
|
|
108
110
|
* @param {string} capability - Unsupported semantic capability.
|
|
109
111
|
* @param {import("./semantic/types.js").SourceLocation | undefined} location - Semantic source location.
|
|
110
112
|
* @returns {never} Always throws.
|
package/src/frontends/c.js
CHANGED
|
@@ -553,7 +553,8 @@ export class CReader {
|
|
|
553
553
|
const bindings = new Map(inherited)
|
|
554
554
|
|
|
555
555
|
for (const statement of block.statements) {
|
|
556
|
-
if (statement.kind == "LocalDeclaration") bindings.set(statement.name,
|
|
556
|
+
if (statement.kind == "LocalDeclaration") bindings.set(statement.name,
|
|
557
|
+
/** @type {import("../semantic/types.js").TypeReference} */ (statement.type).name)
|
|
557
558
|
if (statement.kind == "PrintStatement") {
|
|
558
559
|
const expected = this.printTypes.get(statement)
|
|
559
560
|
|
|
@@ -567,7 +568,8 @@ export class CReader {
|
|
|
567
568
|
}
|
|
568
569
|
}
|
|
569
570
|
|
|
570
|
-
for (const declaration of module.functions) visit(declaration.body, new Map(declaration.parameters.map((parameter) => [parameter.name,
|
|
571
|
+
for (const declaration of module.functions) visit(declaration.body, new Map(declaration.parameters.map((parameter) => [parameter.name,
|
|
572
|
+
/** @type {import("../semantic/types.js").TypeReference} */ (parameter.type).name])))
|
|
571
573
|
visit(module.entryPoint.body, new Map())
|
|
572
574
|
}
|
|
573
575
|
|
package/src/frontends/cpp.js
CHANGED
|
@@ -585,7 +585,8 @@ export class CppReader {
|
|
|
585
585
|
const bindings = new Map(inherited)
|
|
586
586
|
|
|
587
587
|
for (const statement of block.statements) {
|
|
588
|
-
if (statement.kind == "LocalDeclaration") bindings.set(statement.name,
|
|
588
|
+
if (statement.kind == "LocalDeclaration") bindings.set(statement.name,
|
|
589
|
+
/** @type {import("../semantic/types.js").TypeReference} */ (statement.type).name)
|
|
589
590
|
if (statement.kind == "PrintStatement") {
|
|
590
591
|
const expected = this.printTypes.get(statement)
|
|
591
592
|
|
|
@@ -599,7 +600,8 @@ export class CppReader {
|
|
|
599
600
|
}
|
|
600
601
|
}
|
|
601
602
|
|
|
602
|
-
for (const declaration of module.functions) visit(declaration.body, new Map(declaration.parameters.map((parameter) => [parameter.name,
|
|
603
|
+
for (const declaration of module.functions) visit(declaration.body, new Map(declaration.parameters.map((parameter) => [parameter.name,
|
|
604
|
+
/** @type {import("../semantic/types.js").TypeReference} */ (parameter.type).name])))
|
|
603
605
|
visit(module.entryPoint.body, new Map())
|
|
604
606
|
}
|
|
605
607
|
|
package/src/frontends/csharp.js
CHANGED
|
@@ -663,9 +663,11 @@ function validateCheckedArithmetic(module) {
|
|
|
663
663
|
*/
|
|
664
664
|
const visitBlock = (block) => block.statements.forEach((statement) => {
|
|
665
665
|
if (statement.kind == "LocalDeclaration") visitExpression(statement.initializer)
|
|
666
|
-
else if (statement.kind == "AssignmentStatement" || statement.kind == "
|
|
666
|
+
else if (statement.kind == "AssignmentStatement" || statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement") {
|
|
667
667
|
visitExpression(statement.expression)
|
|
668
|
-
} else {
|
|
668
|
+
} else if (statement.kind == "ReturnStatement") {
|
|
669
|
+
if (statement.expression) visitExpression(statement.expression)
|
|
670
|
+
} else if (statement.kind == "IfStatement") {
|
|
669
671
|
visitExpression(statement.condition)
|
|
670
672
|
visitBlock(statement.consequent)
|
|
671
673
|
if (statement.alternate) visitBlock(statement.alternate)
|