@fraczak/k 7.0.2 → 7.2.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 (71) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/DOCS/CODECS.md +37 -2
  3. package/DOCS/CODEC_ARCHITECTURE.md +12 -5
  4. package/DOCS/FILE_FORMATS.md +238 -15
  5. package/DOCS/POLYMORPHIC_IR.md +104 -0
  6. package/DOCS/REPL.md +11 -3
  7. package/DOCS/WEB_REPL_REQUIREMENTS.md +1 -1
  8. package/JOURNAL.md +288 -0
  9. package/README.md +12 -3
  10. package/Value.mjs +28 -3
  11. package/access-table.mjs +343 -0
  12. package/backend-api.mjs +23 -1
  13. package/backends/llvm/README.md +20 -21
  14. package/backends/llvm/bin/k-llvm-build.mjs +105 -32
  15. package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
  16. package/backends/llvm/bin/k-llvm.mjs +292 -0
  17. package/backends/llvm/runtime/krt.c +8 -0
  18. package/backends/llvm/runtime/krt.h +1 -0
  19. package/backends/llvm/src/cli.mjs +95 -17
  20. package/backends/llvm/src/executable.mjs +128 -11
  21. package/backends/llvm/src/kvm2llvm.mjs +10 -5
  22. package/backends/llvm/src/llvm.mjs +121 -9
  23. package/backends/llvm/tests/integration.sh +11 -11
  24. package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
  25. package/backends/llvm/tests/perf-support.mjs +24 -3
  26. package/backends/llvm/tests/test-llvm.mjs +22 -1
  27. package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
  28. package/backends/wasm/bin/k-wasm-run.mjs +61 -20
  29. package/backends/wasm/bin/k-wasm.mjs +47 -13
  30. package/backends/wasm/src/cli.mjs +141 -19
  31. package/backends/wasm/src/wasm.mjs +130 -23
  32. package/browser/repl-browser.mjs +16 -5
  33. package/browser/tree-view.mjs +47 -8
  34. package/browser/vfs-data.mjs +6 -5
  35. package/codecs/README.md +1 -0
  36. package/codecs/djson.mjs +270 -0
  37. package/codecs/int.mjs +2 -1
  38. package/codecs/json.mjs +7 -2
  39. package/codecs/k-parse.mjs +36 -9
  40. package/codecs/k-print.mjs +26 -6
  41. package/codecs/runtime/codec-sdk.mjs +24 -6
  42. package/codecs/runtime/pattern-json.mjs +80 -1
  43. package/codecs/runtime/prefix-codec.mjs +629 -67
  44. package/codecs/runtime/show-value.mjs +93 -51
  45. package/codecs/runtime/unicode-string.mjs +29 -6
  46. package/codecs/show.mjs +24 -6
  47. package/codecs/utf16.mjs +2 -1
  48. package/k.mjs +56 -16
  49. package/kir.mjs +58 -19
  50. package/kvm.mjs +49 -12
  51. package/objects/compile.mjs +37 -23
  52. package/objects/decompile.mjs +40 -10
  53. package/objects/extract-aliases.mjs +44 -14
  54. package/objects/inspect.mjs +19 -14
  55. package/objects/validate.mjs +18 -11
  56. package/package.json +11 -3
  57. package/pkir.mjs +772 -0
  58. package/repl.mjs +92 -23
  59. package/scripts/build-repl-html.mjs +22 -3
  60. package/scripts/perf-ieee.mjs +264 -13
  61. package/scripts/perf-int.mjs +315 -22
  62. package/scripts/perf-multiplication.mjs +58 -7
  63. package/scripts/perf-poly.mjs +306 -24
  64. package/scripts/run-tests.mjs +3 -0
  65. package/tests/test-access-table.mjs +213 -0
  66. package/tests/test-codecs.mjs +168 -0
  67. package/tests/test-pkir.mjs +530 -0
  68. package/tests/test-polymorphic-tdd.mjs +196 -0
  69. package/tests/test-repl-html.mjs +16 -2
  70. package/tests/test-repl.mjs +63 -1
  71. package/backends/llvm/bin/k-llvm-jit.mjs +0 -160
package/CHANGELOG.md CHANGED
@@ -5,6 +5,81 @@ All notable changes to this project will be documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
6
  This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [7.2.0] — 2026-10-17 — Dynamic JSON Codec (djson) & Lazy Wire Decoding
