@fraczak/k 6.3.3 → 6.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/CHANGELOG.md +17 -0
- package/DOCS/CODECS.md +258 -0
- package/DOCS/DICTIONARY.md +1172 -0
- package/DOCS/KIR_SPECIALIZATION_DESIGN.md +51 -46
- package/DOCS/KIR_V1.md +221 -0
- package/DOCS/KVM_EXECUTION_MODEL.md +56 -19
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +2 -1
- package/DOCS/PROFILING_AND_TRACING.md +196 -0
- package/DOCS/REPL.md +61 -4
- package/DOCS/WEB_REPL_REQUIREMENTS.md +135 -0
- package/DOCS/dependency-graph.md +144 -0
- package/Examples/arithmetics.k +108 -82
- package/Examples/bnat.k +1 -1
- package/Examples/buda.k +44 -0
- package/Examples/ieee.k +300 -8671
- package/Examples/poly.k +67 -0
- package/README.md +68 -19
- package/Value.mjs +8 -2
- package/augmentation.mjs +9 -7
- package/backend-api.mjs +11 -2
- package/backends/arm64/README.md +104 -0
- package/backends/arm64/bin/k-arm64-compile.mjs +101 -0
- package/backends/arm64/bin/k-arm64-run.mjs +58 -0
- package/backends/arm64/bin/k-arm64.mjs +88 -0
- package/backends/arm64/scripts/run-tests.mjs +41 -0
- package/backends/arm64/src/arm64.mjs +229 -0
- package/backends/arm64/src/cli.mjs +155 -0
- package/backends/arm64/src/kvm2arm64.mjs +906 -0
- package/backends/arm64/src/runtime.c +728 -0
- package/backends/arm64/tests/integration.sh +112 -0
- package/backends/arm64/tests/test-arm64.mjs +240 -0
- package/backends/llvm/README.md +135 -0
- package/backends/llvm/bin/k-llvm-build.mjs +71 -0
- package/backends/llvm/bin/k-llvm-compile.mjs +68 -0
- package/backends/llvm/bin/k-llvm-jit.mjs +160 -0
- package/backends/llvm/bin/k-llvm-run.mjs +90 -0
- package/backends/llvm/runtime/krt.c +1508 -0
- package/backends/llvm/runtime/krt.h +109 -0
- package/backends/llvm/scripts/conformance.mjs +76 -0
- package/backends/llvm/scripts/run-tests.mjs +28 -0
- package/backends/llvm/src/executable.mjs +562 -0
- package/backends/llvm/src/kvm2llvm.mjs +998 -0
- package/backends/llvm/src/llvm.mjs +1092 -0
- package/backends/llvm/tests/composition-driver.c +22 -0
- package/backends/llvm/tests/identity-driver.c +27 -0
- package/backends/llvm/tests/integration.sh +153 -0
- package/backends/llvm/tests/perf-support.mjs +735 -0
- package/backends/llvm/tests/product-driver.c +23 -0
- package/backends/llvm/tests/projection-driver.c +19 -0
- package/backends/llvm/tests/relation-driver.c +29 -0
- package/backends/llvm/tests/test-llvm.mjs +240 -0
- package/backends/llvm/tests/union-driver.c +31 -0
- package/backends/llvm/tests/variant-driver.c +19 -0
- package/backends/llvm/tests/variant-projection-driver.c +21 -0
- package/backends/wasm/DOCS/USE-WEB-ASSEMBLY.md +233 -0
- package/backends/wasm/README.md +97 -0
- package/backends/wasm/TECHNICAL-DEBT.md +58 -0
- package/backends/wasm/bin/k-wasm-compile.mjs +50 -0
- package/backends/wasm/bin/k-wasm-run.mjs +140 -0
- package/backends/wasm/bin/k-wasm.mjs +49 -0
- package/backends/wasm/demo_ieee.mjs +319 -0
- package/backends/wasm/runtime.wat +475 -0
- package/backends/wasm/scripts/run-tests.mjs +41 -0
- package/backends/wasm/src/cli.mjs +133 -0
- package/backends/wasm/src/kvm2wasm.mjs +697 -0
- package/backends/wasm/src/wasm.mjs +1054 -0
- package/backends/wasm/tests/integration.sh +182 -0
- package/backends/wasm/tests/perf-support.mjs +336 -0
- package/backends/wasm/tests/test-wasm.mjs +625 -0
- package/browser/repl-browser.mjs +1584 -0
- package/browser/shims/assert.mjs +19 -0
- package/browser/shims/buffer.mjs +224 -0
- package/browser/shims/crypto.mjs +103 -0
- package/browser/shims/fs.mjs +159 -0
- package/browser/shims/os.mjs +17 -0
- package/browser/shims/path.mjs +54 -0
- package/browser/shims/process.mjs +44 -0
- package/browser/shims/readline.mjs +11 -0
- package/browser/shims/url.mjs +12 -0
- package/browser/vfs-data.mjs +19 -0
- package/codecs/README.md +3 -0
- package/codecs/runtime/show-value.mjs +12 -3
- package/conformance/helper-reuse/case.json +8 -0
- package/conformance/helper-reuse/expected.kv +1 -0
- package/conformance/helper-reuse/input.kv +1 -0
- package/conformance/helper-reuse/program.k +2 -0
- package/conformance/identity/case.json +8 -0
- package/conformance/identity/expected.kv +1 -0
- package/conformance/identity/input.kv +1 -0
- package/conformance/identity/program.k +1 -0
- package/conformance/product-projection/case.json +8 -0
- package/conformance/product-projection/expected.kv +1 -0
- package/conformance/product-projection/input.kv +1 -0
- package/conformance/product-projection/program.k +1 -0
- package/conformance/run.mjs +149 -0
- package/conformance/variant-construction/case.json +8 -0
- package/conformance/variant-construction/expected.kv +1 -0
- package/conformance/variant-construction/input.kv +1 -0
- package/conformance/variant-construction/program.k +1 -0
- package/harness/adapters/arm64.mjs +105 -0
- package/harness/adapters/kvm.mjs +144 -0
- package/harness/adapters/llvm.mjs +118 -0
- package/harness/adapters/native.mjs +77 -0
- package/harness/adapters/wasm.mjs +169 -0
- package/harness/backend.mjs +95 -0
- package/harness/cli.mjs +130 -0
- package/harness/format.mjs +95 -0
- package/harness/index.mjs +25 -0
- package/harness/persistent.mjs +121 -0
- package/harness/registry.mjs +44 -0
- package/harness/suite.mjs +257 -0
- package/harness/suites/poly.mjs +156 -0
- package/harness/trace.mjs +50 -0
- package/harness/util.mjs +92 -0
- package/intrinsics.mjs +41 -0
- package/kir.mjs +399 -0
- package/kvm.mjs +585 -81
- package/objects/README.md +37 -3
- package/objects/compile.mjs +15 -22
- package/objects/inspect.mjs +96 -0
- package/objects/validate.mjs +415 -0
- package/package.json +51 -19
- package/repl-codecs.mjs +105 -6
- package/repl.mjs +335 -49
- package/run.mjs +2 -7
- package/scripts/benchmark.mjs +406 -22
- package/scripts/build-repl-html.mjs +1784 -0
- package/scripts/perf-ieee.mjs +586 -0
- package/scripts/perf-int.mjs +531 -0
- package/scripts/perf-poly.mjs +945 -0
- package/scripts/render-benchmark.mjs +12 -8
- package/scripts/run-tests.mjs +6 -0
- package/tests/integration.sh +19 -2
- package/tests/test-arithmetics.mjs +54 -0
- package/tests/test-ieee-arithmetic.mjs +4 -0
- package/tests/test-kir.mjs +85 -0
- package/tests/test-kvm-polymorphic.mjs +278 -0
- package/tests/test-kvm.mjs +25 -6
- package/tests/test-poly.mjs +129 -0
- package/tests/test-repl-html.mjs +303 -0
- package/tests/test-repl.mjs +144 -1
- package/tests/test-validate-object.mjs +40 -0
- package/a.klib +0 -1
- package/a.kvm +0 -142676
- package/a.wasm +0 -0
- package/benchmark-results.html +0 -532
- package/benchmark-results.json +0 -480
- package/k-vscode/.vscode/launch.json +0 -14
- package/k-vscode/README.md +0 -75
- package/k-vscode/extension.js +0 -273
- package/k-vscode/language-configuration.json +0 -42
- package/k-vscode/package.json +0 -79
- package/k-vscode/snippets/k.json +0 -92
- package/k-vscode/syntaxes/k.tmLanguage.json +0 -599
- package/k-vscode/test/background-ranges.test.js +0 -50
- package/k-vscode/themes/k-contrast-color-theme.json +0 -104
- package/scripts/git-hooks/pre-commit +0 -10
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { spawn } from "node:child_process";
|
|
8
|
+
import { argv, exit, stdin, stdout } from "node:process";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { decodeObject } from "@fraczak/k/object.mjs";
|
|
11
|
+
import { decodeWire } from "@fraczak/k/codecs/runtime/prefix-codec.mjs";
|
|
12
|
+
import { compileObjectToExecutable } from "../src/executable.mjs";
|
|
13
|
+
|
|
14
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
|
+
|
|
16
|
+
function usage(stream = console.error) {
|
|
17
|
+
const prog = argv[1] || "k-llvm-jit.mjs";
|
|
18
|
+
stream(`Usage: node ${prog} [options] object-file`);
|
|
19
|
+
stream("Compile and execute a k .ko/.klib object against the stdin binary envelope.");
|
|
20
|
+
stream("");
|
|
21
|
+
stream("The runner reads a binary k pattern+value envelope from stdin, specializes");
|
|
22
|
+
stream("the object with that envelope pattern, then writes a binary envelope to stdout.");
|
|
23
|
+
stream("");
|
|
24
|
+
stream("Options:");
|
|
25
|
+
stream(" --retype rel Relation to specialize. Defaults to object main.");
|
|
26
|
+
stream(" --cache-dir path Directory for compiled native executables.");
|
|
27
|
+
stream(" --no-cache Compile in a temporary directory and remove it after execution.");
|
|
28
|
+
stream(" -h, --help Show this help.");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function readStdinBuffer() {
|
|
32
|
+
const chunks = [];
|
|
33
|
+
for await (const chunk of stdin) {
|
|
34
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
35
|
+
}
|
|
36
|
+
return Buffer.concat(chunks);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let cachedBackendFingerprint = null;
|
|
40
|
+
|
|
41
|
+
function backendFingerprint() {
|
|
42
|
+
if (cachedBackendFingerprint != null) return cachedBackendFingerprint;
|
|
43
|
+
const hash = crypto.createHash("sha256");
|
|
44
|
+
for (const relPath of ["src/llvm.mjs", "src/kvm2llvm.mjs", "src/executable.mjs", "runtime/krt.c", "runtime/krt.h"]) {
|
|
45
|
+
hash.update(relPath);
|
|
46
|
+
hash.update("\0");
|
|
47
|
+
hash.update(fs.readFileSync(path.join(root, relPath)));
|
|
48
|
+
hash.update("\0");
|
|
49
|
+
}
|
|
50
|
+
cachedBackendFingerprint = hash.digest("hex").slice(0, 16);
|
|
51
|
+
return cachedBackendFingerprint;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function cacheKey({ objectBuffer, relation, inputPattern }) {
|
|
55
|
+
const hash = crypto.createHash("sha256");
|
|
56
|
+
hash.update("k-llvm-jit-v2\0");
|
|
57
|
+
hash.update(backendFingerprint());
|
|
58
|
+
hash.update("\0");
|
|
59
|
+
hash.update(relation);
|
|
60
|
+
hash.update("\0");
|
|
61
|
+
hash.update(JSON.stringify(inputPattern));
|
|
62
|
+
hash.update("\0");
|
|
63
|
+
hash.update(objectBuffer);
|
|
64
|
+
return hash.digest("hex");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function runExecutable(exePath, inputBuffer) {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
const child = spawn(exePath, [], { stdio: ["pipe", "pipe", "pipe"] });
|
|
70
|
+
const stdoutChunks = [];
|
|
71
|
+
const stderrChunks = [];
|
|
72
|
+
|
|
73
|
+
child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
74
|
+
child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
|
|
75
|
+
child.on("error", reject);
|
|
76
|
+
child.on("close", (status) => {
|
|
77
|
+
if (status !== 0) {
|
|
78
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf8");
|
|
79
|
+
reject(new Error(`${exePath} failed with status ${status}${stderr ? `\n${stderr}` : ""}`));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
resolve(Buffer.concat(stdoutChunks));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
child.stdin.end(inputBuffer);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function compileCached({ object, objectBuffer, relation, inputPattern, cacheDir }) {
|
|
90
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
91
|
+
const key = cacheKey({ objectBuffer, relation, inputPattern });
|
|
92
|
+
const exePath = path.join(cacheDir, `${key}.exe`);
|
|
93
|
+
if (!fs.existsSync(exePath)) {
|
|
94
|
+
const tmpPath = path.join(cacheDir, `${key}.${process.pid}.tmp`);
|
|
95
|
+
compileObjectToExecutable(object, tmpPath, { relation, inputPattern });
|
|
96
|
+
fs.renameSync(tmpPath, exePath);
|
|
97
|
+
}
|
|
98
|
+
return exePath;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function compileTemporary({ object, relation, inputPattern }) {
|
|
102
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "k-llvm-jit-"));
|
|
103
|
+
const exePath = path.join(tmpDir, "program");
|
|
104
|
+
compileObjectToExecutable(object, exePath, { relation, inputPattern });
|
|
105
|
+
return { exePath, tmpDir };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const args = argv.slice(2);
|
|
110
|
+
if (args.includes("-h") || args.includes("--help")) {
|
|
111
|
+
usage(console.log);
|
|
112
|
+
exit(0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let relation = null;
|
|
116
|
+
let cacheDir = path.join(os.tmpdir(), "k-llvm-jit-cache");
|
|
117
|
+
let useCache = true;
|
|
118
|
+
while (args.length > 0 && args[0].startsWith("--")) {
|
|
119
|
+
const option = args.shift();
|
|
120
|
+
if (option === "--retype") {
|
|
121
|
+
relation = args.shift();
|
|
122
|
+
if (!relation) throw new Error("--retype requires a relation name");
|
|
123
|
+
} else if (option === "--cache-dir") {
|
|
124
|
+
cacheDir = args.shift();
|
|
125
|
+
if (!cacheDir) throw new Error("--cache-dir requires a path");
|
|
126
|
+
} else if (option === "--no-cache") {
|
|
127
|
+
useCache = false;
|
|
128
|
+
} else {
|
|
129
|
+
throw new Error(`Unknown option: ${option}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const objectPath = args.shift() || null;
|
|
134
|
+
if (objectPath == null) throw new Error("object-file is required");
|
|
135
|
+
if (args.length > 0) throw new Error(`Unexpected argument: ${args[0]}`);
|
|
136
|
+
|
|
137
|
+
const objectBuffer = fs.readFileSync(objectPath);
|
|
138
|
+
const object = decodeObject(objectBuffer);
|
|
139
|
+
const relationName = relation || object.main;
|
|
140
|
+
const inputBuffer = await readStdinBuffer();
|
|
141
|
+
const { pattern: inputPattern } = decodeWire(inputBuffer);
|
|
142
|
+
|
|
143
|
+
let tmpDir = null;
|
|
144
|
+
try {
|
|
145
|
+
const exePath = useCache
|
|
146
|
+
? compileCached({ object, objectBuffer, relation: relationName, inputPattern, cacheDir })
|
|
147
|
+
: (() => {
|
|
148
|
+
const compiled = compileTemporary({ object, relation: relationName, inputPattern });
|
|
149
|
+
tmpDir = compiled.tmpDir;
|
|
150
|
+
return compiled.exePath;
|
|
151
|
+
})();
|
|
152
|
+
stdout.write(await runExecutable(exePath, inputBuffer));
|
|
153
|
+
} finally {
|
|
154
|
+
if (tmpDir != null) fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
155
|
+
}
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error(error.stack || error.message || String(error));
|
|
158
|
+
usage();
|
|
159
|
+
exit(1);
|
|
160
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { argv, exit, stdin, stdout } from "node:process";
|
|
5
|
+
import { decodeObject } from "@fraczak/k/object.mjs";
|
|
6
|
+
import { parseValue } from "@fraczak/k/valueIO.mjs";
|
|
7
|
+
import { compileObjectAndRun } from "../src/executable.mjs";
|
|
8
|
+
|
|
9
|
+
function usage(stream = console.error) {
|
|
10
|
+
const prog = argv[1] || "k-llvm-run.mjs";
|
|
11
|
+
stream(`Usage: node ${prog} [options] object-file [input.kv]`);
|
|
12
|
+
stream("Compile and execute a k .ko/.klib object through LLVM.");
|
|
13
|
+
stream("");
|
|
14
|
+
stream("Arguments:");
|
|
15
|
+
stream(" object-file Input .ko or .klib file.");
|
|
16
|
+
stream(" input.kv Input value. Reads text from stdin when omitted.");
|
|
17
|
+
stream("");
|
|
18
|
+
stream("Options:");
|
|
19
|
+
stream(" --retype rel Relation to specialize. Defaults to object main.");
|
|
20
|
+
stream(" --input-pattern value Input pattern property-list JSON, or a file containing it.");
|
|
21
|
+
stream(" --expect value Expected output value JSON/k-value text, or a file containing it.");
|
|
22
|
+
stream(" -h, --help Show this help.");
|
|
23
|
+
stream("");
|
|
24
|
+
stream("Without --expect, the runner prints the result value as compact JSON.");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function readStdinText() {
|
|
28
|
+
const chunks = [];
|
|
29
|
+
for await (const chunk of stdin) {
|
|
30
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
31
|
+
}
|
|
32
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function readMaybeFile(textOrPath) {
|
|
36
|
+
return fs.existsSync(textOrPath) ? fs.readFileSync(textOrPath, "utf8") : textOrPath;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readPattern(inputPattern) {
|
|
40
|
+
if (inputPattern == null) return null;
|
|
41
|
+
return JSON.parse(readMaybeFile(inputPattern));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const args = argv.slice(2);
|
|
46
|
+
if (args.includes("-h") || args.includes("--help")) {
|
|
47
|
+
usage(console.log);
|
|
48
|
+
exit(0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let relation = null;
|
|
52
|
+
let inputPattern = null;
|
|
53
|
+
let expectedText = null;
|
|
54
|
+
while (args.length > 0 && args[0].startsWith("--")) {
|
|
55
|
+
const option = args.shift();
|
|
56
|
+
if (option === "--retype") {
|
|
57
|
+
relation = args.shift();
|
|
58
|
+
if (!relation) throw new Error("--retype requires a relation name");
|
|
59
|
+
} else if (option === "--input-pattern") {
|
|
60
|
+
inputPattern = args.shift();
|
|
61
|
+
if (!inputPattern) throw new Error("--input-pattern requires JSON or a file path");
|
|
62
|
+
} else if (option === "--expect") {
|
|
63
|
+
expectedText = args.shift();
|
|
64
|
+
if (!expectedText) throw new Error("--expect requires a value or file path");
|
|
65
|
+
} else {
|
|
66
|
+
throw new Error(`Unknown option: ${option}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const objectPath = args.shift() || null;
|
|
71
|
+
const inputPath = args.shift() || null;
|
|
72
|
+
if (objectPath == null) throw new Error("object-file is required");
|
|
73
|
+
if (args.length > 0) throw new Error(`Unexpected argument: ${args[0]}`);
|
|
74
|
+
|
|
75
|
+
const object = decodeObject(fs.readFileSync(objectPath));
|
|
76
|
+
const inputText = inputPath == null ? await readStdinText() : fs.readFileSync(inputPath, "utf8");
|
|
77
|
+
const input = parseValue(inputText);
|
|
78
|
+
const expected = expectedText == null ? null : parseValue(readMaybeFile(expectedText));
|
|
79
|
+
const result = compileObjectAndRun(object, {
|
|
80
|
+
relation: relation || object.main,
|
|
81
|
+
input,
|
|
82
|
+
expected,
|
|
83
|
+
inputPattern: readPattern(inputPattern)
|
|
84
|
+
});
|
|
85
|
+
stdout.write(expected == null ? result.stdout : "OK\n");
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error(error.stack || error.message || String(error));
|
|
88
|
+
usage();
|
|
89
|
+
exit(1);
|
|
90
|
+
}
|