@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.
Files changed (36) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/DOCS/FILE_FORMATS.md +51 -16
  3. package/Examples/arithmetics.k +222 -110
  4. package/Examples/karatsuba-mult.k +215 -0
  5. package/Examples/poly.k +14 -5
  6. package/backends/arm64/scripts/run-tests.mjs +16 -0
  7. package/backends/llvm/bin/k-llvm-build.mjs +40 -14
  8. package/backends/llvm/bin/k-llvm-compile.mjs +29 -12
  9. package/backends/llvm/runtime/krt.c +10 -10
  10. package/backends/llvm/runtime/krt.h +6 -1
  11. package/backends/llvm/scripts/run-tests.mjs +16 -0
  12. package/backends/llvm/src/cli.mjs +1 -1
  13. package/backends/llvm/src/executable.mjs +36 -0
  14. package/backends/llvm/src/kvm2llvm.mjs +10 -4
  15. package/backends/llvm/tests/integration.sh +11 -0
  16. package/backends/llvm/tests/test-llvm.mjs +15 -1
  17. package/backends/wasm/scripts/run-tests.mjs +16 -0
  18. package/browser/shims/fs.mjs +12 -7
  19. package/browser/vfs-data.mjs +7 -10
  20. package/core.k +25 -18
  21. package/harness/suites/poly.mjs +1 -1
  22. package/package.json +2 -1
  23. package/repl-codecs.mjs +6 -3
  24. package/scripts/benchmark-idempotency.mjs +27 -0
  25. package/scripts/benchmark.mjs +51 -0
  26. package/scripts/build-repl-html.mjs +28 -10
  27. package/scripts/generate-dependency-graph.mjs +25 -1
  28. package/scripts/perf-ieee.mjs +75 -0
  29. package/scripts/perf-int.mjs +67 -0
  30. package/scripts/perf-multiplication.mjs +644 -0
  31. package/scripts/perf-poly.mjs +68 -1
  32. package/scripts/render-benchmark.mjs +25 -0
  33. package/scripts/run-tests.mjs +19 -0
  34. package/tests/test-arithmetics.mjs +96 -0
  35. package/tests/test-karatsuba.mjs +133 -0
  36. package/tests/test-repl-html.mjs +23 -6
package/core.k CHANGED
@@ -39,11 +39,11 @@ concat_ = ${bits x, bits y}
39
39
  -- successor (increment by 1)
40
40
  succ = {inv x, _ y} _inc;
41
41
 
42
- _inc = ${bits x, bits y} <
43
- {.x /0 x, .y |1 y} concat_,
44
- {.x /1 x, .y |0 y} _inc,
45
- .y |1
46
- >;
42
+ _inc = ?{X x, X y}
43
+ <
44
+ {.x </0,/_|_> x, .y |1 y} concat_,
45
+ {.x /1 x, .y |0 y} _inc
46
+ > ?X;
47
47
 
48
48
  -- constants
49
49
  2 = 1 succ;
@@ -58,20 +58,27 @@ _inc = ${bits x, bits y} <
58
58
 
59
59
  -- addition on $bits (unsigned, LSB-first with carry)
60
60
  plus = ${bits x, bits y} {.x inv x, .y inv y, b0 c} _plus;
61
- _plus = ${bits x, bits y, bit c}
61
+ _plus = {.x x, .y y, .c c, _ r} _plus_;
62
+ _plus_ = ${bits x, bits y, bit c, bits r}
62
63
  <
