@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.
@@ -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
 
@@ -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
+ }