@fraczak/k 7.0.2 → 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 (54) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/DOCS/FILE_FORMATS.md +238 -15
  3. package/DOCS/POLYMORPHIC_IR.md +104 -0
  4. package/JOURNAL.md +288 -0
  5. package/README.md +10 -2
  6. package/access-table.mjs +343 -0
  7. package/backend-api.mjs +18 -0
  8. package/backends/llvm/README.md +20 -21
  9. package/backends/llvm/bin/k-llvm-build.mjs +105 -32
  10. package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
  11. package/backends/llvm/bin/k-llvm.mjs +292 -0
  12. package/backends/llvm/runtime/krt.c +8 -0
  13. package/backends/llvm/runtime/krt.h +1 -0
  14. package/backends/llvm/src/cli.mjs +95 -17
  15. package/backends/llvm/src/executable.mjs +128 -11
  16. package/backends/llvm/src/kvm2llvm.mjs +10 -5
  17. package/backends/llvm/src/llvm.mjs +121 -9
  18. package/backends/llvm/tests/integration.sh +11 -11
  19. package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
  20. package/backends/llvm/tests/perf-support.mjs +24 -3
  21. package/backends/llvm/tests/test-llvm.mjs +22 -1
  22. package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
  23. package/backends/wasm/bin/k-wasm-run.mjs +61 -20
  24. package/backends/wasm/bin/k-wasm.mjs +47 -13
  25. package/backends/wasm/src/cli.mjs +141 -19
  26. package/backends/wasm/src/wasm.mjs +130 -23
  27. package/browser/repl-browser.mjs +16 -5
  28. package/codecs/k-parse.mjs +29 -8
  29. package/codecs/k-print.mjs +22 -6
  30. package/codecs/runtime/codec-sdk.mjs +8 -4
  31. package/codecs/show.mjs +20 -6
  32. package/k.mjs +56 -16
  33. package/kir.mjs +58 -19
  34. package/kvm.mjs +49 -12
  35. package/objects/compile.mjs +37 -23
  36. package/objects/decompile.mjs +40 -10
  37. package/objects/extract-aliases.mjs +44 -14
  38. package/objects/inspect.mjs +19 -14
  39. package/objects/validate.mjs +18 -11
  40. package/package.json +10 -3
  41. package/pkir.mjs +772 -0
  42. package/repl.mjs +36 -18
  43. package/scripts/build-repl-html.mjs +14 -2
  44. package/scripts/perf-ieee.mjs +264 -13
  45. package/scripts/perf-int.mjs +315 -22
  46. package/scripts/perf-multiplication.mjs +58 -7
  47. package/scripts/perf-poly.mjs +306 -24
  48. package/scripts/run-tests.mjs +3 -0
  49. package/tests/test-access-table.mjs +213 -0
  50. package/tests/test-pkir.mjs +530 -0
  51. package/tests/test-polymorphic-tdd.mjs +196 -0
  52. package/tests/test-repl-html.mjs +15 -2
  53. package/tests/test-repl.mjs +30 -1
  54. package/backends/llvm/bin/k-llvm-jit.mjs +0 -160
package/CHANGELOG.md CHANGED
@@ -5,6 +5,48 @@ 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.1.0] — 2026-10-16 — Polymorphic K IR (PKIR) & CLI Standardization
9
+
10
+ ### Features & Architecture Improvements
11
+
12
+ - **Polymorphic K IR (PKIR) & Access Table Engine**:
13
+ - Implemented `pkir.mjs` providing an intermediate representation
14
+ tailored for polymorphic relations with variant dispatch, projection
15
+ tables, and partial function failure semantics.
16
+ - Implemented `access-table.mjs` (`buildAccessTable`) for resolving
17
+ field offsets and variant selectors across arbitrary schemas.
18
+ - Added PKIR specialization (`specializePKIR`) eliminating dead
19
+ branches and baking in direct physical offsets.
20
+ - Supported PKIR execution and standalone executable generation across
21
+ both WebAssembly and LLVM backends.
22
+ - Added dedicated test suites: `tests/test-pkir.mjs`,
23
+ `tests/test-access-table.mjs`, and `tests/test-polymorphic-tdd.mjs`.
24
+ - Added specification and documentation in `DOCS/POLYMORPHIC_IR.md`
25
+ and updated `DOCS/FILE_FORMATS.md`.
26
+
27
+ - **Web REPL (`repl.html`) & Wasm Integration**:
28
+ - Enabled `.pkir` generation and lowering to WebAssembly in
29
+ `repl.mjs` and `repl.html`.
30
+ - Promoted Web REPL visibility in `README.md` (top banner,
31
+ zero-install section, further reading).
32
+
33
+ - **Multi-Backend CLI Standardization & Help Completeness**:
34
+ - Standardized CLI syntax, argument parsing, options, and help text
35
+ (`-h` / `--help`) across tools in `backends/*/bin/` and
36
+ `objects/`.
37
+ - Consolidated `backends/llvm/bin/` (`k-llvm.mjs`, `k-llvm-build.mjs`,
38
+ `k-llvm-compile.mjs`) to mirror `backends/wasm/bin/`.
39
+ - Aligned `--lib` and `--export` options across LLVM, Wasm, and object
40
+ tools.
41
+ - Documented explicit defaults (such as cache directories, Clang
42
+ optimization levels, and runtime modes) in CLI help texts.
43
+
44
+ - **Concurrent Multi-Backend Performance Benchmarks**:
45
+ - Added concurrent `llvm` and `llvm-pkir` execution lanes across all
46
+ performance suites (`perf:ieee`, `perf:int`, `perf:poly`,
47
+ `perf:mult`).
48
+ - Documented benchmark findings and throughput in `JOURNAL.md`.
49
+
8
50
  ## [7.0.2] — 2026-10-13 — LLVM Squaring Scaling & Backend Streamlining
9
51
 
10
52
  ### Features & Performance Improvements
@@ -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
+ ```