@fraczak/k 7.0.1 → 7.1.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/DOCS/BIG_PICTURE.md +5 -5
  3. package/DOCS/FILE_FORMATS.md +241 -18
  4. package/DOCS/OBJECT_FILE_AND_PATTERN.md +9 -9
  5. package/DOCS/PATTERNS.md +3 -3
  6. package/DOCS/POLYMORPHIC_IR.md +104 -0
  7. package/DOCS/PROFILING_AND_TRACING.md +60 -72
  8. package/DOCS/REPL.md +3 -3
  9. package/DOCS/book/03-types-as-finite-automata.md +4 -4
  10. package/DOCS/book/06-values-in-memory.md +9 -9
  11. package/DOCS/book/08-operational-semantics-and-execution.md +1 -1
  12. package/DOCS/book/09-compiler-architecture.md +2 -2
  13. package/DOCS/book/10-from-ast-to-intermediate-representation.md +2 -2
  14. package/DOCS/book/14-canonical-serialization.md +1 -1
  15. package/Examples/arithmetics.k +2 -2
  16. package/Examples/bnat.k +1 -1
  17. package/Examples/karatsuba-mult.k +2 -2
  18. package/JOURNAL.md +288 -0
  19. package/README.md +13 -10
  20. package/access-table.mjs +343 -0
  21. package/backend-api.mjs +18 -0
  22. package/backends/llvm/README.md +20 -21
  23. package/backends/llvm/bin/k-llvm-build.mjs +105 -32
  24. package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
  25. package/backends/llvm/bin/k-llvm.mjs +292 -0
  26. package/backends/llvm/runtime/krt.c +41 -0
  27. package/backends/llvm/runtime/krt.h +2 -0
  28. package/backends/llvm/src/cli.mjs +95 -17
  29. package/backends/llvm/src/executable.mjs +132 -15
  30. package/backends/llvm/src/kvm2llvm.mjs +50 -23
  31. package/backends/llvm/src/llvm.mjs +133 -20
  32. package/backends/llvm/tests/integration.sh +11 -11
  33. package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
  34. package/backends/llvm/tests/perf-support.mjs +25 -58
  35. package/backends/llvm/tests/test-llvm.mjs +25 -4
  36. package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
  37. package/backends/wasm/bin/k-wasm-run.mjs +61 -20
  38. package/backends/wasm/bin/k-wasm.mjs +47 -13
  39. package/backends/wasm/src/cli.mjs +141 -19
  40. package/backends/wasm/src/wasm.mjs +132 -24
  41. package/backends/wasm/tests/test-wasm.mjs +5 -5
  42. package/browser/repl-browser.mjs +16 -5
  43. package/browser/vfs-data.mjs +5 -5
  44. package/codecs/k-parse.mjs +29 -8
  45. package/codecs/k-print.mjs +22 -6
  46. package/codecs/runtime/codec-sdk.mjs +8 -4
  47. package/codecs/show.mjs +20 -6
  48. package/core.k +8 -8
  49. package/harness/format.mjs +2 -2
  50. package/harness/registry.mjs +0 -2
  51. package/k.mjs +56 -16
  52. package/kir.mjs +200 -75
  53. package/kvm.mjs +49 -12
  54. package/objects/compile.mjs +37 -23
  55. package/objects/decompile.mjs +40 -10
  56. package/objects/extract-aliases.mjs +44 -14
  57. package/objects/inspect.mjs +19 -14
  58. package/objects/validate.mjs +18 -11
  59. package/package.json +10 -7
  60. package/pkir.mjs +772 -0
  61. package/repl.mjs +36 -18
  62. package/scripts/benchmark-idempotency.mjs +12 -8
  63. package/scripts/benchmark.mjs +5 -9
  64. package/scripts/build-repl-html.mjs +16 -4
  65. package/scripts/perf-ieee.mjs +253 -103
  66. package/scripts/perf-int.mjs +585 -297
  67. package/scripts/perf-multiplication.mjs +66 -25
  68. package/scripts/perf-poly.mjs +292 -164
  69. package/scripts/run-tests.mjs +3 -0
  70. package/tests/code-derivation/pattern-envelope.mjs +4 -4
  71. package/tests/test-access-table.mjs +213 -0
  72. package/tests/test-kvm-polymorphic.mjs +2 -2
  73. package/tests/test-pkir.mjs +530 -0
  74. package/tests/test-polymorphic-tdd.mjs +196 -0
  75. package/tests/test-repl-html.mjs +15 -2
  76. package/tests/test-repl.mjs +30 -1
  77. package/backends/arm64/README.md +0 -103
  78. package/backends/arm64/bin/k-arm64-compile.mjs +0 -93
  79. package/backends/arm64/bin/k-arm64-run.mjs +0 -58
  80. package/backends/arm64/bin/k-arm64.mjs +0 -88
  81. package/backends/arm64/scripts/run-tests.mjs +0 -57
  82. package/backends/arm64/src/arm64.mjs +0 -229
  83. package/backends/arm64/src/cli.mjs +0 -155
  84. package/backends/arm64/src/kvm2arm64.mjs +0 -906
  85. package/backends/arm64/src/runtime.c +0 -744
  86. package/backends/arm64/tests/integration.sh +0 -112
  87. package/backends/arm64/tests/test-arm64.mjs +0 -240
  88. package/backends/llvm/bin/k-llvm-jit.mjs +0 -160
  89. package/harness/adapters/arm64.mjs +0 -105
