@fraczak/k 6.1.3 → 6.2.1
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/AGENTS.md +4 -4
- package/CLAUDE.md +1 -1
- package/DOCS/KIR_SPECIALIZATION_DESIGN.md +11 -2
- package/DOCS/KVM_EXECUTION_MODEL.md +413 -0
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +6 -0
- package/DOCS/REPL.md +22 -17
- package/{NAT.k~ → Examples/arithmetics.k} +1 -1
- package/Examples/bnat.k +291 -0
- package/Examples/byte.k +67 -0
- package/Examples/code.k +44 -0
- package/Examples/esc.k +9 -0
- package/Examples/ieee.k +15766 -0
- package/Examples/list.k +7 -0
- package/Examples/nat.k +12 -0
- package/Examples/vhdl_to_k.k +50 -0
- package/README.md +14 -5
- package/backend-api.mjs +12 -0
- package/codecs/runtime/codec.mjs +1 -0
- package/export.mjs +10 -0
- package/k-vscode/README.md +10 -1
- package/k-vscode/extension.js +273 -0
- package/k-vscode/package.json +22 -0
- package/k-vscode/syntaxes/k.tmLanguage.json +493 -137
- package/k-vscode/test/background-ranges.test.js +50 -0
- package/k-vscode/themes/k-contrast-color-theme.json +104 -0
- package/kvm.mjs +523 -0
- package/package.json +4 -3
- package/repl.mjs +43 -2
- package/run.mjs +1 -1
- package/scripts/run-tests.mjs +55 -0
- package/tests/README.md +35 -0
- package/{Code-derivation-tests → tests/code-derivation}/codec-witness-pattern.mjs +4 -4
- package/{Code-derivation-tests → tests/code-derivation}/convergence-strategy.mjs +1 -1
- package/{Code-derivation-tests → tests/code-derivation}/dot.mjs +1 -1
- package/{Code-derivation-tests → tests/code-derivation}/filter-syntax.mjs +1 -1
- package/{Code-derivation-tests → tests/code-derivation}/index.mjs +1 -1
- package/{Code-derivation-tests → tests/code-derivation}/pattern-envelope.mjs +5 -5
- package/{Code-derivation-tests → tests/code-derivation}/product.mjs +1 -1
- package/{tests.sh → tests/integration.sh} +11 -6
- package/{test-fingerprint.mjs → tests/test-fingerprint.mjs} +3 -3
- package/{test-hash-fuzz.mjs → tests/test-hash-fuzz.mjs} +1 -1
- package/{test-hash-normalization.mjs → tests/test-hash-normalization.mjs} +2 -2
- package/{test-ieee-arithmetic.mjs → tests/test-ieee-arithmetic.mjs} +14 -27
- package/{test-k-object.mjs → tests/test-k-object.mjs} +8 -8
- package/tests/test-kvm.mjs +163 -0
- package/{test-repl.mjs → tests/test-repl.mjs} +22 -4
- package/{test.mjs → tests/test.mjs} +1 -1
- package/.codex +0 -0
- package/DOCS/a.html +0 -398
- package/DOCS/dependency-graph.html +0 -140
- package/DOCS/dependency-graph.md +0 -144
- package/UU/ta.k +0 -1
- package/UU/ta.k~ +0 -0
- package/UU/tb.k +0 -0
- package/UU/tc.k +0 -0
- package/a.k +0 -138
- package/a.klib +0 -1
- package/codecs/BINARY_FORMAT.html +0 -471
- package/codecs/POLYMORPHIC_BINARY_FORMAT.html +0 -355
- package/core.json +0 -1
- package/core.klib +0 -1
- package/core.klib~ +0 -0
- package/ieee.klib +0 -1
- package/k-vscode/package-lock.json +0 -4176
- package/kkk.k +0 -197
- package/kkk.klib +0 -0
- package/kkk.klib~ +0 -0
- package/nak.klib +0 -1
- package/nak2.klib +0 -1
- package/nat.k +0 -10
- package/nat2.k +0 -9
- package/p.json +0 -5475
- package/type_registry/registry.mjs~ +0 -105
- package/type_registry/typeParser.jison~ +0 -132
- /package/{Code-derivation-tests → tests/code-derivation}/blowup.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/bnat.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/loop.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/nat.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/not-not.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/rlz.mjs +0 -0
package/AGENTS.md
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
- `k_compiler/` contains the Python prototype compiler and supporting modules.
|
|
6
6
|
- `type_registry/` houses registry experiments and grammar artifacts.
|
|
7
7
|
- `Examples/` and `DOCS/` provide sample programs and design notes.
|
|
8
|
-
- Tests live in
|
|
8
|
+
- Tests live in `tests/`, with type-derivation cases in `tests/code-derivation/`.
|
|
9
9
|
|
|
10
10
|
## Build, Test, and Development Commands
|
|
11
11
|
- `npm install` installs dev dependencies and runs `prepare` to generate parsers.
|
|
12
12
|
- `npm run prepare` regenerates `parser.mjs` and `valueParser.mjs` from `.jison` grammars.
|
|
13
|
-
- `npm test` runs the full suite
|
|
13
|
+
- `npm test` runs the full suite through `scripts/run-tests.mjs`.
|
|
14
14
|
- `node repl.mjs` (or `k-repl`) starts the interactive REPL.
|
|
15
15
|
- `./k.mjs -k <file.k>` executes a k script on binary pattern+value stream input from stdin or a file; use `k-parse` and `k-print` at the boundaries.
|
|
16
16
|
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
- Grammar sources are `parser.jison` and `valueParser.jison`; generated files should not be hand-edited.
|
|
22
22
|
|
|
23
23
|
## Testing Guidelines
|
|
24
|
-
- Add runtime tests alongside `test.mjs` or new `test-*.mjs` files.
|
|
25
|
-
- Add type-derivation coverage in `
|
|
24
|
+
- Add runtime tests alongside `tests/test.mjs` or new `tests/test-*.mjs` files.
|
|
25
|
+
- Add type-derivation coverage in `tests/code-derivation/` (one case per file is typical).
|
|
26
26
|
- Verify locally with `npm test` before opening a PR.
|
|
27
27
|
|
|
28
28
|
## Commit & Pull Request Guidelines
|
package/CLAUDE.md
CHANGED
|
@@ -60,5 +60,5 @@ npm test # Run comprehensive test suite (unit tests, derivation tests, shell te
|
|
|
60
60
|
|
|
61
61
|
- No external runtime dependencies (only jiwson for parser generation)
|
|
62
62
|
- Uses ES6 modules (.mjs files) throughout
|
|
63
|
-
- Extensive test suite in `
|
|
63
|
+
- Extensive test suite in `tests/code-derivation/` for type system validation
|
|
64
64
|
- REPL supports commands like `:C name` (show canonical type), `:t name` (show relation type), and `:d name` (show relation definition)
|
|
@@ -78,6 +78,14 @@ Alternative:
|
|
|
78
78
|
- Compile KIR-P directly. This is useful for a correctness experiment, but it
|
|
79
79
|
recreates the polymorphic interpreter and is not the final performance path.
|
|
80
80
|
|
|
81
|
+
Relationship to kVM:
|
|
82
|
+
|
|
83
|
+
- [KVM_EXECUTION_MODEL.md](KVM_EXECUTION_MODEL.md) sketches kVM as the concrete
|
|
84
|
+
execution contract for KIR-M.
|
|
85
|
+
- KIR-R remains the retyping contract.
|
|
86
|
+
- kVM keeps product and union as structured regions so backends can choose
|
|
87
|
+
sequential execution first, then safe parallel scheduling later.
|
|
88
|
+
|
|
81
89
|
## Object IR
|
|
82
90
|
|
|
83
91
|
### Step 1: Define KIR-P
|
|
@@ -449,10 +457,11 @@ Alternative:
|
|
|
449
457
|
10. Add call-site retyping for helper relations.
|
|
450
458
|
11. Add retyping cache.
|
|
451
459
|
12. Reject non-converged relations in LLVM/Wasm compilation.
|
|
452
|
-
13. Prototype a small C or Wasm backend
|
|
460
|
+
13. Prototype a small C or Wasm backend through kVM.
|
|
453
461
|
|
|
454
462
|
Rule:
|
|
455
463
|
|
|
456
464
|
- KIR-P is the portable semantic contract.
|
|
457
465
|
- KIR-R is the retyping contract.
|
|
458
|
-
- KIR-M is backend material
|
|
466
|
+
- KIR-M is backend material; kVM is the proposed concrete execution model for
|
|
467
|
+
that material.
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# kVM Execution Model
|
|
2
|
+
|
|
3
|
+
This note sketches a low-level execution model for `k`. The goal is to place
|
|
4
|
+
one abstraction exactly between the current JavaScript evaluator and concrete
|
|
5
|
+
backends such as LLVM and WebAssembly.
|
|
6
|
+
|
|
7
|
+
The working name is **kVM**. It is not primarily a bytecode format. It is an
|
|
8
|
+
execution contract: a small value model, a small instruction set, and precise
|
|
9
|
+
rules for partial failure, products, unions, calls, and safe scheduling.
|
|
10
|
+
|
|
11
|
+
## Position In The Pipeline
|
|
12
|
+
|
|
13
|
+
The current design already points at three layers:
|
|
14
|
+
|
|
15
|
+
- KIR-P: portable, polymorphic object IR.
|
|
16
|
+
- KIR-R: KIR-P retyped for a concrete input envelope pattern.
|
|
17
|
+
- KIR-M: backend material after layout and ABI decisions.
|
|
18
|
+
|
|
19
|
+
kVM should make KIR-M concrete.
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
k source
|
|
23
|
+
-> AST
|
|
24
|
+
-> type derivation
|
|
25
|
+
-> KIR-P object relation
|
|
26
|
+
-> KIR-R relation instance for an input pattern
|
|
27
|
+
-> kVM function
|
|
28
|
+
-> LLVM / Wasm / C / JS kVM interpreter
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
KIR-P remains the portable semantic object format. KIR-R remains the retyping
|
|
32
|
+
contract. kVM is the executable middle form consumed by code generators.
|
|
33
|
+
|
|
34
|
+
## Design Center
|
|
35
|
+
|
|
36
|
+
Every `k` relation is a pure first-order partial function:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
KRef -> KResult<KRef>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
where:
|
|
43
|
+
|
|
44
|
+
- `KRef` is a reference to an immutable runtime value;
|
|
45
|
+
- `KResult` is either `ok(value)` or `fail`;
|
|
46
|
+
- failure is ordinary partial-function undefinedness, not an exception;
|
|
47
|
+
- user-level computation has no mutable environment and no observable effects.
|
|
48
|
+
|
|
49
|
+
This purity is central. It means kVM can expose parallel product and
|
|
50
|
+
speculative union execution while preserving exactly the same deterministic
|
|
51
|
+
semantics as the interpreter.
|
|
52
|
+
|
|
53
|
+
Current debug or host operations such as `_log!` do not fit the pure backend
|
|
54
|
+
contract. They should either be excluded from kVM backend eligibility or marked
|
|
55
|
+
as effectful intrinsics that create ordering barriers.
|
|
56
|
+
|
|
57
|
+
## Value Model
|
|
58
|
+
|
|
59
|
+
A kVM value reference should be more abstract than an LLVM pointer but more
|
|
60
|
+
explicit than the current JavaScript `Value` object.
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
KRef {
|
|
64
|
+
repr: serialized | materialized | external,
|
|
65
|
+
addr: backend-specific handle,
|
|
66
|
+
pattern: optional runtime pattern,
|
|
67
|
+
staticPattern: optional kVM pattern id,
|
|
68
|
+
layout: optional layout id,
|
|
69
|
+
ownership: borrowed | owned
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The important property is immutability. A `KRef` may point into the original
|
|
74
|
+
binary input stream, a materialized node, a constructed result, or an external
|
|
75
|
+
host value. Projections can often produce new `KRef`s without allocation.
|
|
76
|
+
Construction creates new immutable values.
|
|
77
|
+
|
|
78
|
+
There are two valid execution modes:
|
|
79
|
+
|
|
80
|
+
- **Envelope-aware mode**: each `KRef` may carry a runtime pattern, matching the
|
|
81
|
+
current interpreter and codec model.
|
|
82
|
+
- **Envelope-free mode**: retyping has proven the input and output patterns for
|
|
83
|
+
every call site, so inner operations use static layouts and attach the derived
|
|
84
|
+
output pattern only at the boundary.
|
|
85
|
+
|
|
86
|
+
The first mode is the reference path. The second mode is the main LLVM/Wasm
|
|
87
|
+
performance path.
|
|
88
|
+
|
|
89
|
+
## Function Shape
|
|
90
|
+
|
|
91
|
+
A kVM relation instance is specialized by relation hash plus input pattern hash:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
fn @rel_hash__input_pattern_hash(%input: KRef) -> KResult<KRef>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Recursive relations compile to mutually recursive kVM functions. A single
|
|
98
|
+
source relation may produce several kVM functions when called under different
|
|
99
|
+
input patterns.
|
|
100
|
+
|
|
101
|
+
Each kVM function records:
|
|
102
|
+
|
|
103
|
+
- relation hash;
|
|
104
|
+
- input pattern id;
|
|
105
|
+
- output pattern id;
|
|
106
|
+
- convergence status;
|
|
107
|
+
- layout assumptions;
|
|
108
|
+
- called relation instances;
|
|
109
|
+
- required intrinsics.
|
|
110
|
+
|
|
111
|
+
LLVM and Wasm backends should reject functions whose relation derivation is not
|
|
112
|
+
`converged`, unless they intentionally target the envelope-aware reference mode.
|
|
113
|
+
|
|
114
|
+
## Core Instructions
|
|
115
|
+
|
|
116
|
+
kVM should be register-based and block-oriented. Backends can lower it to LLVM
|
|
117
|
+
SSA, Wasm locals and blocks, C temporaries, or a JS interpreter.
|
|
118
|
+
|
|
119
|
+
Primitive instructions:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
id %v -> ok(%v)
|
|
123
|
+
fail -> fail
|
|
124
|
+
guard_pattern %v, @pattern -> ok(%v) | fail
|
|
125
|
+
guard_code %v, @code -> ok(%v) | fail
|
|
126
|
+
project_field %v, label_id, layout_hint -> ok(%child) | fail
|
|
127
|
+
project_variant %v, tag_id, layout_hint -> ok(%child) | fail
|
|
128
|
+
make_product [(label_id, %value), ...] -> %product
|
|
129
|
+
make_variant tag_id, %value -> %variant
|
|
130
|
+
call @function, %value -> ok(%result) | fail
|
|
131
|
+
call_intrinsic @symbol, %value -> ok(%result) | fail
|
|
132
|
+
return %value -> ok(%value)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Composition is ordinary control flow: run the next instruction only after the
|
|
136
|
+
previous one has returned `ok`.
|
|
137
|
+
|
|
138
|
+
Filters lower either to `guard_pattern` or disappear after retyping proves that
|
|
139
|
+
the guard is redundant. Type/code expressions lower to guards. Variant
|
|
140
|
+
introduction lowers to `make_variant`. Product construction lowers to a
|
|
141
|
+
product region plus `make_product`.
|
|
142
|
+
|
|
143
|
+
## Structured Regions
|
|
144
|
+
|
|
145
|
+
The two important high-level operations should survive lowering into kVM as
|
|
146
|
+
structured regions. They carry semantic information that is easy to lose if
|
|
147
|
+
everything is flattened too early.
|
|
148
|
+
|
|
149
|
+
### Product Region
|
|
150
|
+
|
|
151
|
+
A product expression applies several functions to the same input and succeeds
|
|
152
|
+
only if all of them succeed.
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
%p = product %input [
|
|
156
|
+
field a: { ... -> ok(%a) | fail }
|
|
157
|
+
field b: { ... -> ok(%b) | fail }
|
|
158
|
+
] join all_success
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Semantics:
|
|
162
|
+
|
|
163
|
+
1. Every field branch receives the same input `KRef`.
|
|
164
|
+
2. If every branch succeeds, the join constructs a product in canonical field
|
|
165
|
+
order.
|
|
166
|
+
3. If any branch fails, the whole product fails.
|
|
167
|
+
4. For terminating pure branches, branch evaluation order is not observable.
|
|
168
|
+
|
|
169
|
+
Scheduling:
|
|
170
|
+
|
|
171
|
+
- A sequential backend may run branches left to right.
|
|
172
|
+
- A parallel backend may fork all branches.
|
|
173
|
+
- A result-oriented runtime may fail fast and cancel unfinished branches after
|
|
174
|
+
any failure, because failure has no observable payload in release semantics.
|
|
175
|
+
- A strict operational runtime should preserve the chosen product evaluation
|
|
176
|
+
order for divergence-sensitive conformance. It may still run later branches
|
|
177
|
+
speculatively, but it should not expose a later failure while an earlier
|
|
178
|
+
branch is still pending.
|
|
179
|
+
- A debug runtime may optionally wait for all branches to report better
|
|
180
|
+
diagnostics.
|
|
181
|
+
|
|
182
|
+
This is the direct kVM form of parallel composition.
|
|
183
|
+
|
|
184
|
+
### Union Region
|
|
185
|
+
|
|
186
|
+
A union expression tries several functions and returns the first successful
|
|
187
|
+
branch in source order.
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
%u = union %input [
|
|
191
|
+
case 0: { ... -> ok(%r0) | fail }
|
|
192
|
+
case 1: { ... -> ok(%r1) | fail }
|
|
193
|
+
case 2: { ... -> ok(%r2) | fail }
|
|
194
|
+
] join first_success_by_index
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Semantics:
|
|
198
|
+
|
|
199
|
+
1. Every branch receives the same input `KRef`.
|
|
200
|
+
2. If no branch succeeds, the union fails.
|
|
201
|
+
3. If one or more branches succeed, the result is the successful branch with
|
|
202
|
+
the lowest index.
|
|
203
|
+
|
|
204
|
+
Scheduling:
|
|
205
|
+
|
|
206
|
+
- A sequential backend may run branches in source order and stop at the first
|
|
207
|
+
success.
|
|
208
|
+
- A parallel backend may speculatively run branches concurrently.
|
|
209
|
+
- A parallel backend may return branch `j` only after branch `j` has succeeded
|
|
210
|
+
and every branch `i < j` has failed.
|
|
211
|
+
- Once branch `j` is known to be selected, branches `i > j` may be cancelled.
|
|
212
|
+
- If any earlier branch is still pending, a later success remains provisional.
|
|
213
|
+
|
|
214
|
+
This gives concurrency without nondeterminism. The fastest branch does not win;
|
|
215
|
+
the lowest-index successful branch wins.
|
|
216
|
+
|
|
217
|
+
## Partiality And Cancellation
|
|
218
|
+
|
|
219
|
+
kVM failure is pure and unobservable except through product and union joins.
|
|
220
|
+
That gives simple cancellation laws:
|
|
221
|
+
|
|
222
|
+
- In a product, one failure is enough to fail the product.
|
|
223
|
+
- In a union, a later success is provisional until all earlier branches fail.
|
|
224
|
+
- Cancelling an unfinished pure branch cannot change the result.
|
|
225
|
+
- Effectful intrinsics are not cancellable unless they declare that property.
|
|
226
|
+
|
|
227
|
+
These laws are the bridge between mathematical `k` semantics and practical task
|
|
228
|
+
schedulers.
|
|
229
|
+
|
|
230
|
+
There is one important caveat: purity does not by itself erase divergence. If a
|
|
231
|
+
backend must preserve exact operational behavior in the presence of
|
|
232
|
+
nontermination, it should use the strict scheduling profile: sequential lowering
|
|
233
|
+
is always valid, and speculative parallel work may not commit a result or
|
|
234
|
+
failure that an earlier unresolved branch could have prevented. If the
|
|
235
|
+
contract is only result equivalence for terminating computations, product
|
|
236
|
+
fail-fast and broader cancellation are valid optimizations.
|
|
237
|
+
|
|
238
|
+
## Lowering From KIR-R
|
|
239
|
+
|
|
240
|
+
Suggested lowering rules:
|
|
241
|
+
|
|
242
|
+
| KIR operation | kVM lowering |
|
|
243
|
+
| --- | --- |
|
|
244
|
+
| `identity` | `id` or direct value forwarding |
|
|
245
|
+
| `empty` / `<>` | `fail` |
|
|
246
|
+
| `filter` | `guard_pattern` or erased if statically proven |
|
|
247
|
+
| `code` | `guard_code` or erased if statically proven |
|
|
248
|
+
| `dot` | `project_field` |
|
|
249
|
+
| `div` | `project_variant` |
|
|
250
|
+
| `vid` | `make_variant` |
|
|
251
|
+
| `ref` | `call` to a specialized relation instance or `call_intrinsic` |
|
|
252
|
+
| `comp` | success-checked sequence |
|
|
253
|
+
| `product` | `product` region plus `make_product` |
|
|
254
|
+
| `union` | `union` region with `first_success_by_index` join |
|
|
255
|
+
|
|
256
|
+
The lowerer should preserve labels and tags as table ids, not strings in hot
|
|
257
|
+
instructions. Debug metadata may retain source labels.
|
|
258
|
+
|
|
259
|
+
## Layout Tables
|
|
260
|
+
|
|
261
|
+
kVM should not hard-code one memory layout. It should refer to layout tables
|
|
262
|
+
generated from retyped patterns and canonical codes.
|
|
263
|
+
|
|
264
|
+
Useful tables:
|
|
265
|
+
|
|
266
|
+
- label table: label string -> label id;
|
|
267
|
+
- tag table: tag string -> tag id;
|
|
268
|
+
- pattern table: canonical pattern graph ids;
|
|
269
|
+
- layout table: product field offsets and union tag dispatch for each static
|
|
270
|
+
pattern/layout;
|
|
271
|
+
- intrinsic table: pure host functions and external types;
|
|
272
|
+
- relation instance table: `relation hash + input pattern hash -> function id`.
|
|
273
|
+
|
|
274
|
+
This keeps kVM stable while allowing experiments with serialized, lazy,
|
|
275
|
+
materialized, and external value representations.
|
|
276
|
+
|
|
277
|
+
## Backend Mapping
|
|
278
|
+
|
|
279
|
+
### LLVM
|
|
280
|
+
|
|
281
|
+
LLVM can lower each kVM function to a native function returning a `KResult`
|
|
282
|
+
struct. kVM registers map naturally to LLVM SSA values. Product and union
|
|
283
|
+
regions can lower first to ordinary blocks, then later to runtime task calls or
|
|
284
|
+
LLVM parallelism experiments.
|
|
285
|
+
|
|
286
|
+
Baseline product lowering:
|
|
287
|
+
|
|
288
|
+
```text
|
|
289
|
+
run branch 0
|
|
290
|
+
if fail return fail
|
|
291
|
+
run branch 1
|
|
292
|
+
if fail return fail
|
|
293
|
+
construct product
|
|
294
|
+
return ok
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Baseline union lowering:
|
|
298
|
+
|
|
299
|
+
```text
|
|
300
|
+
run branch 0
|
|
301
|
+
if ok return branch 0
|
|
302
|
+
run branch 1
|
|
303
|
+
if ok return branch 1
|
|
304
|
+
return fail
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Parallel lowering is an optimization, not a semantic requirement.
|
|
308
|
+
|
|
309
|
+
### WebAssembly
|
|
310
|
+
|
|
311
|
+
Wasm can use the same kVM control-flow shape with locals and blocks. The MVP
|
|
312
|
+
path should be sequential. Wasm threads, shared memory, or host promises can
|
|
313
|
+
later implement product and union regions without changing kVM semantics.
|
|
314
|
+
|
|
315
|
+
The key Wasm constraint is that the kVM instruction set should avoid relying on
|
|
316
|
+
arbitrary pointer arithmetic in the IR itself. Pointer/layout details should
|
|
317
|
+
live behind runtime imports or explicit memory-layout helpers.
|
|
318
|
+
|
|
319
|
+
### JS kVM Interpreter
|
|
320
|
+
|
|
321
|
+
A JS kVM interpreter is valuable as a conformance oracle. It can start with
|
|
322
|
+
sequential product and union execution, compare results against `run.mjs` and
|
|
323
|
+
`run_converged`, then add optional parallel scheduling later.
|
|
324
|
+
|
|
325
|
+
## Validation Rules
|
|
326
|
+
|
|
327
|
+
A valid kVM function should satisfy:
|
|
328
|
+
|
|
329
|
+
1. Every function has one `KRef` input and returns `KResult<KRef>`.
|
|
330
|
+
2. Every register is assigned once.
|
|
331
|
+
3. Every failure path is explicit.
|
|
332
|
+
4. Product field labels are unique and canonical.
|
|
333
|
+
5. Union branch order is preserved.
|
|
334
|
+
6. Calls target concrete relation instances, not unspecialized source names.
|
|
335
|
+
7. Layout hints match the input pattern expected by the instruction.
|
|
336
|
+
8. Envelope-free functions are allowed only when every reachable relation
|
|
337
|
+
instance has converged type derivation.
|
|
338
|
+
9. Parallel scheduling is allowed only through pure/cancellable regions.
|
|
339
|
+
|
|
340
|
+
## Example
|
|
341
|
+
|
|
342
|
+
For a source shape like:
|
|
343
|
+
|
|
344
|
+
```k
|
|
345
|
+
{ .x a, .y b }
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
kVM should keep the parallel product structure:
|
|
349
|
+
|
|
350
|
+
```text
|
|
351
|
+
fn @example(%in):
|
|
352
|
+
%out = product %in [
|
|
353
|
+
field a: {
|
|
354
|
+
%x = project_field %in, label:x
|
|
355
|
+
return %x
|
|
356
|
+
}
|
|
357
|
+
field b: {
|
|
358
|
+
%y = project_field %in, label:y
|
|
359
|
+
return %y
|
|
360
|
+
}
|
|
361
|
+
] join all_success
|
|
362
|
+
return %out
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
For:
|
|
366
|
+
|
|
367
|
+
```k
|
|
368
|
+
< f, g, h >
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
kVM should keep the deterministic union structure:
|
|
372
|
+
|
|
373
|
+
```text
|
|
374
|
+
fn @choice(%in):
|
|
375
|
+
%out = union %in [
|
|
376
|
+
case 0: { %r0 = call @f__P, %in; return %r0 }
|
|
377
|
+
case 1: { %r1 = call @g__P, %in; return %r1 }
|
|
378
|
+
case 2: { %r2 = call @h__P, %in; return %r2 }
|
|
379
|
+
] join first_success_by_index
|
|
380
|
+
return %out
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
The runtime may evaluate `f`, `g`, and `h` concurrently, but it may return `g`
|
|
384
|
+
only after `f` has failed.
|
|
385
|
+
|
|
386
|
+
## Open Questions
|
|
387
|
+
|
|
388
|
+
- Should kVM be serialized as JSON first, or as a compact binary section inside
|
|
389
|
+
`.ko` only after the schema stabilizes?
|
|
390
|
+
- Should product fail-fast be the only release behavior, or should there be a
|
|
391
|
+
standard diagnostic mode that collects all failed fields?
|
|
392
|
+
- How should effectful debug intrinsics be represented so they cannot silently
|
|
393
|
+
enter parallel backend execution?
|
|
394
|
+
- Is `guard_code` needed in the final envelope-free backend path, or should all
|
|
395
|
+
code/type checks be resolved into layout-specific projections and guards?
|
|
396
|
+
- Should kVM expose a generic `match` instruction for union dispatch, or are
|
|
397
|
+
`project_variant` plus union regions enough?
|
|
398
|
+
|
|
399
|
+
## Implementation Order
|
|
400
|
+
|
|
401
|
+
1. Keep KIR-P as the current object-level relation format.
|
|
402
|
+
2. Define a JSON kVM schema for specialized relation instances.
|
|
403
|
+
3. Lower current relation ops to kVM in envelope-aware mode.
|
|
404
|
+
4. Add a sequential JS kVM interpreter and compare it against `run.mjs`.
|
|
405
|
+
5. Lower retyped/converged relation instances to envelope-free kVM.
|
|
406
|
+
6. Add kVM validation and conformance fixtures.
|
|
407
|
+
7. Add a minimal C or Wasm backend for sequential kVM.
|
|
408
|
+
8. Add LLVM lowering.
|
|
409
|
+
9. Add optional runtime scheduling for product and union regions.
|
|
410
|
+
|
|
411
|
+
The important first milestone is not parallel speed. It is a stable execution
|
|
412
|
+
contract that makes sequential LLVM and Wasm generation boring, while preserving
|
|
413
|
+
the parallel structure that `k` gets from purity.
|
|
@@ -305,3 +305,9 @@ shape is the same object payload shape with `main: null`:
|
|
|
305
305
|
When a library is compiled with `--lib`, the output is the merged library
|
|
306
306
|
closure. Imported codes, relations, aliases, and metadata are preserved, and the
|
|
307
307
|
new source adds its own origins.
|
|
308
|
+
|
|
309
|
+
The REPL `:klib` command uses active relation aliases as roots. It stores their
|
|
310
|
+
transitive relation closure and omits historical content-addressed relations
|
|
311
|
+
that remain in the live session after alias rebinding but are no longer
|
|
312
|
+
reachable from an active alias. Its `codes` field remains the registered code
|
|
313
|
+
snapshot needed to reload the library.
|
package/DOCS/REPL.md
CHANGED
|
@@ -11,9 +11,9 @@ The interpreter keeps a live `.klib`-style state in memory:
|
|
|
11
11
|
- metadata origins used to recover aliases
|
|
12
12
|
- the current value flowing through the session
|
|
13
13
|
|
|
14
|
-
Raw k snippets compile on top of that state. You can also export the
|
|
15
|
-
|
|
16
|
-
expression in the session context.
|
|
14
|
+
Raw k snippets compile on top of that state. You can also export the active
|
|
15
|
+
library closure as a `.klib` file or compile an executable `.ko` object from
|
|
16
|
+
an expression in the session context.
|
|
17
17
|
|
|
18
18
|
## Prompt Model
|
|
19
19
|
|
|
@@ -49,7 +49,7 @@ complete.
|
|
|
49
49
|
| `:codec list` | List loaded REPL codecs |
|
|
50
50
|
| `:input type [codec]` | Read the next line as codec input for a singleton type |
|
|
51
51
|
| `:load [--no-alias] file` | Load `.k` source or `.klib` into the current state |
|
|
52
|
-
| `:klib file` | Export
|
|
52
|
+
| `:klib file` | Export the active relation closure as a `.klib` library |
|
|
53
53
|
| `:ko file expr` | Export a `.ko` executable with `expr` as main |
|
|
54
54
|
| `:val` | Print current value and JSON form |
|
|
55
55
|
| `:reset` | Reset interpreter state |
|
|
@@ -62,7 +62,7 @@ Raw input is compiled as k source on top of the current state.
|
|
|
62
62
|
Examples:
|
|
63
63
|
|
|
64
64
|
```k
|
|
65
|
-
> {} |
|
|
65
|
+
> {} |ok
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
```k
|
|
@@ -107,6 +107,8 @@ The interpreter keeps:
|
|
|
107
107
|
|
|
108
108
|
Definitions are content-addressed. Rebinding an alias changes the name-to-hash
|
|
109
109
|
mapping, but older canonical definitions remain available by hash.
|
|
110
|
+
They stay available in the live session, but `:klib` omits historical
|
|
111
|
+
relations that are no longer reachable from an active relation alias.
|
|
110
112
|
|
|
111
113
|
## Alias Resolution
|
|
112
114
|
|
|
@@ -184,8 +186,11 @@ against that code before becoming the current value.
|
|
|
184
186
|
|
|
185
187
|
### `:klib file`
|
|
186
188
|
|
|
187
|
-
Writes
|
|
188
|
-
|
|
189
|
+
Writes a plain-JSON `.klib` library rooted at the current relation aliases.
|
|
190
|
+
Relations referenced by those aliases are included transitively. Historical
|
|
191
|
+
relations retained in the live session are omitted when no active alias
|
|
192
|
+
depends on them. The registered code snapshot is still included. The library
|
|
193
|
+
has `main: null`; it has no binary header and no object payload version.
|
|
189
194
|
|
|
190
195
|
### `:ko file expr`
|
|
191
196
|
|
|
@@ -197,7 +202,7 @@ writes the resulting executable `.ko` object.
|
|
|
197
202
|
Evaluated values print in k syntax together with the inferred envelope:
|
|
198
203
|
|
|
199
204
|
```text
|
|
200
|
-
{
|
|
205
|
+
{}|0|+1 ?<<{} 0, ...> +1, ...>
|
|
201
206
|
```
|
|
202
207
|
|
|
203
208
|
`undefined` prints as:
|
|
@@ -212,16 +217,16 @@ Evaluated values print in k syntax together with the inferred envelope:
|
|
|
212
217
|
## Example Session
|
|
213
218
|
|
|
214
219
|
```text
|
|
215
|
-
> :type nat = <{}
|
|
220
|
+
> :type nat = <{} 0, nat +1>
|
|
216
221
|
$ nat = @...
|
|
217
|
-
> :rel
|
|
218
|
-
|
|
219
|
-
> {} |
|
|
220
|
-
{
|
|
221
|
-
> :t
|
|
222
|
-
|
|
222
|
+
> :rel inc = |+1
|
|
223
|
+
inc = @...
|
|
224
|
+
> {} |0
|
|
225
|
+
{}|0 ?<{} 0, ...>
|
|
226
|
+
> :t inc
|
|
227
|
+
inc : ?X0 --> ?<X0 +1, ...> (@...)
|
|
223
228
|
> :klib nat.klib
|
|
224
229
|
saved nat.klib
|
|
225
|
-
> :ko
|
|
226
|
-
saved
|
|
230
|
+
> :ko inc.ko inc
|
|
231
|
+
saved inc.ko (inc)
|
|
227
232
|
```
|