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
package/src/backends/python.js
CHANGED
|
@@ -81,15 +81,18 @@ function emitStatement(writer, statement, indent, path) {
|
|
|
81
81
|
emitIf(writer, statement, indent, path, "if")
|
|
82
82
|
return
|
|
83
83
|
}
|
|
84
|
+
if (statement.kind == "ExpressionStatement") throw new TypeError("Python Task 005 expression statement reached emission.")
|
|
84
85
|
|
|
85
86
|
writer.synthetic(indent, "indentation", [statement], [path])
|
|
86
87
|
if (statement.kind == "ReturnStatement") {
|
|
88
|
+
if (!statement.expression) throw new TypeError("Python bare return reached emission.")
|
|
87
89
|
writer.mapped("return", {mappingKind: "anchor", node: statement, path})
|
|
88
90
|
writer.synthetic(" ", "return spacing", [statement], [path])
|
|
89
91
|
emitExpression(writer, statement.expression, `${path}/expression`, "python", identity)
|
|
90
92
|
writer.synthetic("\n", "line break", [statement], [path])
|
|
91
93
|
return
|
|
92
94
|
}
|
|
95
|
+
if (statement.kind != "PrintStatement") throw new TypeError("Unsupported Python statement reached emission.")
|
|
93
96
|
|
|
94
97
|
writer.mapped("print", {mappingKind: "anchor", node: statement, path})
|
|
95
98
|
writer.mapped("(", {mappingKind: "anchor", node: statement, path})
|
package/src/backends/ruby.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
import {emitExpression} from "./shared.js"
|
|
4
|
-
import {
|
|
3
|
+
import {emitExpression, emitType} from "./shared.js"
|
|
4
|
+
import {emitEffectPrefixes, emitEffectSupport} from "./effects.js"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Emits an independently executable Ruby program through the source-aware writer.
|
|
@@ -10,30 +10,116 @@ import {emitScalarType} from "./scalars.js"
|
|
|
10
10
|
* @returns {void}
|
|
11
11
|
*/
|
|
12
12
|
export function generateRuby(module, writer) {
|
|
13
|
+
const records = module.records ?? []
|
|
14
|
+
const classes = module.classes ?? []
|
|
15
|
+
const errors = module.errors ?? []
|
|
16
|
+
|
|
17
|
+
if (writer.program) {
|
|
18
|
+
const programModule = /** @type {import("../semantic/types.js").SemanticProgramModule} */ (/** @type {unknown} */ (module))
|
|
19
|
+
|
|
20
|
+
for (const moduleId of [...new Set(programModule.imports.map((item) => item.moduleId))]) {
|
|
21
|
+
const relative = writer.relativeModuleSpecifier(moduleId).replace(/\.rb$/u, "").replace(/^\.\//u, "")
|
|
22
|
+
const imported = /** @type {import("../semantic/types.js").SemanticImport} */ (
|
|
23
|
+
programModule.imports.find((item) => item.moduleId == moduleId))
|
|
24
|
+
const importPath = `/imports/${programModule.imports.indexOf(imported)}`
|
|
25
|
+
|
|
26
|
+
writer.synthetic("require_relative ", "Ruby require-relative edge", [imported], [importPath])
|
|
27
|
+
writer.mapped(JSON.stringify(relative), {mappingKind: "anchor", node: imported, path: importPath, role: "path"})
|
|
28
|
+
writer.synthetic("\n", "Ruby require-relative terminator", [imported], [importPath])
|
|
29
|
+
}
|
|
30
|
+
if (programModule.imports.length > 0) writer.synthetic("\n", "Ruby require/module separator", [module])
|
|
31
|
+
if (writer.stdlibProviderEntries) {
|
|
32
|
+
const relative = writer.stdlibProviderSpecifier().replace(/\.rb$/u, "").replace(/^\.\//u, "")
|
|
33
|
+
|
|
34
|
+
writer.synthetic("require_relative ", "Ruby stdlib provider require-relative edge", [module])
|
|
35
|
+
writer.synthetic(JSON.stringify(relative), "Ruby stdlib provider require-relative path", [module])
|
|
36
|
+
writer.synthetic("\n", "Ruby stdlib provider require-relative terminator", [module])
|
|
37
|
+
writer.synthetic("\n", "Ruby stdlib provider require separator", [module])
|
|
38
|
+
}
|
|
39
|
+
writer.synthetic(`module ${writer.programModuleName(programModule.id)}\n`, "Ruby semantic module wrapper", [module])
|
|
40
|
+
if (module.functions.length > 0) writer.synthetic("module_function\n\n", "Ruby module-function profile", [module])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
emitEffectSupport(writer, module, "ruby")
|
|
44
|
+
errors.forEach((error, index) => {
|
|
45
|
+
const path = `/errors/${index}`
|
|
46
|
+
|
|
47
|
+
if (index > 0) writer.synthetic("\n\n", "error declaration separator", [error], [path])
|
|
48
|
+
writer.mapped("class", {mappingKind: "anchor", node: error, path})
|
|
49
|
+
writer.synthetic(" ", "error declaration spacing", [error], [path])
|
|
50
|
+
writer.mapped(error.name, {mappingKind: "exact", node: error, path, role: "name"})
|
|
51
|
+
writer.synthetic(" < StandardError\nend", "Ruby unchecked error scaffolding", [error], [path])
|
|
52
|
+
})
|
|
53
|
+
if (errors.length > 0) writer.synthetic("\n\n", "error/declaration separator", [module])
|
|
54
|
+
|
|
55
|
+
records.forEach((record, recordIndex) => {
|
|
56
|
+
const recordPath = `/records/${recordIndex}`
|
|
57
|
+
|
|
58
|
+
if (recordIndex > 0) writer.synthetic("\n\n", "record declaration separator", [record], [recordPath])
|
|
59
|
+
emitTemplateComments(writer, record.typeParameters ?? [], `${recordPath}/typeParameters`)
|
|
60
|
+
writer.mapped("class", {mappingKind: "anchor", node: record, path: recordPath})
|
|
61
|
+
writer.synthetic(" ", "record declaration spacing", [record], [recordPath])
|
|
62
|
+
writer.mapped(record.name, {mappingKind: "exact", node: record, path: recordPath, role: "name"})
|
|
63
|
+
writer.synthetic("\n", "line break", [record], [recordPath])
|
|
64
|
+
record.fields.forEach((field, fieldIndex) => {
|
|
65
|
+
const fieldPath = `${recordPath}/fields/${fieldIndex}`
|
|
66
|
+
|
|
67
|
+
writer.synthetic(" # @type [", "Ruby record field type scaffolding", [field], [fieldPath])
|
|
68
|
+
emitType(writer, field.type, `${fieldPath}/type`, "ruby")
|
|
69
|
+
writer.synthetic("]\n attr_reader :", "Ruby record reader scaffolding", [field], [fieldPath])
|
|
70
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
71
|
+
writer.synthetic("\n", "line break", [field], [fieldPath])
|
|
72
|
+
})
|
|
73
|
+
writer.synthetic("\n", "record constructor separator", [record], [recordPath])
|
|
74
|
+
record.fields.forEach((field, fieldIndex) => {
|
|
75
|
+
const fieldPath = `${recordPath}/fields/${fieldIndex}`
|
|
76
|
+
|
|
77
|
+
writer.synthetic(" # @param ", "Ruby record constructor type scaffolding", [field], [fieldPath])
|
|
78
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
79
|
+
writer.synthetic(" [", "Ruby record constructor type scaffolding", [field], [fieldPath])
|
|
80
|
+
emitType(writer, field.type, `${fieldPath}/type`, "ruby")
|
|
81
|
+
writer.synthetic("]\n", "Ruby record constructor type scaffolding", [field], [fieldPath])
|
|
82
|
+
})
|
|
83
|
+
writer.synthetic(" def initialize(", "Ruby record constructor scaffolding", [record], [recordPath])
|
|
84
|
+
record.fields.forEach((field, fieldIndex) => {
|
|
85
|
+
if (fieldIndex) writer.synthetic(", ", "record field separator", [record], [recordPath])
|
|
86
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: `${recordPath}/fields/${fieldIndex}`, role: "name"})
|
|
87
|
+
})
|
|
88
|
+
writer.synthetic(")\n", "Ruby record constructor scaffolding", [record], [recordPath])
|
|
89
|
+
record.fields.forEach((field, fieldIndex) => {
|
|
90
|
+
const fieldPath = `${recordPath}/fields/${fieldIndex}`
|
|
91
|
+
|
|
92
|
+
writer.synthetic(" @", "Ruby record storage scaffolding", [field], [fieldPath])
|
|
93
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
94
|
+
writer.synthetic(" = ", "Ruby record storage scaffolding", [field], [fieldPath])
|
|
95
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
96
|
+
writer.synthetic("\n", "line break", [field], [fieldPath])
|
|
97
|
+
})
|
|
98
|
+
writer.synthetic(" ::Kernel.instance_method(:freeze).bind_call(self)\n end\nend", "Ruby record immutability scaffolding", [record], [recordPath])
|
|
99
|
+
})
|
|
100
|
+
if (records.length > 0) writer.synthetic("\n\n", "record/function separator", [module])
|
|
101
|
+
|
|
102
|
+
classes.forEach((declaration, classIndex) => {
|
|
103
|
+
if (classIndex > 0) writer.synthetic("\n\n", "reference class separator", [declaration], [`/classes/${classIndex}`])
|
|
104
|
+
emitReferenceClass(writer, declaration, classIndex)
|
|
105
|
+
})
|
|
106
|
+
if (classes.length > 0) writer.synthetic("\n\n", "reference class/function separator", [module])
|
|
107
|
+
|
|
13
108
|
module.functions.forEach((declaration, functionIndex) => {
|
|
14
109
|
if (functionIndex > 0) writer.synthetic("\n\n", "declaration separator", [declaration])
|
|
15
110
|
|
|
111
|
+
emitTemplateComments(writer, declaration.typeParameters ?? [], `/functions/${functionIndex}/typeParameters`)
|
|
16
112
|
for (const [parameterIndex, parameter] of declaration.parameters.entries()) {
|
|
17
113
|
const parameterPath = `/functions/${functionIndex}/parameters/${parameterIndex}`
|
|
18
114
|
|
|
19
115
|
writer.synthetic("# @param ", "Ruby type scaffolding", [parameter], [parameterPath])
|
|
20
116
|
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: parameterPath, role: "name"})
|
|
21
117
|
writer.synthetic(" [", "Ruby type scaffolding", [parameter], [parameterPath])
|
|
22
|
-
writer
|
|
23
|
-
mappingKind: "exact",
|
|
24
|
-
node: parameter.type,
|
|
25
|
-
path: `${parameterPath}/type`,
|
|
26
|
-
role: "type"
|
|
27
|
-
})
|
|
118
|
+
emitType(writer, parameter.type, `${parameterPath}/type`, "ruby")
|
|
28
119
|
writer.synthetic("]\n", "Ruby type scaffolding", [parameter], [parameterPath])
|
|
29
120
|
}
|
|
30
121
|
writer.synthetic("# @return [", "Ruby type scaffolding", [declaration])
|
|
31
|
-
writer
|
|
32
|
-
mappingKind: "exact",
|
|
33
|
-
node: declaration.returnType,
|
|
34
|
-
path: `/functions/${functionIndex}/returnType`,
|
|
35
|
-
role: "type"
|
|
36
|
-
})
|
|
122
|
+
emitType(writer, declaration.returnType, `/functions/${functionIndex}/returnType`, "ruby")
|
|
37
123
|
writer.synthetic("]\n", "Ruby type scaffolding", [declaration])
|
|
38
124
|
writer.mapped("def", {mappingKind: "anchor", node: declaration})
|
|
39
125
|
writer.synthetic(" ", "function spacing", [declaration])
|
|
@@ -55,8 +141,129 @@ export function generateRuby(module, writer) {
|
|
|
55
141
|
writer.mapped("end", {mappingKind: "anchor", node: declaration})
|
|
56
142
|
})
|
|
57
143
|
|
|
58
|
-
writer.
|
|
59
|
-
|
|
144
|
+
if (writer.program) {
|
|
145
|
+
const privateNominals = [...errors, ...records].filter((declaration) => !writer.isExported(declaration.id))
|
|
146
|
+
const privateFunctions = module.functions.filter((declaration) => !writer.isExported(declaration.id))
|
|
147
|
+
|
|
148
|
+
for (const declaration of privateNominals) {
|
|
149
|
+
writer.synthetic("\nprivate_constant :", "Ruby private semantic nominal declaration", [declaration])
|
|
150
|
+
writer.mapped(declaration.name, {mappingKind: "exact", node: declaration, role: "name"})
|
|
151
|
+
}
|
|
152
|
+
for (const declaration of privateFunctions) {
|
|
153
|
+
writer.synthetic("\nprivate_class_method :", "Ruby private semantic function", [declaration])
|
|
154
|
+
writer.mapped(declaration.name, {mappingKind: "exact", node: declaration, role: "name"})
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!writer.program || writer.isProgramEntry()) {
|
|
159
|
+
writer.synthetic("\n\n", "entry-point separator", [module.entryPoint])
|
|
160
|
+
emitBlock(writer, module.entryPoint.body, "", "/entryPoint/body")
|
|
161
|
+
}
|
|
162
|
+
if (writer.program) writer.synthetic("\nend\n", "Ruby semantic module close", [module])
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Emits one native Ruby reference class.
|
|
167
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
168
|
+
* @param {import("../semantic/types.js").ClassDeclaration} declaration - Reference class.
|
|
169
|
+
* @param {number} classIndex - Module class index.
|
|
170
|
+
* @returns {void}
|
|
171
|
+
*/
|
|
172
|
+
function emitReferenceClass(writer, declaration, classIndex) {
|
|
173
|
+
const path = `/classes/${classIndex}`
|
|
174
|
+
|
|
175
|
+
writer.mapped("class", {mappingKind: "anchor", node: declaration, path})
|
|
176
|
+
writer.synthetic(" ", "reference class spacing", [declaration], [path])
|
|
177
|
+
writer.mapped(declaration.name, {mappingKind: "exact", node: declaration, path, role: "name"})
|
|
178
|
+
writer.synthetic("\n", "line break", [declaration], [path])
|
|
179
|
+
declaration.fields.forEach((field, index) => {
|
|
180
|
+
const fieldPath = `${path}/fields/${index}`
|
|
181
|
+
|
|
182
|
+
writer.synthetic(" # @semantifold-private ", "private field metadata", [field], [fieldPath])
|
|
183
|
+
writer.mapped(field.name, {mappingKind: "exact", node: field, path: fieldPath, role: "name"})
|
|
184
|
+
writer.synthetic(" [", "private field type metadata", [field], [fieldPath])
|
|
185
|
+
emitType(writer, field.type, `${fieldPath}/type`, "ruby")
|
|
186
|
+
writer.synthetic("]\n", "line break", [field], [fieldPath])
|
|
187
|
+
})
|
|
188
|
+
const constructor = declaration.constructor
|
|
189
|
+
const constructorPath = `${path}/constructor`
|
|
190
|
+
|
|
191
|
+
writer.synthetic("\n", "constructor spacing", [constructor], [constructorPath])
|
|
192
|
+
emitRubyCallableComments(writer, constructor.parameters, undefined, `${constructorPath}/parameters`, undefined)
|
|
193
|
+
writer.synthetic(" ", "constructor indentation", [constructor], [constructorPath])
|
|
194
|
+
writer.mapped("def initialize", {mappingKind: "exact", node: constructor, path: constructorPath, role: "constructor"})
|
|
195
|
+
emitRubyParameters(writer, constructor.parameters, `${constructorPath}/parameters`)
|
|
196
|
+
writer.synthetic("\n", "line break", [constructor], [constructorPath])
|
|
197
|
+
emitBlock(writer, constructor.body, " ", `${constructorPath}/body`)
|
|
198
|
+
writer.synthetic(" end", "constructor close", [constructor], [constructorPath])
|
|
199
|
+
declaration.methods.forEach((method, index) => {
|
|
200
|
+
const methodPath = `${path}/methods/${index}`
|
|
201
|
+
|
|
202
|
+
writer.synthetic("\n\n", "method spacing", [method], [methodPath])
|
|
203
|
+
emitRubyCallableComments(writer, method.parameters, method.returnType, `${methodPath}/parameters`, `${methodPath}/returnType`)
|
|
204
|
+
writer.synthetic(" def ", "method indentation", [method], [methodPath])
|
|
205
|
+
writer.mapped(method.name, {mappingKind: "exact", node: method, path: methodPath, role: "name"})
|
|
206
|
+
emitRubyParameters(writer, method.parameters, `${methodPath}/parameters`)
|
|
207
|
+
writer.synthetic("\n", "line break", [method], [methodPath])
|
|
208
|
+
emitBlock(writer, method.body, " ", `${methodPath}/body`)
|
|
209
|
+
writer.synthetic(" end", "method close", [method], [methodPath])
|
|
210
|
+
})
|
|
211
|
+
writer.synthetic("\n", "line break", [declaration], [path])
|
|
212
|
+
writer.mapped("end", {mappingKind: "anchor", node: declaration, path})
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Emits exact Ruby callable type comments.
|
|
217
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
218
|
+
* @param {import("../semantic/types.js").Parameter[]} parameters - Ordered parameters.
|
|
219
|
+
* @param {import("../semantic/types.js").SemanticFunctionReturnType | undefined} returnType - Optional return type.
|
|
220
|
+
* @param {string} parameterPath - Parameter collection path.
|
|
221
|
+
* @param {string | undefined} returnPath - Return type path.
|
|
222
|
+
* @returns {void}
|
|
223
|
+
*/
|
|
224
|
+
function emitRubyCallableComments(writer, parameters, returnType, parameterPath, returnPath) {
|
|
225
|
+
for (const [index, parameter] of parameters.entries()) {
|
|
226
|
+
writer.synthetic(" # @param ", "parameter type metadata", [parameter], [`${parameterPath}/${index}`])
|
|
227
|
+
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: `${parameterPath}/${index}`, role: "name"})
|
|
228
|
+
writer.synthetic(" [", "parameter type metadata", [parameter], [`${parameterPath}/${index}`])
|
|
229
|
+
emitType(writer, parameter.type, `${parameterPath}/${index}/type`, "ruby")
|
|
230
|
+
writer.synthetic("]\n", "line break", [parameter])
|
|
231
|
+
}
|
|
232
|
+
if (returnType && returnPath) {
|
|
233
|
+
writer.synthetic(" # @return [", "return type metadata", [])
|
|
234
|
+
emitType(writer, returnType, returnPath, "ruby")
|
|
235
|
+
writer.synthetic("]\n", "line break", [])
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Emits one Ruby parameter list.
|
|
241
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
242
|
+
* @param {import("../semantic/types.js").Parameter[]} parameters - Ordered parameters.
|
|
243
|
+
* @param {string} path - Parameter collection path.
|
|
244
|
+
* @returns {void}
|
|
245
|
+
*/
|
|
246
|
+
function emitRubyParameters(writer, parameters, path) {
|
|
247
|
+
writer.synthetic("(", "parameter list open", parameters)
|
|
248
|
+
parameters.forEach((parameter, index) => {
|
|
249
|
+
if (index) writer.synthetic(", ", "parameter separator", parameters)
|
|
250
|
+
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: `${path}/${index}`, role: "name"})
|
|
251
|
+
})
|
|
252
|
+
writer.synthetic(")", "parameter list close", parameters)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Emits exact RDoc declaration parameters.
|
|
257
|
+
* @param {import("./writer.js").SourceWriter} writer - Source-aware writer.
|
|
258
|
+
* @param {import("../semantic/types.js").TypeParameter[]} parameters - Ordered type parameters.
|
|
259
|
+
* @param {string} path - Type-parameter collection path.
|
|
260
|
+
*/
|
|
261
|
+
function emitTemplateComments(writer, parameters, path) {
|
|
262
|
+
parameters.forEach((parameter, index) => {
|
|
263
|
+
writer.synthetic("# @template ", "Ruby type parameter scaffolding", [parameter], [`${path}/${index}`])
|
|
264
|
+
writer.mapped(parameter.name, {mappingKind: "exact", node: parameter, path: `${path}/${index}`, role: "name"})
|
|
265
|
+
writer.synthetic("\n", "line break", [parameter])
|
|
266
|
+
})
|
|
60
267
|
}
|
|
61
268
|
|
|
62
269
|
/**
|
|
@@ -80,11 +287,112 @@ function emitBlock(writer, block, indent, path) {
|
|
|
80
287
|
* @returns {void}
|
|
81
288
|
*/
|
|
82
289
|
function emitStatement(writer, statement, indent, path) {
|
|
290
|
+
emitEffectPrefixes(writer, statement, indent, path, "ruby",
|
|
291
|
+
(expression, expressionPath) => emitExpression(writer, expression, expressionPath, "ruby", identity))
|
|
83
292
|
if (statement.kind == "LocalDeclaration" || statement.kind == "AssignmentStatement") return emitLocal(writer, statement, indent, path)
|
|
84
293
|
writer.synthetic(indent, "indentation", [statement], [path])
|
|
294
|
+
if (statement.kind == "PrivateFieldWriteStatement") {
|
|
295
|
+
const field = writer.privateFieldForId(statement.field)
|
|
296
|
+
|
|
297
|
+
writer.mapped(`@${field.name}`, {mappingKind: "exact", name: field.name, node: statement, path, role: "member"})
|
|
298
|
+
writer.synthetic(" = ", "private field assignment", [statement], [path])
|
|
299
|
+
emitExpression(writer, statement.expression, `${path}/expression`, "ruby", identity)
|
|
300
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
301
|
+
return
|
|
302
|
+
}
|
|
303
|
+
if (statement.kind == "BreakStatement" || statement.kind == "ContinueStatement") {
|
|
304
|
+
writer.mapped(statement.kind == "BreakStatement" ? "break" : "next", {mappingKind: "exact", node: statement, path})
|
|
305
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
306
|
+
return
|
|
307
|
+
}
|
|
308
|
+
if (statement.kind == "WhileStatement") {
|
|
309
|
+
writer.mapped("while", {mappingKind: "exact", node: statement, path})
|
|
310
|
+
writer.synthetic(" ", "condition-controlled loop spacing", [statement], [path])
|
|
311
|
+
emitExpression(writer, statement.condition, `${path}/condition`, "ruby", identity)
|
|
312
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
313
|
+
emitBlock(writer, statement.body, `${indent} `, `${path}/body`)
|
|
314
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
315
|
+
writer.mapped("end", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
316
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
317
|
+
return
|
|
318
|
+
}
|
|
319
|
+
if (statement.kind == "ForEachStatement") {
|
|
320
|
+
emitExpression(writer, statement.list, `${path}/list`, "ruby", identity)
|
|
321
|
+
writer.mapped(".each", {mappingKind: "anchor", node: statement, path})
|
|
322
|
+
writer.synthetic(" ", "loop spacing", [statement], [path])
|
|
323
|
+
writer.mapped("do", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
324
|
+
writer.synthetic(" |", "iteration binding delimiter", [statement.valueBinding], [`${path}/valueBinding`])
|
|
325
|
+
writer.mapped(statement.valueBinding.name, {
|
|
326
|
+
mappingKind: "exact", node: statement.valueBinding, path: `${path}/valueBinding`, role: "name"
|
|
327
|
+
})
|
|
328
|
+
writer.synthetic("|\n", "iteration binding delimiter", [statement.valueBinding], [`${path}/valueBinding`])
|
|
329
|
+
emitBlock(writer, statement.body, `${indent} `, `${path}/body`)
|
|
330
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
331
|
+
writer.mapped("end", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
332
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
333
|
+
return
|
|
334
|
+
}
|
|
335
|
+
if (statement.kind == "ForEachMapStatement") {
|
|
336
|
+
emitExpression(writer, statement.map, `${path}/map`, "ruby", identity)
|
|
337
|
+
writer.mapped(".each", {mappingKind: "anchor", node: statement, path})
|
|
338
|
+
writer.synthetic(" ", "map loop spacing", [statement], [path])
|
|
339
|
+
writer.mapped("do", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
340
|
+
writer.synthetic(" |", "map iteration binding delimiter", [statement], [path])
|
|
341
|
+
writer.mapped(statement.keyBinding.name, {
|
|
342
|
+
mappingKind: "exact", node: statement.keyBinding, path: `${path}/keyBinding`, role: "name"
|
|
343
|
+
})
|
|
344
|
+
writer.synthetic(", ", "map iteration binding separator", [statement], [path])
|
|
345
|
+
writer.mapped(statement.valueBinding.name, {
|
|
346
|
+
mappingKind: "exact", node: statement.valueBinding, path: `${path}/valueBinding`, role: "name"
|
|
347
|
+
})
|
|
348
|
+
writer.synthetic("|\n", "map iteration binding delimiter", [statement], [path])
|
|
349
|
+
emitBlock(writer, statement.body, `${indent} `, `${path}/body`)
|
|
350
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
351
|
+
writer.mapped("end", {mappingKind: "anchor", node: statement.body, path: `${path}/body`})
|
|
352
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
353
|
+
return
|
|
354
|
+
}
|
|
355
|
+
if (statement.kind == "RaiseStatement") {
|
|
356
|
+
const type = statement.error.error
|
|
357
|
+
const error = writer.errorForId(type.declarationId)
|
|
358
|
+
|
|
359
|
+
writer.mapped("raise", {mappingKind: "anchor", node: statement, path})
|
|
360
|
+
writer.synthetic(" ", "raise spacing", [statement], [path])
|
|
361
|
+
writer.mapped(writer.errorNameForId(type.declarationId), {mappingKind: "exact", name: error.name, node: statement.error, path: `${path}/error`, role: "type"})
|
|
362
|
+
writer.synthetic(", ", "error message separator", [statement.error], [`${path}/error`])
|
|
363
|
+
emitExpression(writer, statement.error.message, `${path}/error/message`, "ruby", identity)
|
|
364
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
365
|
+
return
|
|
366
|
+
}
|
|
367
|
+
if (statement.kind == "TryStatement") {
|
|
368
|
+
const caught = writer.errorForId(statement.catchType.declarationId)
|
|
369
|
+
|
|
370
|
+
writer.mapped("begin", {mappingKind: "anchor", node: statement, path})
|
|
371
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
372
|
+
emitBlock(writer, statement.body, `${indent} `, `${path}/body`)
|
|
373
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
374
|
+
writer.mapped("rescue", {mappingKind: "anchor", node: statement, path, role: "catch"})
|
|
375
|
+
writer.synthetic(" ", "rescue spacing", [statement], [path])
|
|
376
|
+
writer.mapped(writer.errorNameForId(statement.catchType.declarationId), {mappingKind: "exact", name: caught.name, node: statement.catchType, path: `${path}/catchType`, role: "type"})
|
|
377
|
+
writer.synthetic(" => ", "catch binding separator", [statement.catchBinding], [`${path}/catchBinding`])
|
|
378
|
+
writer.mapped(statement.catchBinding.name, {mappingKind: "exact", node: statement.catchBinding, path: `${path}/catchBinding`, role: "name"})
|
|
379
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
380
|
+
emitBlock(writer, statement.catchBody, `${indent} `, `${path}/catchBody`)
|
|
381
|
+
writer.synthetic(indent, "indentation", [statement], [path])
|
|
382
|
+
writer.mapped("end", {mappingKind: "anchor", node: statement.catchBody, path: `${path}/catchBody`})
|
|
383
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
384
|
+
return
|
|
385
|
+
}
|
|
85
386
|
if (statement.kind == "ReturnStatement") {
|
|
86
387
|
writer.mapped("return", {mappingKind: "anchor", node: statement, path})
|
|
87
|
-
|
|
388
|
+
if (statement.expression) {
|
|
389
|
+
writer.synthetic(" ", "return spacing", [statement], [path])
|
|
390
|
+
emitExpression(writer, statement.expression, `${path}/expression`, "ruby", identity)
|
|
391
|
+
}
|
|
392
|
+
writer.synthetic("\n", "line break", [statement], [path])
|
|
393
|
+
return
|
|
394
|
+
}
|
|
395
|
+
if (statement.kind == "ExpressionStatement") {
|
|
88
396
|
emitExpression(writer, statement.expression, `${path}/expression`, "ruby", identity)
|
|
89
397
|
writer.synthetic("\n", "line break", [statement], [path])
|
|
90
398
|
return
|
|
@@ -134,12 +442,7 @@ function emitLocal(writer, statement, indent, statementPath) {
|
|
|
134
442
|
}
|
|
135
443
|
|
|
136
444
|
writer.synthetic("# @type [", "Ruby local type scaffolding", [statement], [statementPath])
|
|
137
|
-
writer
|
|
138
|
-
mappingKind: "exact",
|
|
139
|
-
node: statement.type,
|
|
140
|
-
path: `${statementPath}/type`,
|
|
141
|
-
role: "type"
|
|
142
|
-
})
|
|
445
|
+
emitType(writer, statement.type, `${statementPath}/type`, "ruby")
|
|
143
446
|
writer.synthetic("]\n", "Ruby local type scaffolding", [statement], [statementPath])
|
|
144
447
|
if (!statement.mutable) {
|
|
145
448
|
writer.synthetic(`${indent}# @semantifold-immutable\n`, "Ruby immutability scaffolding", [statement], [statementPath])
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** Qualified edition-2021 support. Every token is checked by the Rust frontend before collapse. */
|
|
4
|
+
export const rustRuntime = `#![allow(dead_code, unused_variables, unused_mut, unused_assignments, unused_parens, unconditional_recursion, non_snake_case)]
|
|
5
|
+
fn semantifold_print_integer(value: i64) { println!("{}", value); }
|
|
6
|
+
fn semantifold_print_boolean(value: bool) { println!("{}", value); }
|
|
7
|
+
fn semantifold_print_string(value: String) { println!("{}", value); }
|
|
8
|
+
fn semantifold_integer_add(left: i64, right: i64) -> i64 {
|
|
9
|
+
let (result, overflow): (i64, bool) = left.overflowing_add(right);
|
|
10
|
+
if overflow { eprintln!("semantifold: integer overflow"); std::process::exit(70); }
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
fn semantifold_integer_subtract(left: i64, right: i64) -> i64 {
|
|
14
|
+
let (result, overflow): (i64, bool) = left.overflowing_sub(right);
|
|
15
|
+
if overflow { eprintln!("semantifold: integer overflow"); std::process::exit(70); }
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
fn semantifold_integer_multiply(left: i64, right: i64) -> i64 {
|
|
19
|
+
let (result, overflow): (i64, bool) = left.overflowing_mul(right);
|
|
20
|
+
if overflow { eprintln!("semantifold: integer overflow"); std::process::exit(70); }
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
fn semantifold_integer_negate(value: i64) -> i64 {
|
|
24
|
+
let (result, overflow): (i64, bool) = value.overflowing_neg();
|
|
25
|
+
if overflow { eprintln!("semantifold: integer overflow"); std::process::exit(70); }
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
`
|
|
29
|
+
|
|
30
|
+
/** Actual manifest qualified with Cargo 1.98.1 on Ubuntu 24.04 and 26.04. */
|
|
31
|
+
export const rustManifest = '[package]\nname = "semantifold-generated"\nversion = "0.0.0"\nedition = "2021"\nrust-version = "1.98.1"\npublish = false\nbuild = false\n\n[profile.dev]\noverflow-checks = true\npanic = "abort"\n\n[profile.release]\noverflow-checks = true\npanic = "abort"\n'
|
|
32
|
+
|
|
33
|
+
/** Cargo-generated bytes, SHA-256 185a41f6648ef49c8e7721f3321604abf05fae11c7007f823121c17fe48eec64. */
|
|
34
|
+
export const rustLockfile = '# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = "semantifold-generated"\nversion = "0.0.0"\n'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import {unsupportedCapability} from "../diagnostic.js"
|
|
4
|
+
|
|
5
|
+
/** Qualified legacy Rust grammar input limit, including support source. */
|
|
6
|
+
export const maximumRustSourceLength = 32767
|
|
7
|
+
|
|
8
|
+
/** Propagates known owned UTF-8 lengths to reject impossible native allocations before emission. */
|
|
9
|
+
class RustValueValidator {
|
|
10
|
+
/**
|
|
11
|
+
* Validates each expression without folding or changing the semantic graph.
|
|
12
|
+
* @param {import("../semantic/types.js").Expression} expression - Validated expression.
|
|
13
|
+
* @param {Map<string, bigint | undefined>} sizes - Known lexical string byte sizes.
|
|
14
|
+
* @returns {bigint | undefined} Proven result size when known.
|
|
15
|
+
*/
|
|
16
|
+
size(expression, sizes) {
|
|
17
|
+
if (expression.kind == "StringLiteral") return BigInt(Buffer.byteLength(expression.value, "utf8"))
|
|
18
|
+
if (expression.kind == "IdentifierExpression") return sizes.get(expression.name)
|
|
19
|
+
if (expression.kind == "CallExpression") {
|
|
20
|
+
for (const argument of expression.arguments) this.size(argument, sizes)
|
|
21
|
+
} else if (expression.kind == "UnaryExpression") this.size(expression.operand, sizes)
|
|
22
|
+
else if (expression.kind == "BinaryExpression") {
|
|
23
|
+
const left = this.size(expression.left, sizes)
|
|
24
|
+
const right = this.size(expression.right, sizes)
|
|
25
|
+
|
|
26
|
+
if (expression.operation == "StringConcat") {
|
|
27
|
+
if ((left ?? 0n) + (right ?? 0n) > 9223372036854775807n) {
|
|
28
|
+
unsupportedCapability("rust", "known owned string size exceeds the qualified signed-64-bit allocation limit", expression.location)
|
|
29
|
+
}
|
|
30
|
+
if (left !== undefined && right !== undefined) return left + right
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return undefined
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Follows value copies and independent branches, retaining only equal outgoing size proofs.
|
|
38
|
+
* @param {import("../semantic/types.js").Block} block - Lexical block.
|
|
39
|
+
* @param {Map<string, bigint | undefined>} inherited - Visible sizes.
|
|
40
|
+
* @returns {Map<string, bigint | undefined>} Outgoing size proofs.
|
|
41
|
+
*/
|
|
42
|
+
block(block, inherited) {
|
|
43
|
+
const sizes = new Map(inherited)
|
|
44
|
+
|
|
45
|
+
for (const statement of block.statements) {
|
|
46
|
+
if (statement.kind == "LocalDeclaration") sizes.set(statement.name, this.size(statement.initializer, sizes))
|
|
47
|
+
else if (statement.kind == "AssignmentStatement") sizes.set(statement.target.name, this.size(statement.expression, sizes))
|
|
48
|
+
else if (statement.kind == "IfStatement") {
|
|
49
|
+
this.size(statement.condition, sizes)
|
|
50
|
+
const left = this.block(statement.consequent, sizes)
|
|
51
|
+
const right = statement.alternate ? this.block(statement.alternate, sizes) : sizes
|
|
52
|
+
|
|
53
|
+
for (const name of sizes.keys()) sizes.set(name, left.get(name) === right.get(name) ? left.get(name) : undefined)
|
|
54
|
+
} else if (statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement" ||
|
|
55
|
+
statement.kind == "ReturnStatement") {
|
|
56
|
+
const expression = statement.expression
|
|
57
|
+
|
|
58
|
+
if (expression) this.size(expression, sizes)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return sizes
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Rejects statically unrepresentable owned values before constructing any artifacts.
|
|
67
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Fully validated semantics.
|
|
68
|
+
* @returns {void}
|
|
69
|
+
*/
|
|
70
|
+
export function validateRustValues(module) {
|
|
71
|
+
const validator = new RustValueValidator()
|
|
72
|
+
|
|
73
|
+
for (const declaration of module.functions) validator.block(declaration.body, new Map())
|
|
74
|
+
validator.block(module.entryPoint.body, new Map())
|
|
75
|
+
}
|