9
+
10
+ ### Features & Performance Improvements
11
+
12
+ - **Universal Dynamic JSON Codec (`codecs/djson.mjs`, `k-djson`)**:
13
+ - Added a standalone dynamic JSON codec (`djson.mjs` / `k-djson`)
14
+ based on a single 29-node recursive pattern `JSON = < number,
15
+ string, bool, null, list, object >`, where arrays are encoded as
16
+ arbitrary-length `cons`/`nil` lists and objects as `cons`/`nil`
17
+ lists of `{ key, val }` pairs.
18
+ - Kept the existing schema-specializing `json.mjs` (`k-json`) as an
19
+ alternative record-oriented JSON codec.
20
+ - Integrated `djson.mjs` into the CLI, REPL, and Web REPL (`repl.html`
21
+ VFS).
22
+
23
+ - **Lazy Prefix-Free Wire Decoding & Fast Bitstream I/O**:
24
+ - Implemented lazy wire decoding (`LazyGeneralProduct` and
25
+ `LazyGeneralVariant`) with precomputed fixed-width bit sizes and
26
+ static field offsets on pattern graphs.
27
+ - Optimized bitstream reading/writing (`BitReader` / `BitWriter`) with
28
+ word-level operations, pre-encoded closed pattern bytes, and direct
29
+ bitstream-to-codepoint UTF-8 string decoding without intermediate
30
+ AST allocations.
31
+
32
+ - **Stack-Safe & Bounded Value Rendering**:
33
+ - Converted `valueToK`, `valueWithEnvelopeToK`, and wire serialization
34
+ to iterative stack-safe algorithms with early character truncation
35
+ (`maxChars`).
36
+ - Added `:limit [num|none]` command and `--limit=<num>` CLI flag in
37
+ `repl.mjs` (default: `4096` chars) and bounded DOM tree previews in
38
+ `repl.html`.
39
+ - Handled broken pipe (`EPIPE`) cleanly across codec CLI entrypoints.
40
+
41
+ ## [7.1.0] — 2026-10-16 — Polymorphic K IR (PKIR) & CLI Standardization
42
+
43
+ ### Features & Architecture Improvements
44
+
45
+ - **Polymorphic K IR (PKIR) & Access Table Engine**:
46
+ - Implemented `pkir.mjs` providing an intermediate representation
47
+ tailored for polymorphic relations with variant dispatch, projection
48
+ tables, and partial function failure semantics.
49
+ - Implemented `access-table.mjs` (`buildAccessTable`) for resolving
50
+ field offsets and variant selectors across arbitrary schemas.
51
+ - Added PKIR specialization (`specializePKIR`) eliminating dead
52
+ branches and baking in direct physical offsets.
53
+ - Supported PKIR execution and standalone executable generation across
54
+ both WebAssembly and LLVM backends.
55
+ - Added dedicated test suites: `tests/test-pkir.mjs`,
56
+ `tests/test-access-table.mjs`, and `tests/test-polymorphic-tdd.mjs`.
57
+ - Added specification and documentation in `DOCS/POLYMORPHIC_IR.md`
58
+ and updated `DOCS/FILE_FORMATS.md`.
59
+
60
+ - **Web REPL (`repl.html`) & Wasm Integration**:
61
+ - Enabled `.pkir` generation and lowering to WebAssembly in
62
+ `repl.mjs` and `repl.html`.
63
+ - Promoted Web REPL visibility in `README.md` (top banner,
64
+ zero-install section, further reading).
65
+
66
+ - **Multi-Backend CLI Standardization & Help Completeness**:
67
+ - Standardized CLI syntax, argument parsing, options, and help text
68
+ (`-h` / `--help`) across tools in `backends/*/bin/` and
69
+ `objects/`.
70
+ - Consolidated `backends/llvm/bin/` (`k-llvm.mjs`, `k-llvm-build.mjs`,
71
+ `k-llvm-compile.mjs`) to mirror `backends/wasm/bin/`.
72
+ - Aligned `--lib` and `--export` options across LLVM, Wasm, and object
73
+ tools.
74
+ - Documented explicit defaults (such as cache directories, Clang
75
+ optimization levels, and runtime modes) in CLI help texts.
76
+
77
+ - **Concurrent Multi-Backend Performance Benchmarks**:
78
+ - Added concurrent `llvm` and `llvm-pkir` execution lanes across all
79
+ performance suites (`perf:ieee`, `perf:int`, `perf:poly`,
80
+ `perf:mult`).
81
+ - Documented benchmark findings and throughput in `JOURNAL.md`.
82
+
8
83
  ## [7.0.2] — 2026-10-13 — LLVM Squaring Scaling & Backend Streamlining
9
84
 
10
85
  ### Features & Performance Improvements
package/DOCS/CODECS.md CHANGED
@@ -141,6 +141,40 @@ printf 'yes\n' | ./codecs/yesno.mjs --parse | ./codecs/yesno.mjs --print
141
141
  # Output: yes
