@fraczak/k 7.2.0 → 8.0.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 (50) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/DOCS/BIG_PICTURE.md +54 -7
  3. package/DOCS/CODECS.md +21 -11
  4. package/DOCS/CODEC_ARCHITECTURE.md +5 -3
  5. package/DOCS/DICTIONARY.md +13 -4
  6. package/DOCS/FILE_FORMATS.md +3 -2
  7. package/DOCS/JSON_APPROACHES_COMPARISON.md +306 -0
  8. package/DOCS/NAMED_PATTERNS.md +317 -0
  9. package/DOCS/PATTERNS.md +59 -11
  10. package/DOCS/REPL.md +13 -2
  11. package/DOCS/WEB_REPL_REQUIREMENTS.md +4 -2
  12. package/Examples/arithmetics.k +22 -17
  13. package/Examples/bnat.k +21 -11
  14. package/Examples/buda.k +37 -20
  15. package/Examples/byte.k +3 -1
  16. package/Examples/code.k +38 -39
  17. package/Examples/djson-btrie.k +414 -0
  18. package/Examples/djson-ptrie.k +663 -0
  19. package/Examples/djson.k +323 -0
  20. package/Examples/esc.k +1 -1
  21. package/Examples/karatsuba-mult.k +16 -13
  22. package/Examples/list.k +8 -4
  23. package/Examples/nat.k +17 -11
  24. package/Examples/poly.k +11 -3
  25. package/Examples/vhdl_to_k.k +43 -31
  26. package/README.md +42 -16
  27. package/browser/repl-browser.mjs +6 -0
  28. package/browser/tree-view.mjs +35 -16
  29. package/browser/vfs-data.mjs +15 -7
  30. package/codecs/README.md +2 -0
  31. package/codecs/djson-btrie.mjs +560 -0
  32. package/codecs/djson-ptrie.mjs +587 -0
  33. package/core.k +79 -115
  34. package/index.mjs +3 -0
  35. package/named-patterns.mjs +267 -0
  36. package/object.mjs +31 -3
  37. package/package.json +4 -1
  38. package/parser.jison +68 -5
  39. package/parser.mjs +111 -60
  40. package/pretty.mjs +5 -0
  41. package/repl.mjs +188 -22
  42. package/scripts/build-repl-html.mjs +68 -4
  43. package/scripts/perf-djson.mjs +1142 -0
  44. package/scripts/run-tests.mjs +5 -0
  45. package/symbol-table.mjs +20 -2
  46. package/tests/bench-djson-tries.mjs +340 -0
  47. package/tests/test-codecs.mjs +59 -16
  48. package/tests/test-named-patterns.mjs +189 -0
  49. package/tests/test-repl-html.mjs +51 -4
  50. package/tests/test-repl.mjs +190 -0
package/README.md CHANGED
@@ -45,18 +45,19 @@ k can define recursive data and transformations in the same file. Peano
45
45
  natural numbers are either `0` or one more than another natural number:
46
46
 
47
47
  ```k
48
+ nat[] = < {} 0, N +1 > = N;
48
49
  0 = {} | 0;
49
50
  inc = | +1;
50
51
  dec = / +1; # undefined for '0'
51
- add = ?{ < {} 0, N +1 > = N x, ... } <
52
- { . x dec x, . y inc y } add, # defined if 'x > 0'
53
- . y # else, return 'y'
52
+ add = ?{ nat[] = N x, ... } <
53
+ { .x dec x, .y inc y } add, # defined if 'x > 0'
54
+ .y # else, return 'y'
54
55
  >;
55
56
  ```
56
57
 
57
58
  `add` takes a product `{ x, y }`. If `x` has a `+1`, it moves that
58
59
  successor from `x` to `y` and recurses. When that no longer applies, it
59
- returns `y`. The inductive filter `?{ < {} 0, N +1 > = N x, ... }`
60
+ returns `y`. The inductive filter `?{ nat[] = N x, ... }`
60
61
  explicitly witnesses that recursive calls shrink `x`.
61
62
 
62
63
  In the REPL:
@@ -122,19 +123,41 @@ Every installed command supports `-h` and `--help`.
122
123
 
123
124
  ## What k Gives You
124
125
 
125
- **Algebraic data shapes**
126
+ **Algebraic data shapes and named patterns**
126
127
 