package/repl.mjs CHANGED
@@ -50,7 +50,7 @@ const NAME_RE = /^[a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]*$/;
50
50
  const COMMAND_NAMES = [
51
51
  "help", "rel",
52
52
  "codecs", "rels", "codec", "input", "reset", "klib", "ko", "load",
53
- "engine", "wasm", "js",
53
+ "engine", "wasm", "pkir", "js",
54
54
  "quit", "exit"
55
55
  ];
56
56
  const CODEC_COMMAND_NAMES = ["load", "unload", "list"];
@@ -76,8 +76,10 @@ function emptyValue() {
76
76
  function createState(options = {}) {
77
77
  codes.load(cloneJSON(initialCodes));
78
78
  const engine = (options.engine || "wasm").toLowerCase();
79
- if (engine !== "wasm" && engine !== "js") {
80
- throw new Error(`Invalid engine '${options.engine}'. Valid engines: wasm, js`);
79
+ if (engine !== "wasm" && engine !== "pkir" && engine !== "js") {
80
+ throw new Error(
81
+ `Invalid engine '${options.engine}'. Valid engines: wasm, pkir, js`
82
+ );
81
83
  }
82
84
  return {
83
85
  engine,
@@ -768,7 +770,7 @@ function completeCommandArgument(line, state) {
768
770
  }
769
771
 
770
772
  if (command === "engine") {
771
- return completeCommandWord(line, argStart, arg, ["wasm", "js"]);
773
+ return completeCommandWord(line, argStart, arg, ["wasm", "pkir", "js"]);
772
774
  }
773
775
 
774
776
  if (command === "input") {
@@ -1003,7 +1005,8 @@ async function executeExpressionWithWasm(annotated, state, lineOffset = 0) {
1003
1005
 
1004
1006
  const wasmCompileStart = performance.now();
1005
1007
  const wasmBytes = await compileWasmArtifactFromObject(obj, {
1006
- inputEnvelopePattern: inputValue?.pattern
1008
+ inputEnvelopePattern: inputValue?.pattern,
1009
+ usePKIR: state.engine === "pkir" || state.usePKIR
1007
1010
  });
1008
1011
  const runner = await instantiateWasmArtifact(wasmBytes);
1009
1012
  const wasmCompileMs = performance.now() - wasmCompileStart;
@@ -1242,8 +1245,10 @@ async function evaluateCommand(line, state) {
1242
1245
  if (!mode) {
1243
1246
  return [`Current engine: ${state.engine}`];
1244
1247
  }
1245
- if (mode !== "wasm" && mode !== "js") {
1246
- throw new Error(`Invalid engine '${arg.trim()}'. Valid engines: wasm, js`);
1248
+ if (mode !== "wasm" && mode !== "pkir" && mode !== "js") {
1249
+ throw new Error(
1250
+ `Invalid engine '${arg.trim()}'. Valid engines: wasm, pkir, js`
1251
+ );
1247
1252
  }
1248
1253
  state.engine = mode;
1249
1254
  return [`engine set to ${mode}`];
@@ -1252,6 +1257,10 @@ async function evaluateCommand(line, state) {
1252
1257
  state.engine = "wasm";
1253
1258
  return ["engine set to wasm"];
1254
1259
  }
1260
+ case "pkir": {
1261
+ state.engine = "pkir";
1262
+ return ["engine set to pkir"];
1263
+ }
1255
1264
  case "js": {
1256
1265
  state.engine = "js";
1257
1266
  return ["engine set to js"];
@@ -1290,7 +1299,7 @@ async function evaluateCommand(line, state) {
1290
1299
 
1291
1300
  function helpText() {
1292
1301
  return [
1293
- ":engine [wasm|js] display or switch evaluation engine (wasm or js)",
1302
+ ":engine [wasm|pkir|js] display or switch evaluation engine",
1294
1303
  ":rel name show relation definition",
1295
1304
  ":rels list relation aliases",
1296
1305
  ":codec load file load a codec module from file (e.g. :codec load codecs/int.mjs)",
@@ -1316,15 +1325,18 @@ function promptForState(state) {
1316
1325
  }
1317
1326
 
1318
1327
  function cliUsage() {
1319
- console.log("Usage: k-repl [options]");
1328
+ console.log("Start the interactive k interpreter.");
1329
+ console.log("Type :help inside the REPL for commands.");
1320
1330
  console.log("");
1321
- console.log("Start the interactive k interpreter. Type :help inside the REPL for commands.");
1331
+ console.log("Usage: k-repl [options]");
1322
1332
  console.log("");
1323
1333
  console.log("Options:");
1324
- console.log(" --engine=<wasm|js> Select evaluation engine (default: wasm)");
1325
- console.log(" --js Shortcut for --engine=js");
1326
- console.log(" --wasm Shortcut for --engine=wasm");
1327
- console.log(" -h, --help Show this help.");
1334
+ console.log(" --engine=<wasm|pkir|js> Select engine: wasm, pkir, js");
1335
+ console.log(" (default: wasm).");
1336
+ console.log(" --pkir Shortcut for --engine=pkir.");
1337
+ console.log(" --wasm Shortcut for --engine=wasm.");
1338
+ console.log(" --js Shortcut for --engine=js.");
1339
+ console.log(" -h, --help Show this help.");
1328
1340
  }
1329
1341
 
1330
1342
  function startRepl(options = {}) {
@@ -1428,18 +1440,24 @@ if (isMainEntrypoint()) {
1428
1440
  engine = "js";
1429
1441
  } else if (arg === "--wasm") {
1430
1442
  engine = "wasm";
1443
+ } else if (arg === "--pkir") {
1444
+ engine = "pkir";
1431
1445
  } else if (arg.startsWith("--engine=")) {
1432
1446
  const val = arg.slice("--engine=".length).toLowerCase();
1433
- if (val !== "wasm" && val !== "js") {
1434
- console.error(`Invalid engine '${val}'. Valid engines: wasm, js`);
1447
+ if (val !== "wasm" && val !== "pkir" && val !== "js") {
1448
+ console.error(
1449
+ `Invalid engine '${val}'. Valid engines: wasm, pkir, js`
1450
+ );
1435
1451
  exit(1);
1436
1452
  }
1437
1453
  engine = val;
1438
1454
  } else if (arg === "--engine") {
1439
1455
  i++;
1440
1456
  const val = (args[i] || "").toLowerCase();
1441
- if (val !== "wasm" && val !== "js") {
1442
- console.error(`Invalid engine '${val}'. Valid engines: wasm, js`);
1457
+ if (val !== "wasm" && val !== "pkir" && val !== "js") {
1458
+ console.error(
1459
+ `Invalid engine '${val}'. Valid engines: wasm, pkir, js`
1460
+ );
1443
1461
  exit(1);
1444
1462
  }
1445
1463
  engine = val;
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { spawnSync } from "node:child_process";
4
- import { mkdtempSync, statSync } from "node:fs";
4
+ import { mkdtempSync, rmSync, statSync } from "node:fs";
5
5
  import { tmpdir } from "node:os";
6
6
  import { join } from "node:path";
7
7
  import { performance } from "node:perf_hooks";
@@ -80,13 +80,17 @@ for (const example of benchmarkExamples) {
80
80
 
81
81
  for (let i = 0; i < iterations; i++) {
82
82
  const out = mkdtempSync(join(tmpdir(), `k-idempotency-bench-${example.replaceAll("/", "_")}-`));
83
- const t0 = performance.now();
84
- run(["objects/compile.mjs", example, join(out, "1.klib")]);
85
- run(["objects/decompile.mjs", join(out, "1.klib"), join(out, "1.k")]);
86
- run(["objects/compile.mjs", join(out, "1.k"), join(out, "2.klib")]);
87
- run(["objects/decompile.mjs", join(out, "2.klib"), join(out, "2.k")]);
88
- times.push(performance.now() - t0);
89
- size = statSync(join(out, "1.klib")).size;
83
+ try {
84
+ const t0 = performance.now();
85
+ run(["objects/compile.mjs", example, join(out, "1.klib")]);
86
+ run(["objects/decompile.mjs", join(out, "1.klib"), join(out, "1.k")]);
87
+ run(["objects/compile.mjs", join(out, "1.k"), join(out, "2.klib")]);
88
+ run(["objects/decompile.mjs", join(out, "2.klib"), join(out, "2.k")]);
89
+ times.push(performance.now() - t0);
90
+ size = statSync(join(out, "1.klib")).size;
91
+ } finally {
92
+ rmSync(out, { recursive: true, force: true });
93
+ }
90
94
  }
91
95
 
92
96
  console.log([
@@ -21,13 +21,12 @@ import {
21
21
  retypeObjectRelationForBackend,
22
22
  patternToPropertyList,
23
23
  propertyListToPattern,
24
- parseFloat64,
25
24
  run,
26
25
  run_converged,
27
- valueForCode,
28
26
  Value
29
27
  } from "../backend-api.mjs";
30
28
  import { parse as parseIntValue } from "../codecs/int.mjs";
29
+ import { parse as parseFloatValue } from "../codecs/ieee.mjs";
31
30
  import {
32
31
  compileObjectBuffer as compileBackendObjectBuffer,
33
32
  decodeObject as decodeBackendObject
@@ -460,13 +459,10 @@ async function prepareState(suite) {
460
459
  }
461
460
 
462
461
  function ieeeInput(testCase, state) {
463
- const float64Hash = state.typeAliases.float64;
464
- const floatPairHash = state.typeAliases.float_pair;
465
- const float64 = text => valueForCode(parseFloat64(text), float64Hash, codes.find);
466
- return valueForCode(Value.product({
467
- x: float64(testCase.input.x),
468
- y: float64(testCase.input.y)
469
- }), floatPairHash, codes.find);
462
+ return Value.product({
463
+ x: parseFloatValue(testCase.input.x),
464
+ y: parseFloatValue(testCase.input.y)
465
+ });
470
466
  }
471
467
 
472
468
  function arithmeticInput(testCase) {
@@ -284,6 +284,17 @@ const htmlContent = `<!DOCTYPE html>
284
284
  border-color: rgba(240, 180, 41, 0.7);
285
285
  }
286
286
 
287
+ .engine-badge.pkir-mode {
288
+ background: rgba(187, 128, 255, 0.15);
289
+ color: #d2a8ff;
290
+ border-color: rgba(187, 128, 255, 0.4);
291
+ }
292
+
293
+ .engine-badge.pkir-mode:hover {
294
+ background: rgba(187, 128, 255, 0.3);
295
+ border-color: rgba(187, 128, 255, 0.7);
296
+ }
297
+
287
298
  .status-indicator {
288
299
  display: flex;
289
300
  align-items: center;
@@ -1644,7 +1655,7 @@ const htmlContent = `<!DOCTYPE html>
1644
1655
  <div class="nav-left">
1645
1656
  <div class="brand">
1646
1657
  <span class="brand-name">k repl</span>
1647
- <span id="engine-badge" class="engine-badge" title="Click to toggle engine (wasm/js)">wasm-in-process</span>
1658
+ <span id="engine-badge" class="engine-badge" title="Click to toggle engine (wasm/pkir/js)">wasm-in-process</span>
1648
1659
  </div>
1649
1660
  <div class="status-indicator">
1650
1661
  <span id="status-dot" class="status-dot ready"></span>
@@ -1673,6 +1684,7 @@ const htmlContent = `<!DOCTYPE html>
1673
1684
  <option value="expr::rels">:rels (list relations)</option>
1674
1685
  <option value="expr::engine">:engine (show engine)</option>
1675
1686
  <option value="expr::engine wasm">:engine wasm</option>
1687
+ <option value="expr::engine pkir">:engine pkir</option>
1676
1688
  <option value="expr::engine js">:engine js</option>
1677
1689
  </optgroup>
1678
1690
  <optgroup label="Codecs &amp; Format Adapters">
@@ -1867,7 +1879,7 @@ const htmlContent = `<!DOCTYPE html>
1867
1879
  <div class="help-section">
1868
1880
  <h4>REPL Commands</h4>
1869
1881
  <table class="help-table">
1870
- <tr><td><code>:engine [wasm|js]</code></td><td>Display or switch evaluation engine (<code>wasm</code> or <code>js</code>)</td></tr>
1882
+ <tr><td><code>:engine [wasm|pkir|js]</code></td><td>Display or switch evaluation engine (<code>wasm</code>, <code>pkir</code>, or <code>js</code>)</td></tr>
1871
1883
  <tr><td><code>:load &lt;file&gt;</code></td><td>Load a <code>.k</code> source or <code>.klib</code> library into current state</td></tr>
1872
1884
  <tr><td><code>:rel &lt;name&gt;</code></td><td>Display definition of relation <code>&lt;name&gt;</code></td></tr>
1873
1885
  <tr><td><code>:rels</code></td><td>List all relation aliases</td></tr>
@@ -1888,8 +1900,8 @@ const htmlContent = `<!DOCTYPE html>
1888
1900
  <li><code>{} | ok</code> &mdash; Constant relation producing variant <code>ok</code> with empty document payload <code>{}</code></li>
1889
1901
  <li><code>not = &lt; / true | false, / false | true &gt;;</code> &mdash; Polymorphic negation via branch projections and ordered choice</li>
1890
1902
  <li><code>{} | true not</code> &mdash; Compose constant relation <code>{} | true</code> with <code>not</code> (evaluates to <code>{} | false</code>)</li>
1891
- <li><code>bool = ?&lt; {} true, {} false &gt;;</code> &mdash; Define a boolean pattern filter relation</li>
1892
- <li><code>not = bool ?X &lt; / true | false, {} | true &gt; ?X;</code> &mdash; Filtered boolean negation: guarded by <code>bool</code>, defaulting to <code>{} | true</code></li>
1903
+ <li><code>bool? = ?&lt; {} true, {} false &gt;;</code> &mdash; Define a boolean pattern filter relation</li>
1904
+ <li><code>not = bool? ?X &lt; / true | false, {} | true &gt; ?X;</code> &mdash; Filtered boolean negation: guarded by <code>bool?</code>, defaulting to <code>{} | true</code></li>
1893
1905
  <li><code>swap = { . y x, . x y };</code> &mdash; Define a product field-swapping relation</li>
1894
1906
  <li><code>{ {} | ok x, {} | nil y } swap</code> &mdash; Construct a product and pass it through <code>swap</code></li>
1895
1907
  </ul>