63
- {.x /_ if, .y /_ and, <.c/0 0, 1> then} .then,
64
- {.x /_ if, .c/0 and, .y then} .then,
65
- {.x y, .y /_|_ x, .c c} _plus,
66
- {<.c/0 0, 1> x, .y y, .x /_ b0 c} _plus,
67
- {.x /0 x, .y /0 y, .c/0 b0 c} _plus |0,
68
- {.x /0 x, .y /0 y, .c/1 b0 c} _plus |1,
69
- {.x /0 x, .y /1 y, .c/0 b0 c} _plus |1,
70
- {.x /0 x, .y /1 y, .c/1 b1 c} _plus |0,
71
- {.x /1 x, .y /0 y, .c/0 b0 c} _plus |1,
72
- {.x /1 x, .y /0 y, .c/1 b1 c} _plus |0,
73
- {.x /1 x, .y /1 y, .c/0 b1 c} _plus |0,
74
- {.x /1 x, .y /1 y, .c/1 b1 c} _plus |1
64
+ {.x /_ if, .y /_ and, .c/0 c, .r then} .then,
65
+ {.x /_ if, .y /_ and, .c/1 c, .r |1 then} .then,
66
+ {.x /_ if, .c/0 and, {.y x, .r y} concat_ then} .then,
67
+ {.y /_ if, .c/0 and, {.x x, .r y} concat_ then} .then,
68
+ <
69
+ {.x/_ _ x, .y /0 y, b0 c, .r |1 r},
70
+ {.x/_ _ x, .y /1 y, b1 c, .r |0 r},
71
+ {.y/_ _ y, .x /0 x, b0 c, .r |1 r},
72
+ {.y/_ _ y, .x /1 x, b1 c, .r |0 r},
73
+ {.x /0 x, .y /0 y, .c/0 b0 c, .r |0 r},
74
+ {.x /0 x, .y /0 y, .c/1 b0 c, .r |1 r},
75
+ {.x /0 x, .y /1 y, .c/0 b0 c, .r |1 r},
76
+ {.x /0 x, .y /1 y, .c/1 b1 c, .r |0 r},
77
+ {.x /1 x, .y /0 y, .c/0 b0 c, .r |1 r},
78
+ {.x /1 x, .y /0 y, .c/1 b1 c, .r |0 r},
79
+ {.x /1 x, .y /1 y, .c/0 b1 c, .r |0 r},
80
+ {.x /1 x, .y /1 y, .c/1 b1 c, .r |1 r}
81
+ > _plus_
75
82
  >;
76
83
 
77
84
  -- multiplication on $bits (unsigned, shift-and-add)
@@ -48,7 +48,7 @@ export async function createPolySuite({ listLength = 40, cacheDir = null } = {})
48
48
  return lines.join("\n") + "\n";
49
49
  }
50
50
 
51
- const neededExports = ["0", "int", "inc", "dec", "nat", "zero_int?", "nil", "cons", "car", "cdr"];
51
+ const neededExports = ["0", "int", "inc", "dec", "nat", "zero_int?"];
52
52
  const exportPreamble = buildExportPreamble(neededExports, [arithmeticsLib]);