127
- All data structures in k are built from products and tagged unions (variants).
128
- Relations and pattern filters describe their domains:
128
+ All data structures in k are built from products and tagged unions
129
+ (variants). Reusable named patterns describe structural type schemas
130
+ using square brackets `name[...]`:
129
131
 
130
132
  ```k
131
- bit? = ?< {} 0, {} 1 >;
132
- byte? = ?{ Bit 0, Bit 1, Bit 2, Bit 3, Bit 4, Bit 5, Bit 6, Bit 7 };
133
- bits? = ?< {} _, bits? 0, bits? 1 > = bits?;
133
+ bit[] = < {} 0, {} 1 >;
134
+ bits[] = < {} _, B 0, B 1 > = B;
135
+ byte[] = {
136
+ bit[] 0, bit[] 1, bit[] 2, bit[] 3,
137
+ bit[] 4, bit[] 5, bit[] 6, bit[] 7
138
+ };
139
+
140
+ -- Parameterized type templates:
141
+ list[X] = < {} nil, { X car, Y cdr } cons > = Y;
142
+ pair[A, B] = { A first, B second };
134
143
  ```
135
144
 
136
- There are no built-in primitive values. The empty product `{}` is the
137
- only leaf in a non-recursive definition.
145
+ Callers instantiate patterns using `? name[...]` as standalone filters
146
+ or inside relation parameter guards (`?{ nat[] = N x, ... }`). There are
147
+ no built-in primitive values: the empty product `{}` is the only leaf
148
+ in a non-recursive definition.
149
+
150
+ **The four-bracket architecture**
151
+
152
+ k uses an orthogonal four-bracket convention with non-overlapping
153
+ semantic domains:
154
+
155
+ | Brackets | Domain | Purpose & Concrete Example |
156
+ | :--- | :--- | :--- |
157
+ | `{ ... }` | Products | Record construction: `{ f a, g b }`, `{}` |
158
+ | `< ... >` | Unions | Variant choice: `< f, g >`, `<>` |
159
+ | `( ... )` | Relations | Composition & identity: `(f g)`, `()` |
160
+ | `[ ... ]` | Patterns | Reusable templates: `list[X]`, `bit[]` |
138
161
 
139
162
  **Composable partial functions**
140
163
 
@@ -149,6 +172,7 @@ Core expressions are deliberately small:
149
172
  | `<f, g>` | try `f`, then `g` if `f` is undefined |
150
173
  | `{f a, g b}` | build a product from parallel transformations |
151
174
  | `?filter` | schema filter / inductive termination witness |
175
+ | `name[...]` | instantiate named pattern template |
152
176
  | `()` | identity |
153
177
  | `<>` | always undefined |
154
178
  | `{}` | constant empty product |
@@ -223,10 +247,12 @@ For a detailed guide to all four formats, commands, and workflows, see
223
247
 
224
248
  | Command | Purpose |
225
249
  | --- | --- |
226
- | `k-json` | Convert JSON to/from the binary stream (schema-specializing) |
227
- | `k-djson` | Convert JSON to/from a universal dynamic JSON singleton pattern |
228
- | `k-int` | Convert decimal integers to/from the binary stream |
229
- | `k-ieee` | Convert float literals to/from the binary stream |
250
+ | `k-json` | Convert JSON to/from binary stream (specializing) |
251
+ | `k-djson` | Convert JSON to/from dynamic JSON (cons-list) |
252
+ | `k-djson-btrie` | Convert JSON to/from binary bit-trie dynamic JSON |
253
+ | `k-djson-ptrie` | Convert JSON to/from radix trie dynamic JSON |
254
+ | `k-int` | Convert decimal integers to/from binary stream |
255
+ | `k-ieee` | Convert float literals to/from binary stream |
230
256
  | `k-unit` | Produce or validate the unit value |
231
257
  | `k-utf8` / `k-utf16` | Convert text to/from k string streams |
232
258
 