142
142
  ```
143
143
 
144
+ ## Built-in Codecs
145
+
146
+ The `codecs/` directory provides the following standard codecs:
147
+
148
+ - **`int.mjs` (`k-int`)**: Decimal integers and bracketed integer lists
149
+ (e.g. `42`, `-15`, `[1, 2, 3]`) mapped to signed binary bit trees and
150
+ `cons`/`nil` lists.
151
+ - **`ieee.mjs` (`k-ieee`)**: IEEE 754 64-bit floating-point numbers
152
+ (`sign`, `exponent`, `fraction`).
153
+ - **`utf8.mjs` (`k-utf8`) & `utf16.mjs` (`k-utf16`)**: Unicode strings
154
+ encoded as `cons`/`nil` code-point lists (`str` in `core.k`).
155
+ - **`unit.mjs` (`k-unit`)**: The unit value `{}`.
156
+ - **`json.mjs` (`k-json`) — Schema-Specializing JSON**:
157
+ Derives a document-specific pattern for each JSON value:
158
+ - JSON objects map directly to products `{ field: val, ... }`.
159
+ - JSON arrays map to indexed products `{ "0": a0, "1": a1, ... }`.
160
+ - Ideal for record-oriented projection (e.g. `.user .name`).
161
+ - **`djson.mjs` (`k-djson`) — Universal Dynamic JSON**:
162
+ Maps every JSON document to a single universal recursive pattern
163
+ `JSON`:
164
+ ```k
165
+ ?<
166
+ float64 number,
167
+ str string,
168
+ < {} true, {} false > bool,
169
+ {} null,
170
+ < {} nil, { JSON car, LIST cdr } cons >=LIST list,
171
+ < {} nil, { { str key, JSON val } car, OBJ cdr } cons >=OBJ object
172
+ >=JSON
173
+ ```
174
+ Because every JSON value shares the exact same static 29-node pattern,
175
+ a `k` relation can be compiled once against `JSON` and process
176
+ arbitrary JSON documents of any shape or array/object length.
177
+
144
178
  ## Testing a Codec
145
179
 
146
180
  For CLI codecs, test both directions in a pipeline:
@@ -174,8 +208,9 @@ npm test
174
208
  ## Web REPL (VFS) Bundling
175
209
 
176
210
  When `repl.html` is generated (`npm run build:repl-html`):
177
- - Codecs (`int.mjs`, `json.mjs`, `utf8.mjs`, `unit.mjs`, `ieee.mjs`) are
178
- bundled into 100% self-contained ES modules with zero imports.
211
+ - Codecs (`int.mjs`, `json.mjs`, `djson.mjs`, `utf8.mjs`, `unit.mjs`,
212
+ `ieee.mjs`) are bundled into 100% self-contained ES modules with zero
213
+ imports.
179
214
  - `runCodecCLI` is shimmed as a no-op, and `Value` helpers are directly
180
215
  inlined.
181
216
  - In the browser, the VFS serves these self-contained modules directly to
@@ -192,11 +192,16 @@ runCodecCLI(import.meta.url, { parse, print, doc });
192
192
  pathToFileURL(process.argv[1]).href`). If imported as a module or
193
193
  running in a browser, it is a no-op.
194
194
  2. **Flag Parsing**: Handles `--parse`, `--print`, and `-h` / `--help`.
195
- 3. **Stream Piping**:
195
+ 3. **Stream Piping & Lazy Wire Decoding**:
196
196
  - For `--parse`: reads `stdin` to string, calls `parse(text)`, encodes
197
197
  enveloped value `(P, v)` to binary wire format on `stdout`.
198
- - For `--print`: decodes wire format from `stdin` into `(P, v)`, calls
199
- `print(value)`, writes formatted text to `stdout`.
198
+ - For `--print`: lazily decodes the wire format from `stdin` into
199
+ bitstream-backed `Value` proxies (`LazyGeneralProduct`,
200
+ `LazyGeneralVariant`) with precomputed fixed-width bit sizes and
201
+ static field offsets, calls `print(value)`, and writes formatted text
202
+ to `stdout`.
203
+ - Cleanly exits on `EPIPE` when piped into downstream consumers like
204
+ `head`.
200
205
 
201
206
  ---
202
207
 