53
53
  const polyLib = loadLibrary(compileLibrary(exportPreamble + polySource, {
54
54
  source: polyPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fraczak/k",
3
- "version": "6.10.3",
3
+ "version": "6.10.5",
4
4
  "description": "k — a language for composing first-order partial functions over algebraic data types (products and tagged unions); includes runtime, type derivation, REPL, and codec toolchain",
5
5
  "main": "index.mjs",
6
6
  "exports": {
@@ -20,6 +20,7 @@
20
20
  "perf:ieee": "node scripts/perf-ieee.mjs",
21
21
  "perf:ieee:full": "node scripts/perf-ieee.mjs --full",
22
22
  "perf:int": "node scripts/perf-int.mjs",
23
+ "perf:mult": "node scripts/perf-multiplication.mjs",
23
24
  "perf:poly": "node scripts/perf-poly.mjs",
24
25
  "perf:poly:trace": "node scripts/perf-poly.mjs --trace",
25
26
  "perf:idempotency": "node scripts/benchmark-idempotency.mjs",
package/repl-codecs.mjs CHANGED
@@ -107,8 +107,10 @@ function registerCodec(state, rawCodec, filePath) {
107
107
 
108
108
  function unregisterCodec(state, codecName) {
109
109
  const store = codecStore(state);
110
- if (!store[codecName]) return 0;
111
- delete store[codecName];
110
+ const baseName = path.basename(codecName);
111
+ const key = store[codecName] ? codecName : (store[baseName] ? baseName : null);
112
+ if (!key) return 0;
113
+ delete store[key];
112
114
  return 1;
113
115
  }
114
116
 
@@ -129,7 +131,8 @@ function resolveCodec(state, codecName, capability = null) {
129
131
  throw new Error("Codec name is required");
130
132
  }
131
133
  const store = codecStore(state);
132
- const codec = store[codecName];
134
+ const baseName = path.basename(codecName);
135
+ const codec = store[codecName] || store[baseName];
133
136
  if (!codec) {
134
137
  throw new Error(`Codec '${codecName}' is not loaded`);
135
138
  }
@@ -14,6 +14,33 @@ const DEFAULT_EXAMPLES = [
14
14
  "Examples/ieee.k"
15
15
  ];
16
16
 
17
+ function printHelp() {
18
+ console.log(
19
+ `Usage: node scripts/benchmark-idempotency.mjs [options] [files...]
20
+
21
+ Measures compile and decompile round-trip idempotency performance
22
+ for K source files through the .klib object format.
23
+
24
+ Arguments:
25
+ example.k ...
26
+ One or more .k source files to benchmark.
27
+ (default: Examples/nat.k Examples/byte.k Examples/bnat.k
28
+ Examples/arithmetics.k Examples/ieee.k)
29
+
30
+ Options:
31
+ -h, --help
32
+ Show this help message and exit.
33
+
34
+ Environment Variables:
35
+ K_BENCH_ITERATIONS
36
+ Number of round-trip benchmark iterations (default: 5).`);
37
+ }
38
+
39
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
40
+ printHelp();
41
+ process.exit(0);
42
+ }
43
+
17
44
  const iterations = Number(process.env.K_BENCH_ITERATIONS || 5);
18
45
  const examples = process.argv.slice(2);
19
46
  const benchmarkExamples = examples.length > 0 ? examples : DEFAULT_EXAMPLES;
@@ -733,7 +733,58 @@ function printSummary(document) {
733
733
  console.log("=============================================================\n");
734
734
  }
735
735
 
736
+ function printHelp() {
737
+ console.log(`Usage: node scripts/benchmark.mjs [options]
738
+
739
+ Unified Multi-Backend Benchmark Suite.
740
+ Runs comprehensive arithmetic and IEEE benchmarks across Native JS,
741
+ kVM, KIR-P, Wasm, and LLVM-JIT execution engines.
742
+
743
+ Options:
744
+ --worker
745
+ Internal flag: execute an isolated benchmark worker job.
746
+ -h, --help
747
+ Show this help message and exit.
748
+
749
+ Environment Variables:
750
+ BENCHMARK_CASES
751
+ Comma-separated benchmark cases to run (default: all).
752
+ Cases: ieee.add, ieee.sub, ieee.mul, ieee.div,
753
+ int.times.220d, int.gcd.90d, int.factorial.101,
754
+ int.factorial.242, int.factorial.1174
755
+ BENCHMARK_MODES
756
+ Comma-separated execution modes to run (default: all).
757
+ Modes: Native JS (Envelope-Aware), Native JS (Envelope-Free),
758
+ kVM Interpreter (Env-Free), KIR-P Export,
759
+ k-wasm, k-llvm-jit
760
+ BENCHMARK_SAMPLES
761
+ Number of measurement samples per benchmark (default: 3).
762
+ BENCHMARK_TIMEOUT_MS
763
+ Timeout per benchmark job in milliseconds (default: 120000).
764
+ BENCHMARK_JOBS
765
+ Maximum parallel worker concurrency (default: 1).
766
+ BENCHMARK_STRICT
767
+ Exit with non-zero exit code if any case fails ('1' to enable).
768
+ K_LLVM_RUNTIME_MODE
769
+ Default LLVM runtime compilation mode (default: fast).
770
+ K_LLVM_IEEE_RUNTIME_MODE
771
+ LLVM runtime mode for IEEE benchmarks (default: compact).
772
+ K_LLVM_CLANG_OPT
773
+ Clang optimization flag for LLVM (default: -O3).
774
+ K_LLVM_IEEE_CLANG_OPT
775
+ Clang optimization flag for IEEE LLVM (default: -O0).
776
+ K_LLVM_CACHE_DIR
777
+ Directory to cache compiled LLVM executable binaries.
778
+ K_BENCHMARK_RESULT_PATH
779
+ Custom destination file path for benchmark results JSON.`);
780
+ }
781
+
736
782
  async function main() {
783
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
784
+ printHelp();
785
+ return;
786
+ }
787
+
737
788
  if (process.env.K_BENCHMARK_WORKER === "1" || process.argv.includes("--worker")) {
738
789
  await workerMain();
739
790
  return;
@@ -10,6 +10,23 @@ const __dirname = path.dirname(__filename);
10
10
  const projectRoot = path.resolve(__dirname, "..");
11
11
  const workspaceRoot = path.resolve(projectRoot, "..");
12
12
 
13
+ function printHelp() {
14
+ console.log(`Usage: node scripts/build-repl-html.mjs [options]
15
+
16
+ Builds the standalone, self-contained K web REPL (repl.html).
17
+ Bundles browser shims, virtual file system (core.k, Examples, Wasm),
18
+ and UI components into a single zero-dependency HTML file.
19
+
20
+ Options:
21
+ -h, --help
22
+ Show this help message and exit.`);
23
+ }
24
+
25
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
26
+ printHelp();
27
+ process.exit(0);
28
+ }
29
+
13
30
  console.log("=== Building Self-Contained K REPL HTML ===");
14
31
 
15
32
  // 1. Node shims plugin for esbuild
@@ -61,8 +78,8 @@ if (fs.existsSync(coreKPath)) {
61
78
  vfsFiles["core.k"] = fs.readFileSync(coreKPath, "utf8");
62
79
  }
63
80
 
64
- // Add verified k-code files: arithmetics.k, ieee.k, poly.k
65
- const verifiedExamples = ["arithmetics.k", "ieee.k", "poly.k"];
81
+ // Add verified k-code files: arithmetics.k, ieee.k, poly.k, karatsuba-mult.k
82
+ const verifiedExamples = ["arithmetics.k", "ieee.k", "poly.k", "karatsuba-mult.k"];
66
83
  const examplesDir = path.join(projectRoot, "Examples");
67
84
  for (const filename of verifiedExamples) {
68
85
  const fullPath = path.join(examplesDir, filename);
@@ -113,7 +130,6 @@ for (const filename of verifiedCodecs) {
113
130
  }]
114
131
  });
115
132
  const bundledContent = buildRes.outputFiles[0].text;
116
- vfsFiles[filename] = bundledContent;
117
133
  vfsFiles[`codecs/${filename}`] = bundledContent;
118
134
  }
119
135
  }