@@ -632,6 +632,12 @@ function renderCodecsModal() {
632
632
  targetDesc = "{}";
633
633
  } else if (entry.name === "json.mjs") {
634
634
  targetDesc = "Self-describing JSON";
635
+ } else if (entry.name === "djson.mjs") {
636
+ targetDesc = "$ json (cons-list)";
637
+ } else if (entry.name === "djson-btrie.mjs") {
638
+ targetDesc = "$ json (binary bit-trie)";
639
+ } else if (entry.name === "djson-ptrie.mjs") {
640
+ targetDesc = "$ json (radix/Patricia trie)";
635
641
  } else if (Array.isArray(entry.patterns) && entry.patterns.length > 0) {
636
642
  targetDesc = `Pattern Family (${entry.patterns.length})`;
637
643
  } else if (entry.pattern) {
@@ -455,7 +455,7 @@ export function createOutputEntryElement({
455
455
  modeGroup.appendChild(rawBtn);
456
456
  toolbar.appendChild(modeGroup);
457
457
 
458
- // Tree Action buttons group (Expand / Collapse / Copy)
458
+ // Tree Action buttons group (Expand / Collapse)
459
459
  const actionGroup = document.createElement("div");
460
460
  actionGroup.className = "k-action-group";
461
461
 
@@ -471,23 +471,8 @@ export function createOutputEntryElement({
471
471
  collapseAllBtn.innerHTML = `⊟ Collapse`;
472
472
  collapseAllBtn.title = "Reset trees to top 3 levels";
473
473
 
474
- const copyBtn = document.createElement("button");
475
- copyBtn.type = "button";
476
- copyBtn.className = "k-btn-action";
477
- copyBtn.innerHTML = `📋 Copy`;
478
- copyBtn.title = "Copy raw output to clipboard";
479
- copyBtn.onclick = (e) => {
480
- e.stopPropagation();
481
- navigator.clipboard.writeText(rawText);
482
- copyBtn.innerHTML = `✓ Copied`;
483
- setTimeout(() => {
484
- copyBtn.innerHTML = `📋 Copy`;
485
- }, 1500);
486
- };
487
-
488
474
  actionGroup.appendChild(expandAllBtn);
489
475
  actionGroup.appendChild(collapseAllBtn);
490
- actionGroup.appendChild(copyBtn);
491
476
  toolbar.appendChild(actionGroup);
492
477
 
493
478
  container.appendChild(toolbar);
@@ -512,6 +497,23 @@ export function createOutputEntryElement({
512
497
  `<span class="k-tree-arrow">▶</span> ` +
513
498
  `<span class="k-section-title">🌲 Value</span> ` +
514
499
  `<span class="k-section-preview">${valEscaped}</span>`;
500
+
501
+ const copyValBtn = document.createElement("button");
502
+ copyValBtn.type = "button";
503
+ copyValBtn.className = "k-btn-action k-btn-copy k-btn-copy-value";
504
+ copyValBtn.innerHTML = `📋 Copy`;
505
+ copyValBtn.title = "Copy value definition to clipboard";
506
+ copyValBtn.onclick = (e) => {
507
+ e.preventDefault();
508
+ e.stopPropagation();
509
+ const valStr = valueToK(value);
510
+ navigator.clipboard.writeText(valStr);
511
+ copyValBtn.innerHTML = `✓ Copied`;
512
+ setTimeout(() => {
513
+ copyValBtn.innerHTML = `📋 Copy`;
514
+ }, 1500);
515
+ };
516
+ valSummary.appendChild(copyValBtn);
515
517
  valSection.appendChild(valSummary);
516
518
 
517
519
  const valBody = document.createElement("div");
@@ -538,6 +540,23 @@ export function createOutputEntryElement({
538
540
  `<span class="k-tree-arrow">▶</span> ` +
539
541
  `<span class="k-section-title">🌿 Pattern</span> ` +
540
542
  `<span class="k-section-preview">?${patEscaped}</span>`;
543
+
544
+ const copyPatBtn = document.createElement("button");
545
+ copyPatBtn.type = "button";
546
+ copyPatBtn.className = "k-btn-action k-btn-copy k-btn-copy-pattern";
547
+ copyPatBtn.innerHTML = `📋 Copy`;
548
+ copyPatBtn.title = "Copy pattern definition to clipboard";
549
+ copyPatBtn.onclick = (e) => {
550
+ e.preventDefault();
551
+ e.stopPropagation();
552
+ const patStr = `?${propertyListToFilter(value.pattern, "X")}`;
553
+ navigator.clipboard.writeText(patStr);
554
+ copyPatBtn.innerHTML = `✓ Copied`;
555
+ setTimeout(() => {
556
+ copyPatBtn.innerHTML = `📋 Copy`;
557
+ }, 1500);
558
+ };
559
+ patSummary.appendChild(copyPatBtn);
541
560
  patSection.appendChild(patSummary);
542
561
 
543
562
  patBody = document.createElement("div");