@fraczak/k 6.10.3 → 6.10.5
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 +78 -0
- package/DOCS/FILE_FORMATS.md +51 -16
- package/Examples/arithmetics.k +222 -110
- package/Examples/karatsuba-mult.k +215 -0
- package/Examples/poly.k +14 -5
- 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/shims/fs.mjs +12 -7
- package/browser/vfs-data.mjs +7 -10
- package/core.k +25 -18
- package/harness/suites/poly.mjs +1 -1
- package/package.json +2 -1
- package/repl-codecs.mjs +6 -3
- package/scripts/benchmark-idempotency.mjs +27 -0
- package/scripts/benchmark.mjs +51 -0
- package/scripts/build-repl-html.mjs +28 -10
- 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 +68 -1
- package/scripts/render-benchmark.mjs +25 -0
- package/scripts/run-tests.mjs +19 -0
- package/tests/test-arithmetics.mjs +96 -0
- package/tests/test-karatsuba.mjs +133 -0
- package/tests/test-repl-html.mjs +23 -6
package/scripts/perf-poly.mjs
CHANGED
|
@@ -60,6 +60,73 @@ import { compileARM64ArtifactFromObject } from "../backends/arm64/src/arm64.mjs"
|
|
|
60
60
|
import { compileWasmArtifactFromObject } from "../backends/wasm/src/wasm.mjs";
|
|
61
61
|
import { inputPatternForObjectRelation } from "../backends/llvm/src/executable.mjs";
|
|
62
62
|
|
|
63
|
+
function printHelp() {
|
|
64
|
+
console.log(`Usage: node scripts/perf-poly.mjs [options]
|
|
65
|
+
|
|
66
|
+
Polymorphic List Operations Benchmark Harness.
|
|
67
|
+
Benchmarks reverse, concat, split_by, get_nth, and length on
|
|
68
|
+
Examples/poly.k across Native JS, kVM interpreter, LLVM, Wasm, and ARM64.
|
|
69
|
+
|
|
70
|
+
Options:
|
|
71
|
+
--trace
|
|
72
|
+
Enable 7-phase nanosecond execution timing.
|
|
73
|
+
--profile
|
|
74
|
+
Enable per-function call count profiling.
|
|
75
|
+
--wasm-in-process
|
|
76
|
+
Run WebAssembly in-process instead of persistent subprocess runner.
|
|
77
|
+
-h, --help
|
|
78
|
+
Show this help message and exit.
|
|
79
|
+
|
|
80
|
+
Environment Variables:
|
|
81
|
+
BACKENDS
|
|
82
|
+
Target backend to run: 'llvm', 'wasm', or 'arm64'.
|
|
83
|
+
LLVM_ONLY
|
|
84
|
+
Run only LLVM backend ('1' to enable).
|
|
85
|
+
WASM_ONLY
|
|
86
|
+
Run only WebAssembly backend ('1' to enable).
|
|
87
|
+
ARM64_ONLY
|
|
88
|
+
Run only ARM64 backend ('1' to enable).
|
|
89
|
+
BACKENDS_ONLY
|
|
90
|
+
Skip JS and kVM interpreter baselines ('1' to enable).
|
|
91
|
+
LIST_LENGTH
|
|
92
|
+
Workload size for list operations (default: 40).
|
|
93
|
+
ITERATIONS
|
|
94
|
+
Measured iterations per benchmark (default: 3).
|
|
95
|
+
TRACE, K_TRACE
|
|
96
|
+
Enable nanosecond execution tracing ('1' to enable).
|
|
97
|
+
PROFILE, K_PROFILE
|
|
98
|
+
Enable per-function call count profiling ('1' to enable).
|
|
99
|
+
ARM64_WARMUP_ITERATIONS
|
|
100
|
+
Warmup iterations for ARM64 backend (default: 1).
|
|
101
|
+
ARM64_OPT
|
|
102
|
+
ARM64 backend optimization flags (default: -O2).
|
|
103
|
+
ARM64_SPAWN_PER_CALL
|
|
104
|
+
Spawn process per ARM64 call instead of persistent ('1' or '0').
|
|
105
|
+
ARM64_PIPELINE
|
|
106
|
+
Use persistent pipelined runner for ARM64 ('1' or '0').
|
|
107
|
+
LLVM_WARMUP_ITERATIONS
|
|
108
|
+
Warmup iterations for LLVM backend (default: 1).
|
|
109
|
+
LLVM_SPAWN_PER_CALL
|
|
110
|
+
Spawn process per LLVM call instead of persistent ('1' or '0').
|
|
111
|
+
LLVM_PIPELINE
|
|
112
|
+
Use persistent pipelined runner for LLVM ('1' or '0').
|
|
113
|
+
K_LLVM_CACHE_DIR
|
|
114
|
+
Directory to cache compiled LLVM executable binaries.
|
|
115
|
+
WASM_WARMUP_ITERATIONS
|
|
116
|
+
Warmup iterations for WebAssembly backend (default: 3).
|
|
117
|
+
WASM_RESET
|
|
118
|
+
Reset WebAssembly memory between iterations (default: 1).
|
|
119
|
+
WASM_PIPE
|
|
120
|
+
Use persistent subprocess for Wasm (default: 1, '0': in-process).
|
|
121
|
+
WASM_IN_PROCESS
|
|
122
|
+
Run WebAssembly in-process ('1' to enable).`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
126
|
+
printHelp();
|
|
127
|
+
process.exit(0);
|
|
128
|
+
}
|
|
129
|
+
|
|
63
130
|
// Backend selection
|
|
64
131
|
const backendsEnv = process.env.BACKENDS?.toLowerCase();
|
|
65
132
|
const llvmOnly = process.env.LLVM_ONLY === "1" || backendsEnv === "llvm";
|
|
@@ -126,7 +193,7 @@ function buildExportPreamble(exports, libraries) {
|
|
|
126
193
|
return lines.join("\n") + "\n";
|
|
127
194
|
}
|
|
128
195
|
|
|
129
|
-
const neededExports = ["0", "int", "inc", "dec", "nat", "zero_int?"
|
|
196
|
+
const neededExports = ["0", "int", "inc", "dec", "nat", "zero_int?"];
|
|
130
197
|
const exportPreamble = buildExportPreamble(neededExports, [arithmeticsLib]);
|
|
131
198
|
const polyLib = loadLibrary(compileLibrary(exportPreamble + polySource, {
|
|
132
199
|
source: polyPath,
|
|
@@ -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"), []]
|
|
@@ -100,10 +100,13 @@ try {
|
|
|
100
100
|
assertOk(resDec, "2 int dec dec zero_int? should succeed");
|
|
101
101
|
|
|
102
102
|
const divTestCases = [
|
|
103
|
+
{ x: "0", yAlias: "7", yVal: 7n },
|
|
104
|
+
{ x: "3", yAlias: "7", yVal: 7n },
|
|
103
105
|
{ x: "4", yAlias: "1", yVal: 1n },
|
|
104
106
|
{ x: "10", yAlias: "2", yVal: 2n },
|
|
105
107
|
{ x: "12", yAlias: "3", yVal: 3n },
|
|
106
108
|
{ x: "11", yAlias: "3", yVal: 3n },
|
|
109
|
+
{ x: "12", yAlias: "12", yVal: 12n },
|
|
107
110
|
{ x: "100", yAlias: "7", yVal: 7n },
|
|
108
111
|
{ x: "-100", yAlias: "7", yVal: 7n },
|
|
109
112
|
{ x: "1000", yAlias: "10", yVal: 10n }
|
|
@@ -143,6 +146,99 @@ try {
|
|
|
143
146
|
assert.equal(remOut, expectedRem, `div(${x}, ${yAlias}) remainder should match BigInt oracle`);
|
|
144
147
|
}
|
|
145
148
|
|
|
149
|
+
// Regression tests for EQ
|
|
150
|
+
const dummyWire = parseIntWire("0");
|
|
151
|
+
const resEqTrue = run(node, [
|
|
152
|
+
"k.mjs",
|
|
153
|
+
"--lib", libPath,
|
|
154
|
+
"--export", "EQ:EQ",
|
|
155
|
+
"--export", "int:int",
|
|
156
|
+
"--export", "2:two",
|
|
157
|
+
"{two x, two y} EQ .x int"
|
|
158
|
+
], { input: dummyWire });
|
|
159
|
+
assertOk(resEqTrue, "{2, 2} EQ should succeed");
|
|
160
|
+
|
|
161
|
+
const resEqFalse = run(node, [
|
|
162
|
+
"k.mjs",
|
|
163
|
+
"--lib", libPath,
|
|
164
|
+
"--export", "EQ:EQ",
|
|
165
|
+
"--export", "int:int",
|
|
166
|
+
"--export", "2:two",
|
|
167
|
+
"--export", "3:three",
|
|
168
|
+
"{two x, three y} EQ .x int"
|
|
169
|
+
], { input: dummyWire });
|
|
170
|
+
assert.notEqual(resEqFalse.status, 0, "{2, 3} EQ should fail");
|
|
171
|
+
|
|
172
|
+
// Regression tests for pos?
|
|
173
|
+
const resPosTrue = run(node, [
|
|
174
|
+
"k.mjs",
|
|
175
|
+
"--lib", libPath,
|
|
176
|
+
"--export", "pos?:pos?",
|
|
177
|
+
"--export", "int:int",
|
|
178
|
+
"--export", "2:two",
|
|
179
|
+
"two int pos?"
|
|
180
|
+
], { input: dummyWire });
|
|
181
|
+
assertOk(resPosTrue, "2 int pos? should succeed");
|
|
182
|
+
|
|
183
|
+
const resPosZero = run(node, [
|
|
184
|
+
"k.mjs",
|
|
185
|
+
"--lib", libPath,
|
|
186
|
+
"--export", "pos?:pos?",
|
|
187
|
+
"--export", "int:int",
|
|
188
|
+
"--export", "0:zero",
|
|
189
|
+
"zero int pos?"
|
|
190
|
+
], { input: dummyWire });
|
|
191
|
+
assert.notEqual(resPosZero.status, 0, "0 int pos? should fail");
|
|
192
|
+
|
|
193
|
+
// Regression tests for mod, gcd, lcm
|
|
194
|
+
const resMod = run(node, [
|
|
195
|
+
"k.mjs",
|
|
196
|
+
"--lib", libPath,
|
|
197
|
+
"--export", "mod:mod",
|
|
198
|
+
"--export", "int:int",
|
|
199
|
+
"--export", "10:ten",
|
|
200
|
+
"--export", "3:three",
|
|
201
|
+
"{ten x, three y} mod int"
|
|
202
|
+
], { input: dummyWire });
|
|
203
|
+
assertOk(resMod, "10 % 3 mod");
|
|
204
|
+
assert.equal(printIntWire(resMod.stdout, "mod"), "1");
|
|
205
|
+
|
|
206
|
+
const resGcd = run(node, [
|
|
207
|
+
"k.mjs",
|
|
208
|
+
"--lib", libPath,
|
|
209
|
+
"--export", "gcd:gcd",
|
|
210
|
+
"--export", "int:int",
|
|
211
|
+
"--export", "12:twelve",
|
|
212
|
+
"--export", "8:eight",
|
|
213
|
+
"{twelve x, eight y} gcd int"
|
|
214
|
+
], { input: dummyWire });
|
|
215
|
+
assertOk(resGcd, "gcd(12, 8)");
|
|
216
|
+
assert.equal(printIntWire(resGcd.stdout, "gcd"), "4");
|
|
217
|
+
|
|
218
|
+
const resGcdZero = run(node, [
|
|
219
|
+
"k.mjs",
|
|
220
|
+
"--lib", libPath,
|
|
221
|
+
"--export", "gcd:gcd",
|
|
222
|
+
"--export", "int:int",
|
|
223
|
+
"--export", "4:four",
|
|
224
|
+
"--export", "0b:zero_b",
|
|
225
|
+
"{four x, zero_b y} gcd int"
|
|
226
|
+
], { input: dummyWire });
|
|
227
|
+
assertOk(resGcdZero, "gcd(4, 0b)");
|
|
228
|
+
assert.equal(printIntWire(resGcdZero.stdout, "gcd 0b"), "4");
|
|
229
|
+
|
|
230
|
+
const resLcm = run(node, [
|
|
231
|
+
"k.mjs",
|
|
232
|
+
"--lib", libPath,
|
|
233
|
+
"--export", "lcm:lcm",
|
|
234
|
+
"--export", "int:int",
|
|
235
|
+
"--export", "4:four",
|
|
236
|
+
"--export", "6:six",
|
|
237
|
+
"{four x, six y} lcm int"
|
|
238
|
+
], { input: dummyWire });
|
|
239
|
+
assertOk(resLcm, "lcm(4, 6)");
|
|
240
|
+
assert.equal(printIntWire(resLcm.stdout, "lcm"), "12");
|
|
241
|
+
|
|
146
242
|
console.log("OK");
|
|
147
243
|
} finally {
|
|
148
244
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
@@ -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
|
+
}
|
package/tests/test-repl-html.mjs
CHANGED
|
@@ -139,14 +139,15 @@ if (chromiumBin) {
|
|
|
139
139
|
const vfsList = await evaluateAsync(`window.kRepl.getAllVfsFiles().sort()`);
|
|
140
140
|
const expectedFiles = [
|
|
141
141
|
"arithmetics.k",
|
|
142
|
+
"codecs/ieee.mjs",
|
|
143
|
+
"codecs/int.mjs",
|
|
144
|
+
"codecs/json.mjs",
|
|
145
|
+
"codecs/unit.mjs",
|
|
146
|
+
"codecs/utf8.mjs",
|
|
142
147
|
"core.k",
|
|
143
148
|
"ieee.k",
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"json.mjs",
|
|
147
|
-
"poly.k",
|
|
148
|
-
"unit.mjs",
|
|
149
|
-
"utf8.mjs"
|
|
149
|
+
"karatsuba-mult.k",
|
|
150
|
+
"poly.k"
|
|
150
151
|
].sort();
|
|
151
152
|
assert.deepStrictEqual(vfsList, expectedFiles, `getAllVfsFiles() must match curated files list, got: ${JSON.stringify(vfsList)}`);
|
|
152
153
|
|
|
@@ -158,6 +159,22 @@ if (chromiumBin) {
|
|
|
158
159
|
})()`);
|
|
159
160
|
assert(loadOut.includes("loaded arithmetics.k"), `Expected loaded arithmetics.k, got: ${loadOut}`);
|
|
160
161
|
|
|
162
|
+
// Test :load karatsuba-mult.k
|
|
163
|
+
const loadKaratsubaOut = await evaluateAsync(`(async () => {
|
|
164
|
+
await window.kRepl.executeCommand(":load karatsuba-mult.k");
|
|
165
|
+
const lines = Array.from(document.querySelectorAll(".entry-line")).map(el => el.textContent);
|
|
166
|
+
return lines[lines.length - 1];
|
|
167
|
+
})()`);
|
|
168
|
+
assert(loadKaratsubaOut.includes("loaded karatsuba-mult.k"), `Expected loaded karatsuba-mult.k, got: ${loadKaratsubaOut}`);
|
|
169
|
+
|
|
170
|
+
// Test evaluating {1 int x, 1 int y} karatsuba
|
|
171
|
+
const karatsubaVal = await evaluateAsync(`(async () => {
|
|
172
|
+
await window.kRepl.executeCommand("{1 int x, 1 int y} karatsuba");
|
|
173
|
+
const lines = Array.from(document.querySelectorAll(".entry-line")).map(el => el.textContent);
|
|
174
|
+
return lines[lines.length - 1];
|
|
175
|
+
})()`);
|
|
176
|
+
assert(karatsubaVal.includes("{}|_|1|+"), `Expected {}|_|1|+ in output, got: ${karatsubaVal}`);
|
|
177
|
+
|
|
161
178
|
// Test evaluating 10
|
|
162
179
|
const valOut = await evaluateAsync(`(async () => {
|
|
163
180
|
await window.kRepl.executeCommand("10");
|