@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.
- package/CHANGELOG.md +42 -0
- package/DOCS/FILE_FORMATS.md +238 -15
- package/DOCS/POLYMORPHIC_IR.md +104 -0
- package/JOURNAL.md +288 -0
- package/README.md +10 -2
- package/access-table.mjs +343 -0
- package/backend-api.mjs +18 -0
- package/backends/llvm/README.md +20 -21
- package/backends/llvm/bin/k-llvm-build.mjs +105 -32
- package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
- package/backends/llvm/bin/k-llvm.mjs +292 -0
- package/backends/llvm/runtime/krt.c +8 -0
- package/backends/llvm/runtime/krt.h +1 -0
- package/backends/llvm/src/cli.mjs +95 -17
- package/backends/llvm/src/executable.mjs +128 -11
- package/backends/llvm/src/kvm2llvm.mjs +10 -5
- package/backends/llvm/src/llvm.mjs +121 -9
- package/backends/llvm/tests/integration.sh +11 -11
- package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
- package/backends/llvm/tests/perf-support.mjs +24 -3
- package/backends/llvm/tests/test-llvm.mjs +22 -1
- package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
- package/backends/wasm/bin/k-wasm-run.mjs +61 -20
- package/backends/wasm/bin/k-wasm.mjs +47 -13
- package/backends/wasm/src/cli.mjs +141 -19
- package/backends/wasm/src/wasm.mjs +130 -23
- package/browser/repl-browser.mjs +16 -5
- package/codecs/k-parse.mjs +29 -8
- package/codecs/k-print.mjs +22 -6
- package/codecs/runtime/codec-sdk.mjs +8 -4
- package/codecs/show.mjs +20 -6
- package/k.mjs +56 -16
- package/kir.mjs +58 -19
- package/kvm.mjs +49 -12
- package/objects/compile.mjs +37 -23
- package/objects/decompile.mjs +40 -10
- package/objects/extract-aliases.mjs +44 -14
- package/objects/inspect.mjs +19 -14
- package/objects/validate.mjs +18 -11
- package/package.json +10 -3
- package/pkir.mjs +772 -0
- package/repl.mjs +36 -18
- package/scripts/build-repl-html.mjs +14 -2
- package/scripts/perf-ieee.mjs +264 -13
- package/scripts/perf-int.mjs +315 -22
- package/scripts/perf-multiplication.mjs +58 -7
- package/scripts/perf-poly.mjs +306 -24
- package/scripts/run-tests.mjs +3 -0
- package/tests/test-access-table.mjs +213 -0
- package/tests/test-pkir.mjs +530 -0
- package/tests/test-polymorphic-tdd.mjs +196 -0
- package/tests/test-repl-html.mjs +15 -2
- package/tests/test-repl.mjs +30 -1
- 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
|
package/DOCS/FILE_FORMATS.md
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
# File Formats in the K Universe
|
|
2
2
|
|
|
3
|
-
The `k` toolchain operates across
|
|
4
|
-
`.ko`, `.klib`, and `.
|
|
5
|
-
in the pipeline from human-authored source to ahead-of-time
|
|
6
|
-
type-checked artifacts
|
|
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
|
|
13
|
-
|
|
14
|
-
| **`.k`**
|
|
15
|
-
| **`.ko`**
|
|
16
|
-
| **`.klib
|
|
17
|
-
| **`.kvm`** | Polymorphic kVM
|
|
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 ["
|
|
34
|
-
KVM[".kvm (
|
|
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
|
|
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
|
|
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
|
|
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
|
+
```
|