@@ -1646,6 +1662,7 @@ const htmlContent = `<!DOCTYPE html>
1646
1662
  <option value="arithmetics.k">arithmetics.k</option>
1647
1663
  <option value="ieee.k">ieee.k</option>
1648
1664
  <option value="poly.k">poly.k</option>
1665
+ <option value="karatsuba-mult.k">karatsuba-mult.k</option>
1649
1666
  </optgroup>
1650
1667
  <optgroup label="Quick Expressions">
1651
1668
  <option value="expr:{} | ok">{} | ok</option>
@@ -1654,6 +1671,7 @@ const htmlContent = `<!DOCTYPE html>
1654
1671
  <option value="expr:{10 x, 5 y} plus">{10 x, 5 y} plus (bits)</option>
1655
1672
  <option value="expr:1 succ">1 succ</option>
1656
1673
  <option value="expr:{10 int x, 5 int y} plus">{10 int x, 5 int y} plus (int)</option>
1674
+ <option value="expr:{10 int x, 5 int y} karatsuba">{10 int x, 5 int y} karatsuba</option>
1657
1675
  <option value="expr::types">:types (list types)</option>
1658
1676
  <option value="expr::rels">:rels (list relations)</option>
1659
1677
  <option value="expr::engine">:engine (show engine)</option>
@@ -1663,13 +1681,13 @@ const htmlContent = `<!DOCTYPE html>
1663
1681
  <optgroup label="Codecs &amp; Format Adapters">
1664
1682
  <option value="expr::codecs">:codecs</option>
1665
1683
  <option value="expr::input">:input (interactive dialog)</option>
1666
- <option value="expr::codec load int.mjs">:codec load int.mjs</option>
1667
- <option value="expr::codec load utf8.mjs">:codec load utf8.mjs</option>
1668
- <option value="expr::codec load json.mjs">:codec load json.mjs</option>
1669
- <option value="expr::codec load ieee.mjs">:codec load ieee.mjs</option>
1670
- <option value="expr::codec load unit.mjs">:codec load unit.mjs</option>
1671
- <option value="expr::input json.mjs {&quot;a&quot;:12,&quot;b&quot;:&quot;hello&quot;}">:input json.mjs {"a":12,"b":"hello"}</option>
1672
- <option value="expr::input int.mjs [0,1,2]">:input int.mjs [0,1,2]</option>
1684
+ <option value="expr::codec load codecs/int.mjs">:codec load codecs/int.mjs</option>
1685
+ <option value="expr::codec load codecs/utf8.mjs">:codec load codecs/utf8.mjs</option>
1686
+ <option value="expr::codec load codecs/json.mjs">:codec load codecs/json.mjs</option>
1687
+ <option value="expr::codec load codecs/ieee.mjs">:codec load codecs/ieee.mjs</option>
1688
+ <option value="expr::codec load codecs/unit.mjs">:codec load codecs/unit.mjs</option>
1689
+ <option value="expr::input codecs/json.mjs {&quot;a&quot;:12,&quot;b&quot;:&quot;hello&quot;}">:input codecs/json.mjs {"a":12,"b":"hello"}</option>
1690
+ <option value="expr::input codecs/int.mjs [0,1,2]">:input codecs/int.mjs [0,1,2]</option>
1673
1691
  </optgroup>
1674
1692
  </select>
1675
1693
  <button id="btn-load-example" class="btn btn-primary">Load</button>
@@ -8,7 +8,31 @@ import { execSync } from "node:child_process";
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = path.dirname(__filename);
10
10
  const root = path.resolve(__dirname, "..");
11
- const outPath = path.join(root, "DOCS", "dependency-graph.md");
11
+
12
+ function printHelp() {
13
+ console.log(
14
+ `Usage: node scripts/generate-dependency-graph.mjs [options] [out]
15
+
16
+ Generates a Mermaid dependency diagram from tracked ESM imports.
17
+
18
+ Arguments:
19
+ out-file
20
+ Destination markdown file path.
21
+ (default: DOCS/dependency-graph.md)
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
+
33
+ const outPath = process.argv[2]
34
+ ? path.resolve(root, process.argv[2])
35
+ : path.join(root, "DOCS", "dependency-graph.md");
12
36
 