@@ -207,7 +212,8 @@ To make `codecs/` intuitive and self-contained:
207
212
  ```text
208
213
  codecs/
209
214
  ├── int.mjs # Integer & list codec
210
- ├── json.mjs # JSON codec
215
+ ├── json.mjs # JSON codec (schema-specializing)
216
+ ├── djson.mjs # Dynamic JSON codec (singleton pattern)
211
217
  ├── utf8.mjs # UTF-8 string codec
212
218
  ├── utf16.mjs # UTF-16 string codec
213
219
  ├── ieee.mjs # IEEE 754 float codec
@@ -236,7 +242,8 @@ In the browser REPL (`repl.html`):
236
242
  imports**.
237
243
  - **No Runtime Files in VFS**: `codecs/runtime/*` is not included in the
238
244
  browser VFS. The VFS only contains verified, self-contained user-facing
239
- files (`int.mjs`, `json.mjs`, `utf8.mjs`, `unit.mjs`, `ieee.mjs`).
245
+ files (`int.mjs`, `json.mjs`, `djson.mjs`, `utf8.mjs`, `unit.mjs`,
246
+ `ieee.mjs`).
240
247
  - **Native Browser Loading**: In `repl-codecs.mjs`, the browser reads the
241
248
  codec source from VFS, wraps it in a Blob, and invokes native `await
242
249
  import(blobUrl)`. No regex manipulation, import stripping, or global
@@ -1,20 +1,30 @@
1
1
  # File Formats in the K Universe
2
2
 
3
- The `k` toolchain operates across four primary file formats: `.k`,
4
- `.ko`, `.klib`, and `.kvm`. Each format occupies a distinct position
5
- in the pipeline from human-authored source to ahead-of-time (AOT)
6
- type-checked artifacts and JIT/native execution.
3
+ The `k` toolchain operates across five primary file formats: `.k`,
4
+ `.ko`, `.klib`, `.kvm`, and `.pkir`. Each format occupies a distinct
5
+ position in the pipeline from human-authored source to ahead-of-time
6
+ (AOT) type-checked artifacts, intermediate representations, and
7
+ JIT/native execution.
7
8
 
8
9
  ---
9
10
 
10
11
  ## Overview & Comparison
11
12
 
12
- | Extension | Role | Internal Storage | Entrypoint (`main`) | Generated By | Consumed By |
13
- |:----------:|:-----------------------------------|:------------------------------------------------|:-------------------------------|:----------------------------------|:--------------------------------------------------------|
14
- | **`.k`** | Human-readable source code | UTF-8 plain text | Optional (trailing expression) | Editor, `k-decompile` | `k.mjs`, `k-repl`, `k-compile`, backends |
15
- | **`.ko`** | Executable compiled object | Binary (`KOBJ\n` + JSON payload) | **Required** (`"__main__"`) | `k-compile`, REPL (`:ko`) | `k.mjs`, `k-wasm-compile`, `k-llvm-build`, inspect tools |
16
- | **`.klib`**| Reusable compiled library | UTF-8 JSON payload | **None** (`null`) | `k-compile --lib`, REPL (`:klib`) | REPL (`:load`), CLI linkers (`--lib`) |
17
- | **`.kvm`** | Polymorphic kVM bytecode template | JSON / CBOR (`format: "k-vm", layer: "KVM-P"`) | Per-relation functions | `k-compile --format kvm`, kvm.mjs | `kvm.mjs`, `k-wasm-compile`, `k-llvm-build` |
13
+ | Extension | Role | Format / Magic | Entrypoint |
14
+ |:---:|:---|:---|:---|
15
+ | **`.k`** | Human source code | UTF-8 plain text | Optional |
16
+ | **`.ko`** | Executable object | Binary (`KOBJ\n`) | Required |
17
+ | **`.klib`** | Reusable library | UTF-8 JSON | None |
18
+ | **`.kvm`** | Polymorphic kVM IR | `k-vm` (KVM-P) | Relations |
19
+ | **`.pkir`** | Polymorphic IR | `pk-ir` (v1) | Relations |
20
+
21
+ | Extension | Generated By | Consumed By |
22
+ |:---:|:---|:---|
23
+ | **`.k`** | Editor, `k-decompile` | `k.mjs`, `k-compile`, backends |
24
+ | **`.ko`** | `k-compile`, REPL (`:ko`) | `k.mjs`, backends, tools |
25
+ | **`.klib`** | `k-compile --lib` | REPL, linkers (`--lib`) |
26
+ | **`.kvm`** | `k-compile --format kvm` | `kvm.mjs`, backends |
27
+ | **`.pkir`** | `compileRelationToPKIR` | `executePKIR`, specializer |
18
28
 
19
29
  ### Format Transformation Workflow
20
30
 
@@ -30,20 +40,22 @@ flowchart TD
30
40
  KO[".ko (Executable Object)"]
31
41
  end
32
42
 
33
- subgraph IR_Artifacts ["Register IR"]
34
- KVM[".kvm (Polymorphic Template)"]
43
+ subgraph IR_Artifacts ["Intermediate Representations"]
44
+ KVM[".kvm (kVM Bytecode)"]
45
+ PKIR[".pkir (Polymorphic IR)"]
35
46
  end
36
47
 
37
48
  subgraph Targets ["Execution Targets"]
38
49
  WASM[".wasm (WebAssembly)"]
39
50
  NATIVE["Native Binary"]
40
- INTERP["Interpreter (k.mjs / kvm.mjs)"]
51
+ INTERP["Interpreter / kVM / PKIR"]
41
52
  end
42
53
 
43
54
  %% Transformations from .k
44
55
  K -->|"k-compile"| KO
45
56
  K -->|"k-compile --lib"| KLIB
46
57
  K -->|"k-compile --format kvm"| KVM
58
+ K -->|"compileRelationToPKIR"| PKIR
47
59
  K -->|":load"| REPL
48
60
 
49
61
  %% REPL exports
@@ -60,11 +72,22 @@ flowchart TD
60
72
  KO -->|"k-llvm-build"| NATIVE
61
73
  KO -->|"k.mjs"| INTERP
62
74
  KO -->|"k-decompile"| K
75
+ KO -->|"compileRelationToPKIR"| PKIR
63
76
 
64
77
  %% Lowering from .kvm
65
78
  KVM -->|"k-wasm-compile"| WASM
66
79
  KVM -->|"k-llvm-build"| NATIVE
67
80
  KVM -->|"kvm.mjs / specializeKVM"| INTERP
81
+
82
+ %% Execution and Specialization from .pkir
83
+ PKIR -->|"executePKIR + AccessTable"| INTERP
84
+ PKIR -->|"specializePKIR"| PKIR_SPEC["Specialized PKIR"]
85
+ PKIR -->|"k-wasm-compile"| WASM
86
+ PKIR -->|"k-llvm-compile"| LLVM[".ll (LLVM IR)"]
87
+ PKIR -->|"k-llvm-build"| NATIVE
88
+ PKIR_SPEC -->|"executePKIR"| INTERP
89
+ PKIR_SPEC -->|"backend lowering"| WASM
90
+ PKIR_SPEC -->|"backend lowering"| NATIVE
68
91
  ```
69
92
 
70
93
  ---
@@ -365,6 +388,204 @@ k-compile add5.ko add5.kvm
365
388
 
366
389
  ---
367
390
 
391
+ ## 5. `.pkir` — Polymorphic K Intermediate Representation File
392
+
393
+ ### What It Is
394
+ `.pkir` is a state-indexed, slot-addressed intermediate representation
395
+ artifact (`format: "pk-ir"`, `version: 1`).
396
+
397
+ While `.kvm` models imperative register control-flow using symbolic
398
+ field strings (`project_field`, `inst.label`), `.pkir` addresses the
399
+ fundamental data-layout problem for polymorphic functions. It unifies
400
+ streaming bitstream processing and random-access memory tables:
401
+
402
+ 1. **Slot Addressing & State Indexing:**
403
+ Eliminates all runtime string lookups (`val.product[label]`). Every
404
+ field access is compiled to an integer slot relative to an abstract
405
+ pattern state (`project_slot`, `slot`, `state`). Every variant test
406
+ is compiled to a branch index (`match_variant`, `branchId`, `state`).
407
+
408
+ 2. **Duality of Transducers & Witnesses:**
409
+ - **Streaming Pushdown Transducers:** Navigates prefix-free serialized
410
+ wire streams using static skip counts (`skipCount`). Erasing and
411
+ linear operations execute in $O(\text{depth})$ stack memory with zero
412
+ node materialization.
413
+ - **Layout Witnesses (`AccessTable`):** Operates on random-access
414
+ memory arenas. Given any concrete input schema $S$ and function
415
+ access profile $P$, `buildAccessTable(S, P)` resolves physical byte
416
+ offsets $\Omega(S, P)$ in a single array load.
417
+
418
+ 3. **Hybrid `KVal` Fat-Pointer Representation:**
419
+ Values remain compact serialized wire slices by default. When
420
+ non-linear access occurs (e.g. repeated reads or field reordering),
421
+ demand-driven **Spine Promotion** materializes only the outer product
422
+ node into an arena record while leaving child payloads as untouched
423
+ slices. Opaque payloads are never re-encoded or reconstructed.
424
+
425
+ ### Payload Structure
426
+
427
+ A `.pkir` artifact is structured as follows:
428
+
429
+ ```json
430
+ {
431
+ "format": "pk-ir",
432
+ "version": 1,
433
+ "name": "extract_id",
434
+ "inputReg": "%v0",
435
+ "outputReg": "%v1",
436
+ "inputPattern": 3,
437
+ "outputPattern": 4,
438
+ "patternGraph": { ... },
439
+ "accessProfile": {
440
+ "0": { "fields": ["id"], "variants": [] },
441
+ "3": { "fields": [], "variants": ["click", "sensor", "ping"] }
442
+ },
443
+ "instructions": [
444
+ {
445
+ "op": "union",
446
+ "dest": "%v1",
447
+ "src": "%v0",
448
+ "branches": [ ... ]
449
+ }
450
+ ]
451
+ }
452
+ ```
453
+
454
+ #### Instruction Set Summary
455
+ - `id`: Register assignment (`{ op: "id", dest, src }`).
456
+ - `project_slot`: State-indexed slot projection
457
+ (`{ op: "project_slot", dest, src, state, slot, label }`).
458
+ - `match_variant`: State-indexed variant match
459
+ (`{ op: "match_variant", dest, src, state, tag, branchId }`).
460
+ - `make_variant`: Variant construction
461
+ (`{ op: "make_variant", dest, src, tag }`).
462
+ - `product`: Product construction with sub-instruction streams.
463
+ - `union`: Multi-branch selection with failure backtracking.
464
+ - `call_rel`: Relation call / recursion
465
+ (`{ op: "call_rel", dest, ref, src }`).
466
+ - `fail`: Unconditional branch failure (`{ op: "fail" }`).
467
+ - **Specialized Instructions:**
468
+ - `project_offset`: Direct memory offset projection:
469
+ `{ op: "project_offset", dest, src, offset, skipCount, childState }`.
470
+ - `match_tag_imm`: Immediate discriminator test
471
+ (`{ op: "match_tag_imm", dest, src, tagId, branchId, childState }`).
472
+
473
+ ### Why `.pkir` Exists (What You Gain)
474
+
475
+ 1. **Elimination of the Envelope Tax (26x Speedup):**
476
+ Previous polymorphic execution required wrapping values in dynamic
477
+ envelopes $(v, P_v)$, suffering a 26x performance penalty during
478
+ envelope packing/unpacking (`scripts/perf-poly.mjs`). PKIR navigates
479
+ heterogeneous records directly via layout witnesses without envelopes.
480
+
481
+ 2. **Sub-30µs Specialization Latency:**
482
+ `specializePKIR` bakes static byte offsets into instructions and prunes
483
+ dead union branches in ~27 microseconds (compared to 100–1500 ms for
484
+ traditional AOT/Wasm compilation), enabling instant JIT tiering.
485
+
486
+ 3. **Zero Payload Re-Encoding:**
487
+ Preserves arbitrary opaque payloads (`data: payload_i`) as byte slices
488
+ without traversal or re-serialization during recursive list
489
+ processing (`search`, `poly_rev`).
490
+
491
+ 4. **1:1 Machine Code Lowering:**
492
+ Specialized PKIR instructions map directly to WebAssembly (`i64.load
493
+ offset=C`, `i32.eq`) and LLVM machine instructions without dynamic
494
+ runtime fallbacks (`@k_product_get_n`).
495
+
496
+ ### How to Generate
497
+
498
+ In JavaScript / Node.js API:
499
+ ```javascript
500
+ import { compileRelationToPKIR } from "@fraczak/k/backend-api.mjs";
501
+
502
+ const pkir = compileRelationToPKIR(relDef, "extract_id");
503
+ ```
504
+
505
+ ### How to Consume
506
+
507
+ - **Direct Execution with AccessTable:**
508
+ ```javascript
509
+ import {
510
+ executePKIR,
511
+ buildAccessTable,
512
+ valueToKVal,
513
+ kvalToValue
514
+ } from "@fraczak/k/backend-api.mjs";
515
+
516
+ const table = buildAccessTable(schemaS, patternP);
517
+ const kval = valueToKVal(inputVal, table.rootState);
518
+ const resKval = executePKIR(pkir, kval, table);
519
+ const result = kvalToValue(resKval);
520
+ ```
521
+
522
+ - **Monomorphic Specialization (`specializePKIR`):**
523
+ ```javascript
524
+ import {
525
+ specializePKIR,
526
+ executePKIR
527
+ } from "@fraczak/k/backend-api.mjs";
528
+
529
+ // Inlines static byte offsets and prunes dead union branches:
530
+ const specialized = specializePKIR(pkir, table);
531
+
532
+ // Executes with zero table overhead:
533
+ const result = executePKIR(specialized, kval, null);
534
+ ```
535
+
536
+ - **Lowering to WebAssembly (`compileWasmArtifactFromPKIR`):**
537
+ ```javascript
538
+ import {
539
+ compileWasmArtifactFromPKIR
540
+ } from "@fraczak/k/backend-api.mjs";
541
+
542
+ const wasmBytes = await compileWasmArtifactFromPKIR(pkir);
543
+ ```
544
+ CLI commands:
545
+ ```bash
546
+ # Compile .pkir directly to WebAssembly binary:
547
+ node backends/wasm/bin/k-wasm-compile.mjs input.pkir -o prog.wasm
548
+
549
+ # Lower .k source via PKIR to WebAssembly:
550
+ node backends/wasm/bin/k-wasm-compile.mjs --pkir prog.k -o prog.wasm
551
+ ```
552
+
553
+ - **Lowering to LLVM IR & Native Binaries:**
554
+ ```javascript
555
+ import {
556
+ compileLLVMArtifactFromPKIR
557
+ } from "@fraczak/k/backend-api.mjs";
558
+ import {
559
+ compilePKIRToExecutable,
560
+ compilePKIRAndRun
561
+ } from "@fraczak/k/backends/llvm/src/executable.mjs";
562
+
563
+ // Compile PKIR directly to LLVM IR string:
564
+ const llvmIR = compileLLVMArtifactFromPKIR(pkir);
565
+
566
+ // Compile PKIR directly to a native executable:
567
+ compilePKIRToExecutable(pkir, "./prog.exe");
568
+
569
+ // Compile and execute in one step:
570
+ const res = compilePKIRAndRun(pkir, { input: inputVal });
571
+ ```
572
+ CLI commands:
573
+ ```bash
574
+ # Compile .pkir directly to LLVM IR:
575
+ node backends/llvm/bin/k-llvm-compile.mjs input.pkir -o prog.ll
576
+
577
+ # Lower .k source via PKIR to LLVM IR:
578
+ node backends/llvm/bin/k-llvm-compile.mjs --pkir prog.k -o prog.ll
579
+
580
+ # Compile .pkir directly to native executable:
581
+ node backends/llvm/bin/k-llvm-build.mjs input.pkir -o prog.exe
582
+
583
+ # Lower .k source via PKIR to native executable:
584
+ node backends/llvm/bin/k-llvm-build.mjs --pkir prog.k -o prog.exe
585
+ ```
586
+
587
+ ---
588
+
368
589
  ## Practical Rules & Common Gotchas
369
590
 
370
591
  ### 1. Library Aliases Require Explicit `--export`
@@ -398,9 +619,11 @@ In `k`, there are no primitive numerical types or built-in integer
398
619
  literals. Identifiers such as `5` or `10` are not language keywords;
399
620
  they are defined relations (aliases) in `Examples/arithmetics.k`:
400
621
  - `5` and `10` are nullary relations (constants) of type `{} -> bits`,
401
- defined as binary digit trees over `bits? = ?< {} _, bits? 0, bits? 1 > = bits?;`.
622
+ defined as binary digit trees over:
623
+ `bits? = ?< {} _, bits? 0, bits? 1 > = bits?;`.
402
624
  - Arithmetic operations (`plus`, `minus`, `times`, `inc`) operate on
403
- signed integers (`int? = ?< <bits 0, bits 1, {} _>=bits "+", bits "-" >`).
625
+ signed integers:
626
+ `int? = ?< <bits 0, bits 1, {} _>=bits "+", bits "-" >`.
404
627
  - Passing a bit-representation like `5` to an integer relation requires
405
628
  applying the `int` constructor (`5 int`), producing a constant
406
629
  relation of type `{} -> int`.
@@ -0,0 +1,104 @@
1
+ # Polymorphic K Intermediate Representation (PKIR)
2
+
3
+ ## 1. Overview
4
+
5
+ PKIR (Polymorphic K Intermediate Representation) is the target execution
6
+ contract for polymorphic `k` relations.
7
+
8
+ Unlike the high-level relational AST or traditional bytecode that
9
+ relies on runtime string lookups for field names and variant tags, PKIR
10
+ is a **state-indexed, slot-addressed intermediate representation**.
11
+
12
+ PKIR operates in two cooperating execution modes:
13
+ 1. **Generic Polymorphic Mode**: Instructions execute against a
14
+ precomputed `AccessTable` (Layout Witness), accessing fields and
15
+ variants via static slot numbers and array lookups with zero string
16
+ comparisons.
17
+ 2. **Specialized Monomorphic Mode**: Given an `AccessTable`, a fast linear
18
+ pass (`specializePKIR`) inlines offsets directly into immediate machine
19
+ instructions, pruning unreachable union branches for peak LLVM/Wasm
20
+ performance.
21
+
22
+ ---
23
+
24
+ ## 2. Core Concepts
25
+
26
+ ### 2.1 The Structural Access Profile
27
+
28
+ Every PKIR relation is accompanied by an **Access Profile** derived from
29
+ its pattern graph:
30
+ - For every product pattern node $u$: a list of accessed field labels
31
+ defining dense, zero-based **logical slots**:
32
+ $$\text{fields}(u) = [ f_0, f_1, \dots, f_{k-1} ]$$
33
+ where slot $i$ corresponds to field $f_i$.
34
+ - For every union pattern node $u$: a list of matched variant tags
35
+ defining dense **branch targets**:
36
+ $$\text{variants}(u) = [ v_0, v_1, \dots, v_{m-1} ]$$
37
+ where branch $j$ corresponds to variant $v_j$.
38
+
39
+ ### 2.2 Dual-Form Values (`KVal`)
40
+
41
+ Values in PKIR conform to the hybrid representation:
42
+ - **Serialized (Wire Slice)**: A pointer into an immutable prefix-free
43
+ bitstream, carrying a bit offset and schema state.
44
+ - **Materialized (Arena Node)**: An allocated record in memory containing
45
+ word-aligned pointers to child values.
46
+
47
+ ---
48
+
49
+ ## 3. Instruction Set
50
+
51
+ PKIR instructions operate over a register file (`%v0`, `%v1`, ...):
52
+
53
+ ### 3.1 Field & Variant Operations
54
+
55
+ - **`project_slot dest, src, state, slot`**:
56
+ Projects field at logical `slot` of pattern `state` from `src`.
57
+ At runtime with `AccessTable`:
58
+ ```c
59
+ dest.ptr = src.ptr + table[src.state].slotToByteOffset[slot];
60
+ dest.state = table[src.state].slotToChildState[slot];
61
+ ```
62
+ - **`match_tag src, state, branches`**:
63
+ Evaluates variant discriminator of `src` against pattern `state`.
64
+ At runtime with `AccessTable`:
65
+ ```c
66
+ branch_idx = table[src.state].branchMap[src.tag];
67
+ dest.state = table[src.state].childStateMap[src.tag];
68
+ jump branches[branch_idx];
69
+ ```
70
+ - **`make_variant dest, src, tag_id`**:
71
+ Wraps `src` into a tagged union with discriminator `tag_id`.
72
+ - **`make_product dest, [src0, src1, ...]`**:
73
+ Allocates a product node whose fields are registers `[src0, src1, ...]`.
74
+
75
+ ### 3.2 Memory & Control Operations
76
+
77
+ - **`promote_spine dest, src`**:
78
+ If `src` is in serialized wire form, materializes only its immediate
79
+ outer record in the arena; children remain serialized wire slices.
80
+ If `src` is already materialized, acts as identity.
81
+ - **`dup dest1, dest2, src`**:
82
+ Zero-copy duplication of a value handle.
83
+ - **`call_rel dest, rel_name, src`**:
84
+ Invokes relation `rel_name` with input `src`.
85
+ - **`id dest, src`**:
86
+ Identity move.
87
+ - **`fail`**:
88
+ Signals partial function failure (backtracking or branch exit).
89
+
90
+ ---
91
+
92
+ ## 4. Execution Pipeline
93
+
94
+ ```text
95
+ [AOT Phase]
96
+ k source -> AST -> Type Pattern Graph -> PKIR Relation
97
+
98
+ [Runtime Invocation with (Schema S, Payload V)]
99
+ 1. AccessTable = buildAccessTable(S, PKIR.patternGraph)
100
+ 2. Choose execution tier:
101
+ - Tier 0 (Interpreter): executePKIR(PKIR, V, AccessTable)
102
+ - Tier 1 (Specialized AOT/JIT): specializePKIR(PKIR, AccessTable)
103
+ -> direct emission to LLVM / WebAssembly
104
+ ```
package/DOCS/REPL.md CHANGED
@@ -33,10 +33,11 @@ is complete.
33
33
  | Command | Meaning |
34
34
  | --- | --- |
35
35
  | `:help` | Show command summary |
36
- | `:engine [wasm|js]` | Display or switch evaluation engine (`wasm` or `js`) |
37
- | `:wasm` / `:js` | Shortcut to switch engine |
36
+ | `:engine [wasm\|pkir\|js]` | Display or switch evaluation engine (`wasm`, `pkir`, or `js`) |
37
+ | `:wasm` / `:pkir` / `:js` | Shortcut to switch engine |
38
38
  | `:rel name` | Show relation definition |
39
39
  | `:rels` | List relation aliases |
40
+ | `:limit [num\|none]` | Set maximum characters for value output (default: 4096) |
40
41
  | `:codec load file` | Load a codec from an ES module file (e.g. `:codec load codecs/int.mjs`) |
41
42
  | `:codec unload name` | Unload a registered codec |
42
43
  | `:codec list` | List loaded REPL codecs (alias: `:codecs`) |
@@ -231,11 +232,13 @@ The REPL supports two evaluation engines:
231
232
 
232
233
  ### CLI Options
233
234
 
234
- When starting `k-repl`, choose the engine with:
235
+ When starting `k-repl`, choose the engine or output limit with:
235
236
 
236
237
  ```bash
237
238
  k-repl --engine=js # or k-repl --js
239
+ k-repl --engine=pkir # or k-repl --pkir
238
240
  k-repl --engine=wasm # or k-repl --wasm (default)
241
+ k-repl --limit=8192 # set max characters for rendered output
239
242
  ```
240
243
 
241
244
  ## Timing and Profiling
@@ -297,6 +300,11 @@ Evaluated values print in k syntax together with the inferred envelope:
297
300
  {}|0|+1 ?<<{} 0, ...> +1, ...>
298
301
  ```
299
302
 
303
+ Large values are rendered iteratively and truncated at `maxChars`
304
+ (default: `4096` characters) so deeply nested or large values print
305
+ instantly without exhausting stack or terminal buffers. Use
306
+ `:limit <num>` or `:limit none` to adjust or disable the limit.
307
+
300
308
  `undefined` prints as:
301
309
 
302
310
  ```text
@@ -113,7 +113,7 @@ The bundled VFS and UI examples must include only verified useful files:
113
113
  #### 1. Curated Files Explorer
114
114
  In the Web REPL "Files" (VFS) explorer, the visible files are strictly curated to verified examples and codecs:
115
115
  - **k-codes**: `core.k`, `arithmetics.k`, `ieee.k`
116
- - **codecs**: `json.mjs`, `utf8.mjs`, `int.mjs`, `unit.mjs`, `ieee.mjs`
116
+ - **codecs**: `json.mjs`, `djson.mjs`, `utf8.mjs`, `int.mjs`, `unit.mjs`, `ieee.mjs`
117
117
  - User-created or uploaded files remain visible.
118
118
  - Internal runtime artifacts (`backends/wasm/runtime.wat`) and redundant directory prefixes (`Examples/`, `codecs/`) are kept accessible internally but hidden from the default file listing.
119
119
  - Clicking "Load" on a `.mjs` file automatically executes `:codec load <filename>`.