@fraczak/k 6.10.3 → 6.10.4
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 +43 -0
- package/DOCS/FILE_FORMATS.md +51 -16
- package/Examples/karatsuba-mult.k +215 -0
- package/backends/arm64/scripts/run-tests.mjs +16 -0
- package/backends/llvm/bin/k-llvm-build.mjs +40 -14
- package/backends/llvm/bin/k-llvm-compile.mjs +29 -12
- package/backends/llvm/runtime/krt.c +10 -10
- package/backends/llvm/runtime/krt.h +6 -1
- package/backends/llvm/scripts/run-tests.mjs +16 -0
- package/backends/llvm/src/cli.mjs +1 -1
- package/backends/llvm/src/executable.mjs +36 -0
- package/backends/llvm/src/kvm2llvm.mjs +10 -4
- package/backends/llvm/tests/integration.sh +11 -0
- package/backends/llvm/tests/test-llvm.mjs +15 -1
- package/backends/wasm/scripts/run-tests.mjs +16 -0
- package/browser/vfs-data.mjs +1 -1
- package/core.k +5 -5
- package/package.json +2 -1
- package/scripts/benchmark-idempotency.mjs +27 -0
- package/scripts/benchmark.mjs +51 -0
- package/scripts/build-repl-html.mjs +17 -0
- package/scripts/generate-dependency-graph.mjs +25 -1
- package/scripts/perf-ieee.mjs +75 -0
- package/scripts/perf-int.mjs +67 -0
- package/scripts/perf-multiplication.mjs +644 -0
- package/scripts/perf-poly.mjs +67 -0
- package/scripts/render-benchmark.mjs +25 -0
- package/scripts/run-tests.mjs +19 -0
- package/tests/test-karatsuba.mjs +133 -0
|
@@ -5,6 +5,31 @@ import path from "node:path";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
7
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
8
|
+
|
|
9
|
+
function printHelp() {
|
|
10
|
+
console.log(
|
|
11
|
+
`Usage: node scripts/render-benchmark.mjs [in.json] [out.html]
|
|
12
|
+
|
|
13
|
+
Renders benchmark results JSON into a standalone interactive HTML report.
|
|
14
|
+
|
|
15
|
+
Arguments:
|
|
16
|
+
input-json
|
|
17
|
+
Path to benchmark results JSON file.
|
|
18
|
+
(default: benchmark-results.json)
|
|
19
|
+
output-html
|
|
20
|
+
Destination path for generated HTML report.
|
|
21
|
+
(default: benchmark-results.html)
|
|
22
|
+
|
|
23
|
+
Options:
|
|
24
|
+
-h, --help
|
|
25
|
+
Show this help message and exit.`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
29
|
+
printHelp();
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
|
|
8
33
|
const inputPath = path.resolve(root, process.argv[2] || "benchmark-results.json");
|
|
9
34
|
const outputPath = path.resolve(root, process.argv[3] || "benchmark-results.html");
|
|
10
35
|
|
package/scripts/run-tests.mjs
CHANGED
|
@@ -7,6 +7,24 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
|
|
8
8
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
9
9
|
const node = process.execPath;
|
|
10
|
+
|
|
11
|
+
function printHelp() {
|
|
12
|
+
console.log(`Usage: node scripts/run-tests.mjs [options]
|
|
13
|
+
|
|
14
|
+
Runs the comprehensive K language test suite, including core unit tests,
|
|
15
|
+
type derivation, codecs, object encoding, conformance, REPL, interpreter,
|
|
16
|
+
and arithmetic suites.
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
-h, --help
|
|
20
|
+
Show this help message and exit.`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
24
|
+
printHelp();
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
10
28
|
const derivationTests = fs.readdirSync(path.join(root, "tests/code-derivation"))
|
|
11
29
|
.filter((name) => name.endsWith(".mjs"))
|
|
12
30
|
.sort()
|
|
@@ -31,6 +49,7 @@ const tests = [
|
|
|
31
49
|
["tests/test-kvm.mjs", node, ["tests/test-kvm.mjs"]],
|
|
32
50
|
["tests/test-kvm-polymorphic.mjs", node, ["tests/test-kvm-polymorphic.mjs"]],
|
|
33
51
|
["tests/test-arithmetics.mjs", node, ["tests/test-arithmetics.mjs"]],
|
|
52
|
+
["tests/test-karatsuba.mjs", node, ["tests/test-karatsuba.mjs"]],
|
|
34
53
|
["tests/test-poly.mjs", node, ["tests/test-poly.mjs"]],
|
|
35
54
|
["tests/test-ieee-arithmetic.mjs", node, ["tests/test-ieee-arithmetic.mjs"]],
|
|
36
55
|
["tests/integration.sh", path.join(root, "tests/integration.sh"), []]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const root = path.resolve(scriptDir, "..");
|
|
10
|
+
const node = process.execPath;
|
|
11
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "k-karatsuba-"));
|
|
12
|
+
const libPath = path.join(tmpDir, "karatsuba-mult.klib");
|
|
13
|
+
const kSource = path.join(root, "Examples/karatsuba-mult.k");
|
|
14
|
+
const program = "{() x, () y} karatsuba";
|
|
15
|
+
|
|
16
|
+
const smallInput =
|
|
17
|
+
"111111122222233333344444445555556666667777777888888999999000000" +
|
|
18
|
+
"11111122222233333344444455555";
|
|
19
|
+
|
|
20
|
+
function run(command, args, options = {}) {
|
|
21
|
+
const result = spawnSync(command, args, {
|
|
22
|
+
cwd: root,
|
|
23
|
+
input: options.input,
|
|
24
|
+
encoding: options.encoding ?? null,
|
|
25
|
+
maxBuffer: 64 * 1024 * 1024
|
|
26
|
+
});
|
|
27
|
+
if (result.error && result.status == null) throw result.error;
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function assertOk(result, label) {
|
|
32
|
+
if (result.status !== 0) {
|
|
33
|
+
const stderr = Buffer.isBuffer(result.stderr)
|
|
34
|
+
? result.stderr.toString("utf8")
|
|
35
|
+
: String(result.stderr ?? "");
|
|
36
|
+
const stdout = Buffer.isBuffer(result.stdout)
|
|
37
|
+
? result.stdout.toString("utf8")
|
|
38
|
+
: String(result.stdout ?? "");
|
|
39
|
+
assert.fail(
|
|
40
|
+
`${label} failed (status ${result.status})\n` +
|
|
41
|
+
`STDERR:\n${stderr}\nSTDOUT:\n${stdout}`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function parseIntWire(text) {
|
|
47
|
+
const result = run(node, ["codecs/int.mjs", "--parse"], {
|
|
48
|
+
input: `${text}\n`
|
|
49
|
+
});
|
|
50
|
+
assertOk(result, `parse int ${text}`);
|
|
51
|
+
return result.stdout;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function printIntWire(wire, label) {
|
|
55
|
+
const result = run(node, ["codecs/int.mjs", "--print"], {
|
|
56
|
+
input: wire,
|
|
57
|
+
encoding: "utf8"
|
|
58
|
+
});
|
|
59
|
+
assertOk(result, `${label} print`);
|
|
60
|
+
return result.stdout.trim();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function runKaratsuba(inputText) {
|
|
64
|
+
const wire = parseIntWire(inputText);
|
|
65
|
+
const result = run(node, [
|
|
66
|
+
"k.mjs",
|
|
67
|
+
"--lib", libPath,
|
|
68
|
+
"--export", "karatsuba:karatsuba",
|
|
69
|
+
program
|
|
70
|
+
], { input: wire });
|
|
71
|
+
assertOk(result, `native karatsuba(${inputText})`);
|
|
72
|
+
return printIntWire(result.stdout, `native karatsuba`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function expectedSquare(inputText) {
|
|
76
|
+
const n = BigInt(inputText);
|
|
77
|
+
return (n * n).toString();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
assertOk(
|
|
82
|
+
run(node, ["objects/compile.mjs", kSource, libPath], {
|
|
83
|
+
encoding: "utf8"
|
|
84
|
+
}),
|
|
85
|
+
"compile Examples/karatsuba-mult.k"
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const testInputs = [
|
|
89
|
+
"0",
|
|
90
|
+
"1",
|
|
91
|
+
"-1",
|
|
92
|
+
"7",
|
|
93
|
+
"-7",
|
|
94
|
+
"42",
|
|
95
|
+
"-42",
|
|
96
|
+
"123456789",
|
|
97
|
+
"-123456789",
|
|
98
|
+
"987654321987654321",
|
|
99
|
+
"-987654321987654321",
|
|
100
|
+
smallInput,
|
|
101
|
+
`-${smallInput}`
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
for (const input of testInputs) {
|
|
105
|
+
assert.equal(
|
|
106
|
+
runKaratsuba(input),
|
|
107
|
+
expectedSquare(input),
|
|
108
|
+
`karatsuba square(${input.slice(0, 20)}...) mismatch`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Test asymmetric pair multiplication with mixed signs via int list
|
|
113
|
+
const pairWire = parseIntWire(
|
|
114
|
+
"[12345678901234567890, -98765432109876543210]"
|
|
115
|
+
);
|
|
116
|
+
const pairProgram = "/cons { .car x, .cdr /cons .car y } karatsuba";
|
|
117
|
+
const resPair = run(node, [
|
|
118
|
+
"k.mjs",
|
|
119
|
+
"--lib", libPath,
|
|
120
|
+
"--export", "karatsuba:karatsuba",
|
|
121
|
+
pairProgram
|
|
122
|
+
], { input: pairWire });
|
|
123
|
+
assertOk(resPair, "pair multiplication");
|
|
124
|
+
assert.equal(
|
|
125
|
+
printIntWire(resPair.stdout, "pair multiplication"),
|
|
126
|
+
(12345678901234567890n * -98765432109876543210n).toString(),
|
|
127
|
+
"asymmetric pair multiplication should match BigInt oracle"
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
console.log("OK");
|
|
131
|
+
} finally {
|
|
132
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
133
|
+
}
|