13
37
  function getTrackedMjsFiles() {
14
38
  const raw = execSync("git ls-files '*.mjs'", {
@@ -52,6 +52,81 @@ import {
52
52
  import { compileWasmArtifactFromObject } from "../backends/wasm/src/wasm.mjs";
53
53
  import { compileARM64ArtifactFromObject } from "../backends/arm64/src/arm64.mjs";
54
54
 
55
+ function printHelp() {
56
+ console.log(`Usage: node scripts/perf-ieee.mjs [options]
57
+
58
+ IEEE 754 Floating-Point Arithmetic Benchmark Harness.
59
+ Benchmarks add, sub, mul, and div on Examples/ieee.k across
60
+ Native JS, kVM interpreter, LLVM, Wasm, and ARM64 backends.
61
+
62
+ Options:
63
+ --opt=<levels>, --opts=<levels>
64
+ Comma-separated Clang optimization levels for LLVM (e.g. -O1,-O2).
65
+ --O0, --O1, --O2, --O3
66
+ Direct Clang optimization level flags for LLVM.
67
+ --full
68
+ Run full LLVM optimization sweep (-O0, -O1, -O2).
69
+ --wasm-in-process
70
+ Run WebAssembly in-process instead of persistent subprocess runner.
71
+ -h, --help
72
+ Show this help message and exit.
73
+
74
+ Environment Variables:
75
+ BACKENDS
76
+ Target backend to run: 'llvm', 'wasm', or 'arm64'.
77
+ LLVM_ONLY
78
+ Run only LLVM backend ('1' to enable).
79
+ WASM_ONLY
80
+ Run only WebAssembly backend ('1' to enable).
81
+ ARM64_ONLY
82
+ Run only ARM64 backend ('1' to enable).
83
+ BACKENDS_ONLY
84
+ Skip JS and kVM interpreter baselines ('1' to enable).
85
+ VALUES
86
+ Comma-separated float values to benchmark
87
+ (default: 0.5,-4,0,Infinity,-Infinity,NaN).
88
+ ITERATIONS
89
+ Measured iterations per benchmark (default: 3).
90
+ ARM64_WARMUP_ITERATIONS
91
+ Warmup iterations for ARM64 backend (default: 1).
92
+ ARM64_OPT
93
+ ARM64 backend optimization flags (default: -O2).
94
+ ARM64_SPAWN_PER_CALL
95
+ Spawn process per ARM64 call instead of persistent ('1' or '0').
96
+ ARM64_PIPELINE
97
+ Use persistent pipelined runner for ARM64 ('1' or '0').
98
+ LLVM_WARMUP_ITERATIONS
99
+ Warmup iterations for LLVM backend (default: 1).
100
+ LLVM_SPAWN_PER_CALL
101
+ Spawn process per LLVM call instead of persistent ('1' or '0').
102
+ LLVM_PIPELINE
103
+ Use persistent pipelined runner for LLVM ('1' or '0').
104
+ LLVM_OPTS
105
+ Comma-separated Clang optimization levels for LLVM.
106
+ K_LLVM_IEEE_RUNTIME_MODE
107
+ LLVM runtime compilation mode for IEEE (default: fast).
108
+ K_LLVM_IEEE_CLANG_OPT
109
+ Clang optimization levels for IEEE LLVM (default: -O1).
110
+ K_LLVM_CACHE_DIR
111
+ Directory to cache compiled LLVM executable binaries.
112
+ PERF_FULL
113
+ Set to '1' to test multiple LLVM optimization levels
114
+ (-O0, -O1, -O2).
115
+ WASM_WARMUP_ITERATIONS
116
+ Warmup iterations for WebAssembly backend (default: 10).
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
+
55
130
  // Backend selection
56
131
  const backendsEnv = process.env.BACKENDS?.toLowerCase();
57
132
  const llvmOnly = process.env.LLVM_ONLY === "1" || backendsEnv === "llvm";
@@ -56,6 +56,73 @@ import {
56
56
  import { compileARM64ArtifactFromObject } from "../backends/arm64/src/arm64.mjs";
57
57
  import { compileWasmArtifactFromObject } from "../backends/wasm/src/wasm.mjs";
58
58
 
59
+ function printHelp() {
60
+ console.log(`Usage: node scripts/perf-int.mjs [options]
61
+
62
+ Big Integer Arithmetic Performance Benchmark Harness.
63
+ Benchmarks plus, minus, times, and squaring scale on arithmetics.k
64
+ across Native JS, kVM interpreter, LLVM, Wasm, and ARM64 backends.
65
+
66
+ Options:
67
+ --wasm-in-process
68
+ Run WebAssembly in-process instead of persistent subprocess runner.
69
+ -h, --help
70
+ Show this help message and exit.
71
+
72
+ Environment Variables:
73
+ BACKENDS
74
+ Target backend to run: 'llvm', 'wasm', or 'arm64'.
75
+ LLVM_ONLY
76
+ Run only LLVM backend ('1' to enable).
77
+ WASM_ONLY
78
+ Run only WebAssembly backend ('1' to enable).
79
+ ARM64_ONLY
80
+ Run only ARM64 backend ('1' to enable).
81
+ BACKENDS_ONLY
82
+ Skip JS and kVM interpreter baselines ('1' to enable).
83
+ INPUTS
84
+ Comma-separated integer strings to benchmark.
85
+ ITERATIONS
86
+ Measured iterations per benchmark (default: 3).
87
+ ARM64_WARMUP_ITERATIONS
88
+ Warmup iterations for ARM64 backend (default: 1).
89
+ ARM64_OPT
90
+ ARM64 backend optimization flags (default: -O2).
91
+ ARM64_SPAWN_PER_CALL
92
+ Spawn process per ARM64 call instead of persistent ('1' or '0').
93
+ ARM64_PIPELINE
94
+ Use persistent pipelined runner for ARM64 ('1' or '0').
95
+ LLVM_WARMUP_ITERATIONS
96
+ Warmup iterations for LLVM backend (default: 1).
97
+ LLVM_SPAWN_PER_CALL
98
+ Spawn process per LLVM call instead of persistent ('1' or '0').
99
+ LLVM_PIPELINE
100
+ Use persistent pipelined runner for LLVM ('1' or '0').
101
+ K_LLVM_CACHE_DIR
102
+ Directory to cache compiled LLVM executable binaries.
103
+ WASM_WARMUP_ITERATIONS
104
+ Warmup iterations for WebAssembly backend (default: 3).
105
+ WASM_RESET
106
+ Reset WebAssembly memory between iterations (default: 1).
107
+ WASM_PIPE
108
+ Use persistent subprocess for Wasm (default: 1, '0': in-process).
109
+ WASM_IN_PROCESS
110
+ Run WebAssembly in-process ('1' to enable).
111
+ SQUARING_INPUT
112
+ Initial integer for squaring benchmark (default: 987654321).
113
+ SQUARING_STEPS
114
+ Number of squaring steps (default: 10).
115
+ SQUARING_STEP_TIMEOUT_MS
116
+ Timeout per squaring step in milliseconds (default: 60000).
117
+ K_ARENA_CAPACITY_MB
118
+ Memory arena capacity in MB (default: 4096).`);
119
+ }
120
+
121
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
122
+ printHelp();
123
+ process.exit(0);
124
+ }
125
+
59
126
  // Backend selection
60
127
  const backendsEnv = process.env.BACKENDS?.toLowerCase();
61
128
  const llvmOnly = process.env.LLVM_ONLY === "1" || backendsEnv === "llvm";