semantifold 0.8.0 → 0.10.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 +11 -5
- package/bin/semantifold.js +6 -0
- package/build/bin/semantifold.d.ts +3 -0
- package/build/bin/semantifold.d.ts.map +1 -0
- package/build/bin/semantifold.js +5 -0
- package/build/index.d.ts +9 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +10 -1
- package/build/src/artifact-path.d.ts +16 -0
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +29 -3
- package/build/src/backends/c-check.d.ts +7 -0
- package/build/src/backends/c-check.d.ts.map +1 -0
- package/build/src/backends/c-check.js +65 -0
- package/build/src/backends/check-plan.d.ts +96 -0
- package/build/src/backends/check-plan.d.ts.map +1 -0
- package/build/src/backends/check-plan.js +135 -0
- package/build/src/backends/cpp-check.d.ts +7 -0
- package/build/src/backends/cpp-check.d.ts.map +1 -0
- package/build/src/backends/cpp-check.js +59 -0
- package/build/src/backends/csharp-check.d.ts +7 -0
- package/build/src/backends/csharp-check.d.ts.map +1 -0
- package/build/src/backends/csharp-check.js +125 -0
- package/build/src/backends/csharp.d.ts +1 -0
- package/build/src/backends/csharp.d.ts.map +1 -1
- package/build/src/backends/csharp.js +5 -4
- package/build/src/backends/dart-check.d.ts +7 -0
- package/build/src/backends/dart-check.d.ts.map +1 -0
- package/build/src/backends/dart-check.js +103 -0
- package/build/src/backends/dart.d.ts +2 -0
- package/build/src/backends/dart.d.ts.map +1 -1
- package/build/src/backends/dart.js +5 -5
- package/build/src/backends/go-check.d.ts +7 -0
- package/build/src/backends/go-check.d.ts.map +1 -0
- package/build/src/backends/go-check.js +77 -0
- package/build/src/backends/go.d.ts +1 -0
- package/build/src/backends/go.d.ts.map +1 -1
- package/build/src/backends/go.js +3 -3
- package/build/src/backends/java-check.d.ts +21 -0
- package/build/src/backends/java-check.d.ts.map +1 -0
- package/build/src/backends/java-check.js +73 -0
- package/build/src/backends/javascript-check.d.ts +7 -0
- package/build/src/backends/javascript-check.d.ts.map +1 -0
- package/build/src/backends/javascript-check.js +29 -0
- package/build/src/backends/kotlin-check.d.ts +7 -0
- package/build/src/backends/kotlin-check.d.ts.map +1 -0
- package/build/src/backends/kotlin-check.js +31 -0
- package/build/src/backends/php-check.d.ts +7 -0
- package/build/src/backends/php-check.d.ts.map +1 -0
- package/build/src/backends/php-check.js +21 -0
- package/build/src/backends/program.d.ts +7 -0
- package/build/src/backends/program.d.ts.map +1 -1
- package/build/src/backends/program.js +16 -1
- package/build/src/backends/python-check.d.ts +7 -0
- package/build/src/backends/python-check.d.ts.map +1 -0
- package/build/src/backends/python-check.js +28 -0
- package/build/src/backends/ruby-check.d.ts +7 -0
- package/build/src/backends/ruby-check.d.ts.map +1 -0
- package/build/src/backends/ruby-check.js +21 -0
- package/build/src/backends/rust-check.d.ts +7 -0
- package/build/src/backends/rust-check.d.ts.map +1 -0
- package/build/src/backends/rust-check.js +65 -0
- package/build/src/backends/swift-check.d.ts +7 -0
- package/build/src/backends/swift-check.d.ts.map +1 -0
- package/build/src/backends/swift-check.js +77 -0
- package/build/src/backends/typescript-check.d.ts +7 -0
- package/build/src/backends/typescript-check.d.ts.map +1 -0
- package/build/src/backends/typescript-check.js +33 -0
- package/build/src/backends/zig-check.d.ts +7 -0
- package/build/src/backends/zig-check.d.ts.map +1 -0
- package/build/src/backends/zig-check.js +70 -0
- package/build/src/diagnostic.d.ts +13 -1
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +14 -2
- package/build/src/frontends/program.d.ts +6 -0
- package/build/src/frontends/program.d.ts.map +1 -1
- package/build/src/frontends/program.js +9 -1
- package/build/src/language-registry.d.ts +54 -0
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +107 -5
- package/build/src/project-build.d.ts +172 -0
- package/build/src/project-build.d.ts.map +1 -0
- package/build/src/project-build.js +320 -0
- package/build/src/project-cli.d.ts +40 -0
- package/build/src/project-cli.d.ts.map +1 -0
- package/build/src/project-cli.js +145 -0
- package/build/src/project-manifest.d.ts +148 -0
- package/build/src/project-manifest.d.ts.map +1 -0
- package/build/src/project-manifest.js +432 -0
- package/build/src/project-reporter.d.ts +81 -0
- package/build/src/project-reporter.d.ts.map +1 -0
- package/build/src/project-reporter.js +293 -0
- package/build/src/project-snapshot.d.ts +129 -0
- package/build/src/project-snapshot.d.ts.map +1 -0
- package/build/src/project-snapshot.js +362 -0
- package/build/src/project-watch-reporter.d.ts +125 -0
- package/build/src/project-watch-reporter.d.ts.map +1 -0
- package/build/src/project-watch-reporter.js +280 -0
- package/build/src/project-watch.d.ts +133 -0
- package/build/src/project-watch.d.ts.map +1 -0
- package/build/src/project-watch.js +839 -0
- package/build/src/publication.d.ts +218 -0
- package/build/src/publication.d.ts.map +1 -0
- package/build/src/publication.js +1832 -0
- package/build/src/semantic/types.d.ts +613 -0
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +163 -1
- package/build/src/subprocess.d.ts +8 -0
- package/build/src/subprocess.d.ts.map +1 -1
- package/build/src/subprocess.js +50 -9
- package/build/src/target-check.d.ts +52 -0
- package/build/src/target-check.d.ts.map +1 -0
- package/build/src/target-check.js +796 -0
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +3 -3
- package/docs/architecture.md +3 -1
- package/docs/c.md +4 -0
- package/docs/cpp.md +4 -0
- package/docs/dart.md +4 -0
- package/docs/generated-artifact-publication.md +98 -0
- package/docs/kotlin.md +2 -2
- package/docs/language-support.md +29 -3
- package/docs/project-build-cli.md +147 -0
- package/docs/project-watch.md +60 -0
- package/docs/rust.md +4 -0
- package/docs/swift.md +2 -0
- package/docs/testing.md +70 -3
- package/docs/watch-build-pipeline.md +42 -26
- package/docs/zig.md +2 -0
- package/examples/jsdoc-java-watch/expected-output.txt +3 -0
- package/examples/jsdoc-java-watch/semantifold.json +23 -0
- package/examples/jsdoc-java-watch/src/main.js +21 -0
- package/index.js +9 -0
- package/package.json +6 -1
- package/src/artifact-path.js +31 -2
- package/src/backends/c-check.js +80 -0
- package/src/backends/check-plan.js +147 -0
- package/src/backends/cpp-check.js +73 -0
- package/src/backends/csharp-check.js +139 -0
- package/src/backends/csharp.js +4 -3
- package/src/backends/dart-check.js +117 -0
- package/src/backends/dart.js +4 -4
- package/src/backends/go-check.js +89 -0
- package/src/backends/go.js +2 -2
- package/src/backends/java-check.js +77 -0
- package/src/backends/javascript-check.js +33 -0
- package/src/backends/kotlin-check.js +41 -0
- package/src/backends/php-check.js +23 -0
- package/src/backends/program.js +17 -0
- package/src/backends/python-check.js +30 -0
- package/src/backends/ruby-check.js +23 -0
- package/src/backends/rust-check.js +78 -0
- package/src/backends/swift-check.js +89 -0
- package/src/backends/typescript-check.js +37 -0
- package/src/backends/zig-check.js +81 -0
- package/src/diagnostic.js +9 -1
- package/src/frontends/program.js +9 -0
- package/src/language-registry.js +113 -4
- package/src/project-build.js +353 -0
- package/src/project-cli.js +155 -0
- package/src/project-manifest.js +479 -0
- package/src/project-reporter.js +320 -0
- package/src/project-snapshot.js +403 -0
- package/src/project-watch-reporter.js +303 -0
- package/src/project-watch.js +870 -0
- package/src/publication.js +2071 -0
- package/src/semantic/types.js +184 -0
- package/src/subprocess.js +49 -8
- package/src/target-check.js +844 -0
- package/src/toolchains.js +3 -2
- package/tsconfig.json +1 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import {SemantifoldDiagnostic} from "../diagnostic.js"
|
|
5
|
+
import {
|
|
6
|
+
checkArtifacts,
|
|
7
|
+
checkOutput,
|
|
8
|
+
checkPlan,
|
|
9
|
+
checkStage,
|
|
10
|
+
checkTool,
|
|
11
|
+
environmentPath,
|
|
12
|
+
pathArgument
|
|
13
|
+
} from "./check-plan.js"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Constructs Swift's warnings-as-errors type-check/compile plan.
|
|
17
|
+
* @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
|
|
18
|
+
* @returns {import("../semantic/types.js").TargetCheckPlan} Immutable Swift plan.
|
|
19
|
+
*/
|
|
20
|
+
export function createSwiftCheckPlan(context) {
|
|
21
|
+
const tool = checkTool(context, "swiftc", "swift")
|
|
22
|
+
const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".swift"), "swift", "only staged '.swift' sources")
|
|
23
|
+
|
|
24
|
+
if (artifacts.length != 1 || artifacts[0] != path.join(context.sourcePath, "program.swift")) {
|
|
25
|
+
throw new SemantifoldDiagnostic({code: "INVALID_TARGET_CHECK_PLAN", language: "swift",
|
|
26
|
+
message: "Swift developer checks require the exact producer-owned 'program.swift' source."})
|
|
27
|
+
}
|
|
28
|
+
const home = path.join(context.buildPath, "home")
|
|
29
|
+
const cache = path.join(context.buildPath, "cache")
|
|
30
|
+
const temporary = path.join(context.buildPath, "tmp")
|
|
31
|
+
const environment = {
|
|
32
|
+
HOME: home,
|
|
33
|
+
PATH: [path.dirname(tool.executable), "/usr/bin", "/usr/local/bin", "/bin"].filter((value, index, values) =>
|
|
34
|
+
values.indexOf(value) == index).join(path.delimiter),
|
|
35
|
+
TMPDIR: temporary,
|
|
36
|
+
XDG_CACHE_HOME: cache
|
|
37
|
+
}
|
|
38
|
+
const environmentPaths = [environmentPath("HOME", "build"), environmentPath("TMPDIR", "build"),
|
|
39
|
+
environmentPath("XDG_CACHE_HOME", "build")]
|
|
40
|
+
const objects = path.join(context.buildPath, "objects")
|
|
41
|
+
const object = path.join(objects, "program.o")
|
|
42
|
+
const binary = path.join(context.buildPath, "semantifold-swift")
|
|
43
|
+
const typecheckArgv = [
|
|
44
|
+
"--driver-mode=swiftc", "-warnings-as-errors", "-typecheck", "-module-name", "SemantifoldGenerated", ...artifacts
|
|
45
|
+
]
|
|
46
|
+
const compileArgv = [
|
|
47
|
+
"--driver-mode=swiftc", "-warnings-as-errors", "-c", ...artifacts,
|
|
48
|
+
"-module-name", "SemantifoldGenerated", "-o", "program.o"
|
|
49
|
+
]
|
|
50
|
+
const linkArgv = ["--driver-mode=swiftc", object, "-Xlinker", "--build-id=none", "-o", binary]
|
|
51
|
+
|
|
52
|
+
return checkPlan(context, "swift", artifacts, [
|
|
53
|
+
checkStage({
|
|
54
|
+
argv: typecheckArgv,
|
|
55
|
+
cwd: context.sourcePath,
|
|
56
|
+
environment,
|
|
57
|
+
environmentPaths,
|
|
58
|
+
inputs: artifacts,
|
|
59
|
+
output: null,
|
|
60
|
+
pathArguments: artifacts.map((_, index) => pathArgument(index + 5, "source")),
|
|
61
|
+
stage: "compile",
|
|
62
|
+
tool
|
|
63
|
+
}),
|
|
64
|
+
checkStage({
|
|
65
|
+
argv: compileArgv,
|
|
66
|
+
cwd: objects,
|
|
67
|
+
environment,
|
|
68
|
+
environmentPaths,
|
|
69
|
+
inputs: artifacts,
|
|
70
|
+
output: null,
|
|
71
|
+
pathArguments: artifacts.map((_, index) => pathArgument(index + 3, "source")),
|
|
72
|
+
stage: "compile",
|
|
73
|
+
tool,
|
|
74
|
+
transientPaths: [objects]
|
|
75
|
+
}),
|
|
76
|
+
checkStage({
|
|
77
|
+
argv: linkArgv,
|
|
78
|
+
cwd: context.buildPath,
|
|
79
|
+
environment,
|
|
80
|
+
environmentPaths,
|
|
81
|
+
inputs: [object],
|
|
82
|
+
output: checkOutput(context.buildPath, "application/x-executable", "compiler-output"),
|
|
83
|
+
pathArguments: [pathArgument(1, "build"), pathArgument(linkArgv.length - 1, "build")],
|
|
84
|
+
stage: "compile",
|
|
85
|
+
tool,
|
|
86
|
+
transientPaths: [objects]
|
|
87
|
+
})
|
|
88
|
+
])
|
|
89
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import {SemantifoldDiagnostic} from "../diagnostic.js"
|
|
5
|
+
import {checkArtifacts, checkPlan, checkStage, checkTool, pathArgument} from "./check-plan.js"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Constructs TypeScript's non-emitting compiler plan.
|
|
9
|
+
* @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
|
|
10
|
+
* @returns {import("../semantic/types.js").TargetCheckPlan} Immutable TypeScript plan.
|
|
11
|
+
*/
|
|
12
|
+
export function createTypeScriptCheckPlan(context) {
|
|
13
|
+
const tool = checkTool(context, "tsc", "typescript")
|
|
14
|
+
const artifacts = checkArtifacts(context, artifact => artifact.path.endsWith(".ts") || path.basename(artifact.path) == "package.json",
|
|
15
|
+
"typescript", "only staged '.ts' artifacts and package manifests")
|
|
16
|
+
const sources = artifacts.filter(artifact => artifact.endsWith(".ts"))
|
|
17
|
+
|
|
18
|
+
if (sources.length == 0) {
|
|
19
|
+
throw new SemantifoldDiagnostic({code: "INVALID_TARGET_CHECK_PLAN", language: "typescript",
|
|
20
|
+
message: "TypeScript developer checks require at least one staged '.ts' artifact."})
|
|
21
|
+
}
|
|
22
|
+
const typeRoots = path.join(context.buildPath, "types")
|
|
23
|
+
const argv = [
|
|
24
|
+
"--pretty", "false", "--noEmit", "--incremental", "false", "--target", "ES2024", "--module", "NodeNext",
|
|
25
|
+
"--moduleResolution", "NodeNext", "--typeRoots", typeRoots, ...sources
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
return checkPlan(context, "typescript", artifacts, [checkStage({
|
|
29
|
+
argv,
|
|
30
|
+
cwd: context.sourcePath,
|
|
31
|
+
inputs: artifacts,
|
|
32
|
+
output: null,
|
|
33
|
+
pathArguments: [pathArgument(12, "build"), ...sources.map((_, index) => pathArgument(13 + index, "source"))],
|
|
34
|
+
stage: "compile",
|
|
35
|
+
tool
|
|
36
|
+
})])
|
|
37
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import {SemantifoldDiagnostic} from "../diagnostic.js"
|
|
5
|
+
import {
|
|
6
|
+
checkArtifacts,
|
|
7
|
+
checkPlan,
|
|
8
|
+
checkStage,
|
|
9
|
+
checkTool,
|
|
10
|
+
environmentPath,
|
|
11
|
+
pathArgument
|
|
12
|
+
} from "./check-plan.js"
|
|
13
|
+
import {zigBuild} from "./zig-runtime.js"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Constructs Zig's isolated Debug project build and canonical format-check plan.
|
|
17
|
+
* @param {import("../language-registry.js").TargetCheckPlanContext} context - Validated candidate context.
|
|
18
|
+
* @returns {import("../semantic/types.js").TargetCheckPlan} Immutable Zig plan.
|
|
19
|
+
*/
|
|
20
|
+
export function createZigCheckPlan(context) {
|
|
21
|
+
const tool = checkTool(context, "zig", "zig")
|
|
22
|
+
const artifacts = checkArtifacts(context, artifact => artifact.path == "build.zig" || artifact.path.endsWith(".zig"),
|
|
23
|
+
"zig", "only staged Zig source and the canonical build manifest")
|
|
24
|
+
const manifests = context.artifacts.artifacts.filter(artifact => artifact.path == "build.zig")
|
|
25
|
+
const sources = artifacts.filter(artifact => artifact != path.join(context.sourcePath, "build.zig"))
|
|
26
|
+
|
|
27
|
+
if (manifests.length != 1 || manifests[0].contentKind != "text" || manifests[0].role != "manifest" ||
|
|
28
|
+
manifests[0].content != zigBuild || artifacts.length != 2 || sources.length != 1 ||
|
|
29
|
+
sources[0] != path.join(context.sourcePath, "src/main.zig")) {
|
|
30
|
+
throw new SemantifoldDiagnostic({
|
|
31
|
+
code: "INVALID_TARGET_CHECK_PLAN",
|
|
32
|
+
language: "zig",
|
|
33
|
+
message: "Zig developer checks require the exact standard-library-only 'build.zig' and staged Zig source."
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
const home = path.join(context.buildPath, "home")
|
|
37
|
+
const temporary = path.join(context.buildPath, "tmp")
|
|
38
|
+
const globalCache = path.join(context.buildPath, "zig-global-cache")
|
|
39
|
+
const localCache = path.join(context.buildPath, "zig-local-cache")
|
|
40
|
+
const output = path.join(context.buildPath, "output")
|
|
41
|
+
const environment = {
|
|
42
|
+
HOME: home,
|
|
43
|
+
HTTP_PROXY: "http://127.0.0.1:9",
|
|
44
|
+
HTTPS_PROXY: "http://127.0.0.1:9",
|
|
45
|
+
NO_PROXY: "",
|
|
46
|
+
TMPDIR: temporary,
|
|
47
|
+
ZIG_GLOBAL_CACHE_DIR: globalCache,
|
|
48
|
+
ZIG_LOCAL_CACHE_DIR: localCache
|
|
49
|
+
}
|
|
50
|
+
const environmentPaths = [
|
|
51
|
+
environmentPath("HOME", "build"), environmentPath("TMPDIR", "build"),
|
|
52
|
+
environmentPath("ZIG_GLOBAL_CACHE_DIR", "build"), environmentPath("ZIG_LOCAL_CACHE_DIR", "build")
|
|
53
|
+
]
|
|
54
|
+
const formatArgv = ["fmt", "--check", ...artifacts]
|
|
55
|
+
|
|
56
|
+
return checkPlan(context, "zig", artifacts, [
|
|
57
|
+
checkStage({
|
|
58
|
+
argv: ["build", "-Doptimize=Debug", "--prefix", output],
|
|
59
|
+
cwd: context.sourcePath,
|
|
60
|
+
environment,
|
|
61
|
+
environmentPaths,
|
|
62
|
+
inputs: artifacts,
|
|
63
|
+
output: null,
|
|
64
|
+
pathArguments: [pathArgument(3, "build")],
|
|
65
|
+
stage: "compile",
|
|
66
|
+
tool,
|
|
67
|
+
transientPaths: [output]
|
|
68
|
+
}),
|
|
69
|
+
checkStage({
|
|
70
|
+
argv: formatArgv,
|
|
71
|
+
cwd: context.sourcePath,
|
|
72
|
+
environment,
|
|
73
|
+
environmentPaths,
|
|
74
|
+
inputs: artifacts,
|
|
75
|
+
output: null,
|
|
76
|
+
pathArguments: artifacts.map((_, index) => pathArgument(index + 2, "source")),
|
|
77
|
+
stage: "validate",
|
|
78
|
+
tool
|
|
79
|
+
})
|
|
80
|
+
])
|
|
81
|
+
}
|
package/src/diagnostic.js
CHANGED
|
@@ -19,8 +19,12 @@ export class SemantifoldDiagnostic extends Error {
|
|
|
19
19
|
* @param {string | undefined} [options.stderr] - Captured standard error when available.
|
|
20
20
|
* @param {string | undefined} [options.stdout] - Captured standard output when available.
|
|
21
21
|
* @param {string | undefined} [options.version] - Captured executable version when known.
|
|
22
|
+
* @param {number | undefined} [options.durationMs] - Observed process duration when known.
|
|
23
|
+
* @param {string | undefined} [options.projectId] - Exact project identity when known.
|
|
24
|
+
* @param {string | undefined} [options.targetId] - Exact project target identity when known.
|
|
25
|
+
* @param {string | undefined} [options.toolId] - Exact toolchain identity when known.
|
|
22
26
|
*/
|
|
23
|
-
constructor({cause, code, command, executable, exitCode, generatedLocation, language, location, message, signal, stage, stderr, stdout, version}) {
|
|
27
|
+
constructor({cause, code, command, durationMs, executable, exitCode, generatedLocation, language, location, message, projectId, signal, stage, stderr, stdout, targetId, toolId, version}) {
|
|
24
28
|
const locationText = location ? ` at ${location.filename}:${location.start.line}:${location.start.column}` : ""
|
|
25
29
|
|
|
26
30
|
super(`[${code}] ${language}${locationText}: ${message}`, cause ? {cause} : undefined)
|
|
@@ -31,12 +35,16 @@ export class SemantifoldDiagnostic extends Error {
|
|
|
31
35
|
this.language = language
|
|
32
36
|
this.location = location
|
|
33
37
|
if (command != undefined) this.command = command
|
|
38
|
+
if (durationMs != undefined) this.durationMs = durationMs
|
|
34
39
|
if (executable != undefined) this.executable = executable
|
|
35
40
|
if (exitCode != undefined) this.exitCode = exitCode
|
|
36
41
|
if (signal != undefined) this.signal = signal
|
|
37
42
|
if (stage != undefined) this.stage = stage
|
|
38
43
|
if (stderr != undefined) this.stderr = stderr
|
|
39
44
|
if (stdout != undefined) this.stdout = stdout
|
|
45
|
+
if (projectId != undefined) this.projectId = projectId
|
|
46
|
+
if (targetId != undefined) this.targetId = targetId
|
|
47
|
+
if (toolId != undefined) this.toolId = toolId
|
|
40
48
|
if (version != undefined) this.version = version
|
|
41
49
|
}
|
|
42
50
|
}
|
package/src/frontends/program.js
CHANGED
|
@@ -19,6 +19,15 @@ import {inspectRubyModule} from "./ruby.js"
|
|
|
19
19
|
const programLanguages = new Set(["php", "ruby", "javascript", "typescript", "java"])
|
|
20
20
|
const moduleIdPattern = /^[a-z][a-z0-9_]*(?:[.-][a-z][a-z0-9_]*)*$/u
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Reports whether a registered frontend participates in the explicit Task-010 program profile.
|
|
24
|
+
* @param {string} language - Registered source identity.
|
|
25
|
+
* @returns {boolean} Whether the profile accepts the language.
|
|
26
|
+
*/
|
|
27
|
+
export function supportsProgramSourceLanguage(language) {
|
|
28
|
+
return programLanguages.has(/** @type {import("../semantic/types.js").SemanticLanguage} */ (language))
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
/** @typedef {{facade?: import("../stdlib-facades.js").StdlibFacadeRecord, filename: string, id: string, language: import("../semantic/types.js").SemanticLanguage, ownership: "application" | "facade", source: string}} ProgramSource */
|
|
23
32
|
/** @typedef {{declarationLocation?: import("../semantic/types.js").SourceLocation, facade?: import("../stdlib-facades.js").StdlibFacadeRecord, importedName: string, importedNameLocation?: import("../semantic/types.js").SourceLocation, localName: string, localNameLocation?: import("../semantic/types.js").SourceLocation, location: import("../semantic/types.js").SourceLocation, namespace?: boolean, pathLocation: import("../semantic/types.js").SourceLocation, specifier: string, stdlibCandidate?: true, typeOnly: boolean}} ProgramImportRequest */
|
|
24
33
|
/** @typedef {{importedName: string, localName: string, location: import("../semantic/types.js").SourceLocation, nativeName: string, symbolKind: import("../semantic/types.js").SemanticDeclarationKind, typeOnly: boolean}} ProgramNativeBinding */
|
package/src/language-registry.js
CHANGED
|
@@ -5,6 +5,7 @@ import {SemantifoldDiagnostic, unsupportedRole} from "./diagnostic.js"
|
|
|
5
5
|
import {generateJava} from "./backends/java.js"
|
|
6
6
|
import {generateKotlin} from "./backends/kotlin.js"
|
|
7
7
|
import {generateCSharpProject} from "./backends/csharp.js"
|
|
8
|
+
import {createCSharpCheckPlan} from "./backends/csharp-check.js"
|
|
8
9
|
import {generateGoModule} from "./backends/go.js"
|
|
9
10
|
import {generateRustProject} from "./backends/rust.js"
|
|
10
11
|
import {generateSwift} from "./backends/swift.js"
|
|
@@ -35,12 +36,27 @@ import {parseJavaScriptTypeScript} from "./frontends/javascript-typescript.js"
|
|
|
35
36
|
import {parsePhp} from "./frontends/php.js"
|
|
36
37
|
import {parsePython} from "./frontends/python.js"
|
|
37
38
|
import {parseRuby} from "./frontends/ruby.js"
|
|
39
|
+
import {createJavaCheckPlan} from "./backends/java-check.js"
|
|
40
|
+
import {createJavaScriptCheckPlan} from "./backends/javascript-check.js"
|
|
41
|
+
import {createKotlinCheckPlan} from "./backends/kotlin-check.js"
|
|
42
|
+
import {createPhpCheckPlan} from "./backends/php-check.js"
|
|
43
|
+
import {createPythonCheckPlan} from "./backends/python-check.js"
|
|
44
|
+
import {createRubyCheckPlan} from "./backends/ruby-check.js"
|
|
45
|
+
import {createTypeScriptCheckPlan} from "./backends/typescript-check.js"
|
|
46
|
+
import {createGoCheckPlan} from "./backends/go-check.js"
|
|
47
|
+
import {createCCheckPlan} from "./backends/c-check.js"
|
|
48
|
+
import {createCppCheckPlan} from "./backends/cpp-check.js"
|
|
49
|
+
import {createRustCheckPlan} from "./backends/rust-check.js"
|
|
50
|
+
import {createSwiftCheckPlan} from "./backends/swift-check.js"
|
|
51
|
+
import {createDartCheckPlan} from "./backends/dart-check.js"
|
|
52
|
+
import {createZigCheckPlan} from "./backends/zig-check.js"
|
|
38
53
|
|
|
39
54
|
const registryRoles = Object.freeze(["frontend", "textBackend", "binaryBackend", "applicationBackend", "interoperability"])
|
|
40
55
|
const acceptanceStageOrder = ["parse", "generate", "restore", "compile", "link", "validate", "instantiate", "execute"]
|
|
41
56
|
const acceptanceStages = new Map(acceptanceStageOrder.map((stage, index) => [stage, index]))
|
|
57
|
+
const developerCheckStages = new Set(["restore", "compile", "link", "validate"])
|
|
42
58
|
const registryKeys = new Set([
|
|
43
|
-
"acceptance", "applicationBackend", "artifactMultiplicity", "binaryBackend", "defaultFilename", "frontend", "id",
|
|
59
|
+
"acceptance", "applicationBackend", "artifactMultiplicity", "binaryBackend", "check", "defaultFilename", "frontend", "id",
|
|
44
60
|
"features", "interoperability", "mapping", "mediaType", "provider", "roundTrip", "textBackend"
|
|
45
61
|
])
|
|
46
62
|
|
|
@@ -65,6 +81,7 @@ const registryKeys = new Set([
|
|
|
65
81
|
* @typedef LanguageRegistryRecord
|
|
66
82
|
* @property {string} id - Stable identity.
|
|
67
83
|
* @property {{stages: import("./semantic/types.js").AcceptanceStage[], toolchains: string[]}} acceptance - Acceptance declaration.
|
|
84
|
+
* @property {Readonly<LanguageRegistryCheckRecord>} check - Developer-check declaration.
|
|
68
85
|
* @property {"single" | "multiple"} artifactMultiplicity - Artifact multiplicity.
|
|
69
86
|
* @property {import("./semantic/types.js").LanguageFeatureCapabilities} features - Semantic feature capabilities.
|
|
70
87
|
* @property {import("./semantic/types.js").LanguageMappingCapabilities} mapping - Mapping capabilities.
|
|
@@ -79,6 +96,31 @@ const registryKeys = new Set([
|
|
|
79
96
|
* @property {RegistryImplementation} [interoperability] - Interoperability bridge.
|
|
80
97
|
*/
|
|
81
98
|
|
|
99
|
+
/**
|
|
100
|
+
* @typedef {Readonly<{
|
|
101
|
+
* artifacts: import("./semantic/types.js").GeneratedArtifactSet,
|
|
102
|
+
* buildPath: string,
|
|
103
|
+
* projectId: string,
|
|
104
|
+
* sourcePath: string,
|
|
105
|
+
* targetId: string,
|
|
106
|
+
* tools: readonly import("./semantic/types.js").DiscoveredToolchain[]
|
|
107
|
+
* }>} TargetCheckPlanContext
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @callback TargetCheckPlanFactory
|
|
112
|
+
* @param {TargetCheckPlanContext} context - Exact staged target context.
|
|
113
|
+
* @returns {import("./semantic/types.js").TargetCheckPlan} Immutable plan.
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @typedef LanguageRegistryCheckRecord
|
|
118
|
+
* @property {TargetCheckPlanFactory} [factory] - Target-owned plan factory for supported checks.
|
|
119
|
+
* @property {readonly import("./semantic/types.js").AcceptanceStage[]} stages - Exact non-executing stages.
|
|
120
|
+
* @property {boolean} supported - Whether the target supplies a check plan.
|
|
121
|
+
* @property {readonly string[]} toolchains - Exact declared canonical toolchains.
|
|
122
|
+
*/
|
|
123
|
+
|
|
82
124
|
/**
|
|
83
125
|
* @typedef LanguageRegistry
|
|
84
126
|
* @property {readonly import("./semantic/types.js").LanguageCapabilities[]} descriptors - Public descriptors.
|
|
@@ -218,6 +260,52 @@ export function createLanguageRegistry(candidateRecords) {
|
|
|
218
260
|
if (new Set(toolchains).size != toolchains.length) {
|
|
219
261
|
invalidRegistry(`Registry record '${id}' has duplicate acceptance toolchains.`, id)
|
|
220
262
|
}
|
|
263
|
+
const checkCandidate = candidate.check
|
|
264
|
+
/** @type {Readonly<LanguageRegistryCheckRecord>} */
|
|
265
|
+
let check
|
|
266
|
+
|
|
267
|
+
if (checkCandidate === undefined) {
|
|
268
|
+
check = deepFreeze({stages: [], supported: false, toolchains: []})
|
|
269
|
+
} else {
|
|
270
|
+
if (!isPlainObject(checkCandidate) || Object.keys(checkCandidate).sort().join(",") != "factory,stages,toolchains" ||
|
|
271
|
+
typeof checkCandidate.factory != "function" || !isDenseArray(checkCandidate.stages) ||
|
|
272
|
+
!isDenseArray(checkCandidate.toolchains) || checkCandidate.stages.length == 0) {
|
|
273
|
+
invalidRegistry(`Registry record '${id}' has an invalid developer-check declaration.`, id)
|
|
274
|
+
}
|
|
275
|
+
/** @type {unknown[]} */
|
|
276
|
+
const checkStageSnapshot = []
|
|
277
|
+
/** @type {unknown[]} */
|
|
278
|
+
const checkToolchainSnapshot = []
|
|
279
|
+
|
|
280
|
+
for (let index = 0; index < checkCandidate.stages.length; index += 1) {
|
|
281
|
+
checkStageSnapshot.push(checkCandidate.stages[index])
|
|
282
|
+
}
|
|
283
|
+
for (let index = 0; index < checkCandidate.toolchains.length; index += 1) {
|
|
284
|
+
checkToolchainSnapshot.push(checkCandidate.toolchains[index])
|
|
285
|
+
}
|
|
286
|
+
if (!checkStageSnapshot.every(stage => typeof stage == "string" && developerCheckStages.has(stage) &&
|
|
287
|
+
declaredStages.has(stage)) || !checkToolchainSnapshot.every(toolchain => typeof toolchain == "string" &&
|
|
288
|
+
toolchains.includes(toolchain)) || new Set(checkStageSnapshot).size != checkStageSnapshot.length ||
|
|
289
|
+
new Set(checkToolchainSnapshot).size != checkToolchainSnapshot.length) {
|
|
290
|
+
invalidRegistry(`Registry record '${id}' developer checks must use ordered non-executing declared stages and toolchains.`, id)
|
|
291
|
+
}
|
|
292
|
+
let previousCheckStage = -1
|
|
293
|
+
|
|
294
|
+
for (const stage of checkStageSnapshot) {
|
|
295
|
+
const stageIndex = /** @type {number} */ (acceptanceStages.get(/** @type {string} */ (stage)))
|
|
296
|
+
|
|
297
|
+
if (stageIndex < previousCheckStage) {
|
|
298
|
+
invalidRegistry(`Registry record '${id}' has unordered developer-check stages.`, id)
|
|
299
|
+
}
|
|
300
|
+
previousCheckStage = stageIndex
|
|
301
|
+
}
|
|
302
|
+
check = deepFreeze({
|
|
303
|
+
factory: /** @type {TargetCheckPlanFactory} */ (checkCandidate.factory),
|
|
304
|
+
stages: /** @type {import("./semantic/types.js").AcceptanceStage[]} */ (checkStageSnapshot),
|
|
305
|
+
supported: true,
|
|
306
|
+
toolchains: /** @type {string[]} */ (checkToolchainSnapshot)
|
|
307
|
+
})
|
|
308
|
+
}
|
|
221
309
|
|
|
222
310
|
const hasFrontend = typeof candidate.frontend == "function"
|
|
223
311
|
const hasTextBackend = typeof candidate.textBackend == "function"
|
|
@@ -225,6 +313,10 @@ export function createLanguageRegistry(candidateRecords) {
|
|
|
225
313
|
const hasApplicationBackend = typeof candidate.applicationBackend == "function"
|
|
226
314
|
const hasBackend = hasTextBackend || hasBinaryBackend || hasApplicationBackend
|
|
227
315
|
|
|
316
|
+
if (check.supported && !hasBackend) {
|
|
317
|
+
invalidRegistry(`Registry record '${id}' declares developer checks without a backend role.`, id)
|
|
318
|
+
}
|
|
319
|
+
|
|
228
320
|
if ((mapping.richText || mapping.sourceMapV3 || mapping.binaryRanges) && !hasBackend ||
|
|
229
321
|
mapping.sourceMapV3 && !mapping.richText ||
|
|
230
322
|
mapping.binaryRanges && !hasBinaryBackend && !hasApplicationBackend) {
|
|
@@ -255,6 +347,7 @@ export function createLanguageRegistry(candidateRecords) {
|
|
|
255
347
|
const record = deepFreeze(/** @type {LanguageRegistryRecord} */ ({
|
|
256
348
|
acceptance,
|
|
257
349
|
artifactMultiplicity,
|
|
350
|
+
check,
|
|
258
351
|
features,
|
|
259
352
|
id,
|
|
260
353
|
mapping,
|
|
@@ -271,6 +364,7 @@ export function createLanguageRegistry(candidateRecords) {
|
|
|
271
364
|
const descriptor = deepFreeze(/** @type {import("./semantic/types.js").LanguageCapabilities} */ ({
|
|
272
365
|
acceptance,
|
|
273
366
|
artifactMultiplicity,
|
|
367
|
+
check: deepFreeze({stages: check.stages, supported: check.supported, toolchains: check.toolchains}),
|
|
274
368
|
features,
|
|
275
369
|
id,
|
|
276
370
|
mapping,
|
|
@@ -384,7 +478,8 @@ const zigFrontend = ({filename, source}) => parseZig({filename, source})
|
|
|
384
478
|
|
|
385
479
|
const records = [
|
|
386
480
|
language({
|
|
387
|
-
acceptance: {stages: ["parse", "generate", "execute"], toolchains: ["php82"]},
|
|
481
|
+
acceptance: {stages: ["parse", "generate", "validate", "execute"], toolchains: ["php82"]},
|
|
482
|
+
check: {factory: createPhpCheckPlan, stages: ["validate"], toolchains: ["php82"]},
|
|
388
483
|
defaultFilename: "program.php",
|
|
389
484
|
frontend: phpFrontend,
|
|
390
485
|
id: "php",
|
|
@@ -392,7 +487,8 @@ const records = [
|
|
|
392
487
|
textBackend: generatePhp
|
|
393
488
|
}),
|
|
394
489
|
language({
|
|
395
|
-
acceptance: {stages: ["parse", "generate", "execute"], toolchains: ["ruby"]},
|
|
490
|
+
acceptance: {stages: ["parse", "generate", "validate", "execute"], toolchains: ["ruby"]},
|
|
491
|
+
check: {factory: createRubyCheckPlan, stages: ["validate"], toolchains: ["ruby"]},
|
|
396
492
|
defaultFilename: "program.rb",
|
|
397
493
|
frontend: rubyFrontend,
|
|
398
494
|
id: "ruby",
|
|
@@ -400,7 +496,8 @@ const records = [
|
|
|
400
496
|
textBackend: generateRuby
|
|
401
497
|
}),
|
|
402
498
|
language({
|
|
403
|
-
acceptance: {stages: ["parse", "generate", "execute"], toolchains: ["node"]},
|
|
499
|
+
acceptance: {stages: ["parse", "generate", "validate", "execute"], toolchains: ["node"]},
|
|
500
|
+
check: {factory: createJavaScriptCheckPlan, stages: ["validate"], toolchains: ["node"]},
|
|
404
501
|
defaultFilename: "program.js",
|
|
405
502
|
frontend: javaScriptFrontend,
|
|
406
503
|
id: "javascript",
|
|
@@ -409,6 +506,7 @@ const records = [
|
|
|
409
506
|
}),
|
|
410
507
|
language({
|
|
411
508
|
acceptance: {stages: ["parse", "generate", "compile", "execute"], toolchains: ["tsc", "node"]},
|
|
509
|
+
check: {factory: createTypeScriptCheckPlan, stages: ["compile"], toolchains: ["tsc"]},
|
|
412
510
|
defaultFilename: "program.ts",
|
|
413
511
|
frontend: typeScriptFrontend,
|
|
414
512
|
id: "typescript",
|
|
@@ -417,6 +515,7 @@ const records = [
|
|
|
417
515
|
}),
|
|
418
516
|
language({
|
|
419
517
|
acceptance: {stages: ["parse", "generate", "compile", "execute"], toolchains: ["javac", "java"]},
|
|
518
|
+
check: {factory: createJavaCheckPlan, stages: ["compile"], toolchains: ["javac"]},
|
|
420
519
|
defaultFilename: "Main.java",
|
|
421
520
|
frontend: javaFrontend,
|
|
422
521
|
id: "java",
|
|
@@ -425,6 +524,7 @@ const records = [
|
|
|
425
524
|
}),
|
|
426
525
|
language({
|
|
427
526
|
acceptance: {stages: ["parse", "generate", "compile", "execute"], toolchains: ["kotlinc", "java25"]},
|
|
527
|
+
check: {factory: createKotlinCheckPlan, stages: ["compile"], toolchains: ["kotlinc"]},
|
|
428
528
|
defaultFilename: "Program.kt",
|
|
429
529
|
frontend: kotlinFrontend,
|
|
430
530
|
id: "kotlin",
|
|
@@ -433,6 +533,7 @@ const records = [
|
|
|
433
533
|
}),
|
|
434
534
|
language({
|
|
435
535
|
acceptance: {stages: ["parse", "generate", "compile", "execute"], toolchains: ["python"]},
|
|
536
|
+
check: {factory: createPythonCheckPlan, stages: ["compile"], toolchains: ["python"]},
|
|
436
537
|
defaultFilename: "program.py",
|
|
437
538
|
frontend: pythonFrontend,
|
|
438
539
|
id: "python",
|
|
@@ -442,6 +543,7 @@ const records = [
|
|
|
442
543
|
language({
|
|
443
544
|
acceptance: {stages: ["parse", "generate", "restore", "compile", "execute"], toolchains: ["dotnet"]},
|
|
444
545
|
artifactMultiplicity: "multiple",
|
|
546
|
+
check: {factory: createCSharpCheckPlan, stages: ["restore", "compile"], toolchains: ["dotnet"]},
|
|
445
547
|
defaultFilename: "Program.cs",
|
|
446
548
|
frontend: csharpFrontend,
|
|
447
549
|
id: "csharp",
|
|
@@ -451,6 +553,7 @@ const records = [
|
|
|
451
553
|
language({
|
|
452
554
|
acceptance: {stages: ["parse", "generate", "compile", "validate", "execute"], toolchains: ["go"]},
|
|
453
555
|
artifactMultiplicity: "multiple",
|
|
556
|
+
check: {factory: createGoCheckPlan, stages: ["compile", "validate"], toolchains: ["go"]},
|
|
454
557
|
defaultFilename: "main.go",
|
|
455
558
|
frontend: goFrontend,
|
|
456
559
|
id: "go",
|
|
@@ -460,6 +563,7 @@ const records = [
|
|
|
460
563
|
language({
|
|
461
564
|
acceptance: {stages: ["parse", "generate", "compile", "link", "execute"], toolchains: ["clang"]},
|
|
462
565
|
artifactMultiplicity: "multiple",
|
|
566
|
+
check: {factory: createCCheckPlan, stages: ["compile", "link"], toolchains: ["clang"]},
|
|
463
567
|
defaultFilename: "program.c",
|
|
464
568
|
frontend: parseC,
|
|
465
569
|
id: "c",
|
|
@@ -468,18 +572,22 @@ const records = [
|
|
|
468
572
|
}),
|
|
469
573
|
language({
|
|
470
574
|
acceptance: {stages: ["parse", "generate", "compile", "link", "execute"], toolchains: ["clangpp"]},
|
|
575
|
+
check: {factory: createCppCheckPlan, stages: ["compile", "link"], toolchains: ["clangpp"]},
|
|
471
576
|
defaultFilename: "program.cpp", frontend: parseCpp, id: "cpp", mediaType: "text/x-c++src", textBackend: generateCpp
|
|
472
577
|
}),
|
|
473
578
|
language({
|
|
474
579
|
acceptance: {stages: ["parse", "generate", "compile", "validate", "execute"], toolchains: ["rustc", "cargo"]},
|
|
475
580
|
artifactMultiplicity: "multiple",
|
|
581
|
+
check: {factory: createRustCheckPlan, stages: ["compile", "validate"], toolchains: ["rustc", "cargo"]},
|
|
476
582
|
defaultFilename: "src/main.rs", frontend: parseRust, id: "rust", mediaType: "text/x-rust", textBackend: generateRustProject
|
|
477
583
|
}),
|
|
478
584
|
language({acceptance: {stages: ["parse", "generate", "compile", "execute"], toolchains: ["swiftc"]},
|
|
585
|
+
check: {factory: createSwiftCheckPlan, stages: ["compile"], toolchains: ["swiftc"]},
|
|
479
586
|
defaultFilename: "program.swift", frontend: parseSwift, id: "swift", mediaType: "text/x-swift", textBackend: generateSwift}),
|
|
480
587
|
language({
|
|
481
588
|
acceptance: {stages: ["parse", "generate", "restore", "compile", "validate", "execute"], toolchains: ["dart"]},
|
|
482
589
|
artifactMultiplicity: "multiple",
|
|
590
|
+
check: {factory: createDartCheckPlan, stages: ["restore", "compile", "validate"], toolchains: ["dart"]},
|
|
483
591
|
defaultFilename: "bin/program.dart",
|
|
484
592
|
features: {
|
|
485
593
|
closedRecords: false,
|
|
@@ -502,6 +610,7 @@ const records = [
|
|
|
502
610
|
language({
|
|
503
611
|
acceptance: {stages: ["parse", "generate", "compile", "validate", "execute"], toolchains: ["zig"]},
|
|
504
612
|
artifactMultiplicity: "multiple",
|
|
613
|
+
check: {factory: createZigCheckPlan, stages: ["compile", "validate"], toolchains: ["zig"]},
|
|
505
614
|
defaultFilename: "src/main.zig",
|
|
506
615
|
features: {
|
|
507
616
|
closedRecords: false,
|