@fraczak/k 6.10.1 → 6.10.3
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 +39 -0
- package/DOCS/BIG_PICTURE.md +174 -100
- package/DOCS/CODECS.md +74 -29
- package/DOCS/CODEC_ARCHITECTURE.md +87 -31
- package/DOCS/CONVERGENCE.md +42 -11
- package/DOCS/DICTIONARY.md +69 -2
- package/DOCS/FILE_FORMATS.md +385 -0
- package/DOCS/KIR_V1.md +53 -42
- package/DOCS/KVM_EXECUTION_MODEL.md +189 -147
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +35 -17
- package/DOCS/PATTERNS.md +10 -6
- package/DOCS/REPL.md +100 -60
- package/DOCS/TEXTUAL_VALUES.md +24 -19
- package/DOCS/TYPE_DERIVATION.md +68 -22
- package/README.md +92 -58
- package/codecs/README.md +78 -67
- package/codecs/runtime/show-value.mjs +68 -16
- package/objects/README.md +57 -37
- package/package.json +1 -1
- package/tests/README.md +28 -17
- package/tests/test-repl-html.mjs +19 -0
|
@@ -2,13 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
## 1. Overview & Objectives
|
|
4
4
|
|
|
5
|
-
In **k**, a **codec** is a two-way translator between external domain
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
In **k**, a **codec** is a two-way translator between external domain
|
|
6
|
+
data (e.g. decimal integers, JSON, UTF-8 text, IEEE 754 floats) and **k**
|
|
7
|
+
enveloped values (a structural `Value` tree paired with a closed pattern
|
|
8
|
+
graph).
|
|
9
|
+
|
|
10
|
+
In **k**, there are no primitive numbers or built-in numerical types.
|
|
11
|
+
Numbers are nullary relations mapping the unit to bit trees
|
|
12
|
+
(`${} -> $bits`), and arithmetic relations operate on signed
|
|
13
|
+
integer variants (`$int`). Codecs like `int.mjs` bridge human
|
|
14
|
+
decimal representations and these algebraic structures.
|
|
15
|
+
|
|
16
|
+
Every codec in the **k** ecosystem is designed to serve three unified
|
|
17
|
+
objectives from a single module definition:
|
|
18
|
+
|
|
19
|
+
1. **Document the Codec**: Formally specify the external syntax and its
|
|
20
|
+
semantics as an enveloped **k** value `(P, v)`.
|
|
21
|
+
2. **REPL Module**: Provide interactive input parsing (`:input
|
|
22
|
+
<codec.mjs>`) and multi-codec output inspection (`<codec.mjs>:
|
|
23
|
+
<formatted>`) in both Node.js and browser REPLs.
|
|
24
|
+
3. **Standalone Shell Executable**: Function as a first-class Unix filter
|
|
25
|
+
(`--parse`, `--print`, `--help`) for composition in command-line
|
|
26
|
+
pipelines.
|
|
12
27
|
|
|
13
28
|
```text
|
|
14
29
|
+---------------------------------------+
|
|
@@ -36,38 +51,55 @@ Every codec in the **k** ecosystem is designed to serve three unified objectives
|
|
|
36
51
|
|
|
37
52
|
## 2. Objective 1: Documentation & Specification
|
|
38
53
|
|
|
39
|
-
Every codec defines what external text it accepts and how that text
|
|
54
|
+
Every codec defines what external text it accepts and how that text
|
|
55
|
+
maps to an enveloped **k** value.
|
|
40
56
|
|
|
41
57
|
### 2.1 External Syntax
|
|
42
|
-
The syntax specification defines the valid textual forms accepted by
|
|
43
|
-
|
|
58
|
+
The syntax specification defines the valid textual forms accepted by
|
|
59
|
+
the codec:
|
|
60
|
+
- **Grammar & Rules**: Defines the accepted language. While regular
|
|
61
|
+
expressions offer simple examples, the syntax can be an arbitrary
|
|
62
|
+
formal language (context-free, recursive, JSON RFC 8259, etc.).
|
|
44
63
|
- **Normalization**: Rules for whitespace, casing, or escaping.
|
|
45
|
-
- **Rejection Criteria**: Explicit errors when invalid input is
|
|
64
|
+
- **Rejection Criteria**: Explicit errors when invalid input is
|
|
65
|
+
encountered.
|
|
46
66
|
|
|
47
67
|
### 2.2 Semantics as an Enveloped k Value
|
|
48
68
|
Parsing external text produces an **enveloped value** `(P, v)`:
|
|
49
|
-
- **Pattern Graph ($P$)**: A closed pattern graph specifying the
|
|
50
|
-
|
|
69
|
+
- **Pattern Graph ($P$)**: A closed pattern graph specifying the
|
|
70
|
+
algebraic structure.
|
|
71
|
+
- **Value Tree ($v$)**: A concrete tree matching $P$, constructed from
|
|
72
|
+
products (`{...}`) and variants (`<...>`).
|
|
51
73
|
|
|
52
|
-
A codec does not produce an ungrounded type; it performs a concrete
|
|
74
|
+
A codec does not produce an ungrounded type; it performs a concrete
|
|
75
|
+
transformation from text to an enveloped value `(P, v)`.
|
|
53
76
|
|
|
54
77
|
### 2.3 Pattern Derivation via k Type System (`patternFromFilter`)
|
|
55
|
-
Pattern graphs ($P$) must never be handwritten as raw property-list
|
|
78
|
+
Pattern graphs ($P$) must never be handwritten as raw property-list
|
|
79
|
+
JSON arrays (e.g. `[["closed-union", ...]]`). Instead, codecs derive
|
|
80
|
+
pattern graphs directly through the **k** type system from filter or
|
|
81
|
+
type expressions using `patternFromFilter`:
|
|
56
82
|
|
|
57
83
|
```js
|
|
58
84
|
import { patternFromFilter } from "./runtime/codec-sdk.mjs";
|
|
59
85
|
|
|
60
86
|
// Derived from k filter expression
|
|
61
|
-
const INT_PATTERN = patternFromFilter(
|
|
87
|
+
const INT_PATTERN = patternFromFilter(
|
|
88
|
+
'?< <bits 0, bits 1, {} _>=bits "+", bits "-">'
|
|
89
|
+
);
|
|
62
90
|
```
|
|
63
91
|
|
|
64
92
|
This guarantees:
|
|
65
|
-
1. All patterns are verified, normalized, and canonicalized by **k**'s
|
|
93
|
+
1. All patterns are verified, normalized, and canonicalized by **k**'s
|
|
94
|
+
type derivation and graph unification engine.
|
|
66
95
|
2. Codecs remain concise, declarative, and maintainable.
|
|
67
|
-
3. Codecs run identically in Node.js and in the Web REPL (via the browser
|
|
96
|
+
3. Codecs run identically in Node.js and in the Web REPL (via the browser
|
|
97
|
+
runtime shim).
|
|
68
98
|
|
|
69
99
|
### 2.4 Documentation Contract
|
|
70
|
-
A codec is identified solely by the file loaded—there is no artificial
|
|
100
|
+
A codec is identified solely by the file loaded—there is no artificial
|
|
101
|
+
`name` export or `patterns` list export. A codec may optionally export
|
|
102
|
+
a `doc` string:
|
|
71
103
|
- Describes accepted syntax, options, and representation.
|
|
72
104
|
- Displayed by `--help` in shell invocations.
|
|
73
105
|
- Displayed by `:help <codec.mjs>` or documentation commands in REPLs.
|
|
@@ -110,8 +142,10 @@ The user specifies the codec to parse an input payload:
|
|
|
110
142
|
Whenever an evaluation produces a resulting **k** `Value`:
|
|
111
143
|
1. The primary representation is the standard **k** value envelope.
|
|
112
144
|
2. The REPL iterates over loaded codecs and calls `codec.print(value)`.
|
|
113
|
-
3. If `codec.print(value)` succeeds, the REPL displays
|
|
114
|
-
|
|
145
|
+
3. If `codec.print(value)` succeeds, the REPL displays
|
|
146
|
+
`<codec>: <formattedString>`.
|
|
147
|
+
4. If `codec.print(value)` throws, the codec is silently ignored for
|
|
148
|
+
that value.
|
|
115
149
|
|
|
116
150
|
---
|
|
117
151
|
|
|
@@ -135,7 +169,8 @@ chmod +x codecs/int.mjs
|
|
|
135
169
|
- Reads binary wire bytes `(P, v)` from `stdin`.
|
|
136
170
|
- Decodes the wire stream and calls `print(value)`.
|
|
137
171
|
- Writes formatted text to `stdout`.
|
|
138
|
-
- Exit code: `0` on success, non-zero if not representable under this
|
|
172
|
+
- Exit code: `0` on success, non-zero if not representable under this
|
|
173
|
+
codec.
|
|
139
174
|
|
|
140
175
|
3. **Help Mode (`-h`, `--help`)**:
|
|
141
176
|
- Outputs CLI usage and the codec's `doc` string to `stdout`.
|
|
@@ -144,18 +179,24 @@ chmod +x codecs/int.mjs
|
|
|
144
179
|
|
|
145
180
|
## 5. Implementation: Codec CLI Runner
|
|
146
181
|
|
|
147
|
-
To avoid duplicating stdin/stdout stream handling and CLI flag parsing
|
|
182
|
+
To avoid duplicating stdin/stdout stream handling and CLI flag parsing
|
|
183
|
+
across codecs, a helper is provided:
|
|
148
184
|
|
|
149
185
|
```javascript
|
|
150
186
|
runCodecCLI(import.meta.url, { parse, print, doc });
|
|
151
187
|
```
|
|
152
188
|
|
|
153
189
|
### Responsibilities of `runCodecCLI`:
|
|
154
|
-
1. **Entrypoint Detection**: Checks if the module is invoked directly
|
|
190
|
+
1. **Entrypoint Detection**: Checks if the module is invoked directly
|
|
191
|
+
from the CLI (e.g. `import.meta.url ===
|
|
192
|
+
pathToFileURL(process.argv[1]).href`). If imported as a module or
|
|
193
|
+
running in a browser, it is a no-op.
|
|
155
194
|
2. **Flag Parsing**: Handles `--parse`, `--print`, and `-h` / `--help`.
|
|
156
195
|
3. **Stream Piping**:
|
|
157
|
-
- For `--parse`: reads `stdin` to string, calls `parse(text)`, encodes
|
|
158
|
-
|
|
196
|
+
- For `--parse`: reads `stdin` to string, calls `parse(text)`, encodes
|
|
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`.
|
|
159
200
|
|
|
160
201
|
---
|
|
161
202
|
|
|
@@ -181,14 +222,29 @@ codecs/
|
|
|
181
222
|
└── cli-entry.mjs # Entrypoint detection
|
|
182
223
|
```
|
|
183
224
|
|
|
184
|
-
Each codec file directly under `codecs/` is both an executable CLI
|
|
225
|
+
Each codec file directly under `codecs/` is both an executable CLI
|
|
226
|
+
script and an importable module.
|
|
185
227
|
|
|
186
228
|
---
|
|
187
229
|
|
|
188
230
|
## 7. Web REPL & VFS Bundling Architecture
|
|
189
231
|
|
|
190
232
|
In the browser REPL (`repl.html`):
|
|
191
|
-
- **Self-Contained Modules**: At build time
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
233
|
+
- **Self-Contained Modules**: At build time
|
|
234
|
+
(`scripts/build-repl-html.mjs`), verified codecs in `codecs/` are
|
|
235
|
+
compiled via `esbuild` into 100% self-contained ES modules with **zero
|
|
236
|
+
imports**.
|
|
237
|
+
- **No Runtime Files in VFS**: `codecs/runtime/*` is not included in the
|
|
238
|
+
browser VFS. The VFS only contains verified, self-contained user-facing
|
|
239
|
+
files (`int.mjs`, `json.mjs`, `utf8.mjs`, `unit.mjs`, `ieee.mjs`).
|
|
240
|
+
- **Native Browser Loading**: In `repl-codecs.mjs`, the browser reads the
|
|
241
|
+
codec source from VFS, wraps it in a Blob, and invokes native `await
|
|
242
|
+
import(blobUrl)`. No regex manipulation, import stripping, or global
|
|
243
|
+
environment injection is required.
|
|
244
|
+
|
|
245
|
+
## Further Reading
|
|
246
|
+
|
|
247
|
+
- [DOCS/FILE_FORMATS.md](./FILE_FORMATS.md) — guide to
|
|
248
|
+
.k, .ko, .klib, and .kvm formats
|
|
249
|
+
- [DOCS/CODECS.md](./CODECS.md) — guide to writing codecs
|
|
250
|
+
- [DOCS/DICTIONARY.md](./DICTIONARY.md) — concept names and terminology
|
package/DOCS/CONVERGENCE.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Convergence Strategies
|
|
2
2
|
|
|
3
|
-
This note describes the current structure of the JavaScript
|
|
3
|
+
This note describes the current structure of the JavaScript
|
|
4
|
+
type-derivation engine and the places intended for experimentation.
|
|
4
5
|
|
|
5
6
|
## Current default
|
|
6
7
|
|
|
@@ -12,9 +13,11 @@ Type derivation operates on the SCC DAG of relation dependencies.
|
|
|
12
13
|
- compact once
|
|
13
14
|
- Recursive SCC:
|
|
14
15
|
- use `fixed_point`
|
|
15
|
-
- iterate until signatures stabilize or the iteration budget is
|
|
16
|
+
- iterate until signatures stabilize or the iteration budget is
|
|
17
|
+
exhausted
|
|
16
18
|
|
|
17
|
-
This split keeps acyclic modules fast while preserving the old
|
|
19
|
+
This split keeps acyclic modules fast while preserving the old
|
|
20
|
+
behavior for recursive polymorphic definitions.
|
|
18
21
|
|
|
19
22
|
## Public tuning hook
|
|
20
23
|
|
|
@@ -51,22 +54,37 @@ This is the supported inspection surface for convergence experiments.
|
|
|
51
54
|
|
|
52
55
|
## Why the current fast path works
|
|
53
56
|
|
|
54
|
-
For an acyclic singleton SCC, every callee has already been fully
|
|
57
|
+
For an acyclic singleton SCC, every callee has already been fully
|
|
58
|
+
derived by the time the current relation is processed. There is no
|
|
59
|
+
need for repeated fixed-point propagation because:
|
|
55
60
|
|
|
56
61
|
1. Callee boundary patterns are stable.
|
|
57
62
|
2. The current relation only needs those stable input/output boundaries.
|
|
58
63
|
3. One propagation pass plus one compaction is sufficient.
|
|
59
64
|
|
|
60
|
-
`Examples/ieee.k` is exactly this shape: a large acyclic dependency
|
|
65
|
+
`Examples/ieee.k` is exactly this shape: a large acyclic dependency
|
|
66
|
+
graph. The major speedup comes from avoiding unnecessary fixed-point
|
|
67
|
+
iteration there.
|
|
61
68
|
|
|
62
69
|
## Current implementation choices
|
|
63
70
|
|
|
64
71
|
Two implementation changes matter for performance:
|
|
65
72
|
|
|
66
|
-
1. Compaction now starts from the quotient graph of live
|
|
67
|
-
|
|
73
|
+
1. Compaction now starts from the quotient graph of live
|
|
74
|
+
representatives instead of cloning the full historical union-find
|
|
75
|
+
forest.
|
|
76
|
+
2. Singleton-pattern registration is incremental and no longer
|
|
77
|
+
re-finalizes the entire global code repository on every compaction.
|
|
68
78
|
|
|
69
|
-
These two changes are what make `Examples/ieee.k` practical to
|
|
79
|
+
These two changes are what make `Examples/ieee.k` practical to
|
|
80
|
+
type-check.
|
|
81
|
+
|
|
82
|
+
## Role in Ahead-Of-Time (AOT) Compilation
|
|
83
|
+
|
|
84
|
+
Convergence strategies dictate the time spent during Ahead-Of-Time
|
|
85
|
+
(AOT) type checking. Because compilation resolves and converges these
|
|
86
|
+
dependency SCCs beforehand into `.ko`, `.klib`, and `.kvm` artifacts,
|
|
87
|
+
runtime execution does not incur any convergence overhead.
|
|
70
88
|
|
|
71
89
|
## Where to experiment next
|
|
72
90
|
|
|
@@ -86,7 +104,20 @@ If you want to continue convergence work, these are the main seams:
|
|
|
86
104
|
|
|
87
105
|
Promising next experiments:
|
|
88
106
|
|
|
89
|
-
- Replace signature-string stabilization in `fixed_point` with
|
|
107
|
+
- Replace signature-string stabilization in `fixed_point` with
|
|
108
|
+
structural change tracking.
|
|
90
109
|
- Add divergence heuristics for recursive polymorphic SCCs.
|
|
91
|
-
- Cache cloned callee boundary graphs for repeated call sites within
|
|
92
|
-
|
|
110
|
+
- Cache cloned callee boundary graphs for repeated call sites within
|
|
111
|
+
one relation.
|
|
112
|
+
- Compare the current partition refinement in `compression.mjs` with
|
|
113
|
+
a hash-consed canonical-form approach.
|
|
114
|
+
|
|
115
|
+
## Further Reading
|
|
116
|
+
|
|
117
|
+
- [DOCS/FILE_FORMATS.md](./FILE_FORMATS.md) — guide to
|
|
118
|
+
.k, .ko, .klib, and .kvm formats
|
|
119
|
+
- [DOCS/TYPE_DERIVATION.md](./TYPE_DERIVATION.md) — type derivation
|
|
120
|
+
algorithm and rules
|
|
121
|
+
- [DOCS/OBJECT_FILE_AND_PATTERN.md](./OBJECT_FILE_AND_PATTERN.md) —
|
|
122
|
+
object format and pattern encoding
|
|
123
|
+
- [DOCS/DICTIONARY.md](./DICTIONARY.md) — concept names and terminology
|
package/DOCS/DICTIONARY.md
CHANGED
|
@@ -69,6 +69,34 @@ pattern and otherwise behaves like identity.
|
|
|
69
69
|
Source syntax may present this operation as a filter expression. The semantic
|
|
70
70
|
operation is a pattern guard.
|
|
71
71
|
|
|
72
|
+
### Canonical Content-Addressed Hash (`@hash`)
|
|
73
|
+
|
|
74
|
+
A `canonical content-addressed hash` is the immutable, unique identifier
|
|
75
|
+
derived from the normalized AST of a relation or the minimal deterministic
|
|
76
|
+
tree automaton of a type.
|
|
77
|
+
|
|
78
|
+
In `k`, there is no global symbol namespace. Every compiled relation and
|
|
79
|
+
type code is identified globally and uniquely by its `@hash`.
|
|
80
|
+
|
|
81
|
+
### Local Alias
|
|
82
|
+
|
|
83
|
+
A `local alias` is a human-readable identifier (such as `plus`, `int`,
|
|
84
|
+
or `5`) mapped to a canonical hash in object metadata (`relAlias`,
|
|
85
|
+
`typeAliases`).
|
|
86
|
+
|
|
87
|
+
Aliases are local to their compilation scope. When loading libraries
|
|
88
|
+
with `--lib`, canonical definitions are available by their `@hash`, but
|
|
89
|
+
local aliases are not automatically exported into the consumer's scope
|
|
90
|
+
unless explicitly mapped with `--export`.
|
|
91
|
+
|
|
92
|
+
### Relations as Values (No Built-in Numbers)
|
|
93
|
+
|
|
94
|
+
In `k`, there are no primitive numerical types or built-in integer
|
|
95
|
+
literals. Numerical identifiers such as `5` or `10` are nullary
|
|
96
|
+
relations (constants) mapping the unit `${}` to bit trees of type
|
|
97
|
+
`${} -> $bits`. Operations on signed integers (`$int`) require
|
|
98
|
+
converting bit trees via the `int` constructor (`5 int`).
|
|
99
|
+
|
|
72
100
|
## Values, Types, And Patterns
|
|
73
101
|
|
|
74
102
|
### Value Tree
|
|
@@ -235,6 +263,16 @@ The key product is still a k-shaped core expression graph, now annotated by
|
|
|
235
263
|
type-pattern facts. This stage is a semantic artifact; it does not imply a
|
|
236
264
|
particular serialized format.
|
|
237
265
|
|
|
266
|
+
### Ahead-Of-Time (AOT) Type Checking
|
|
267
|
+
|
|
268
|
+
`Ahead-of-time (AOT) type checking` refers to the compilation phase
|
|
269
|
+
where parsing, relation expansion, structural type derivation, and
|
|
270
|
+
fixed-point constraint convergence are solved in advance.
|
|
271
|
+
|
|
272
|
+
The resulting compiled artifacts (`.ko`, `.klib`, `.kvm`) store fully
|
|
273
|
+
derived principal type graphs and interned type codes, allowing downstream
|
|
274
|
+
execution or linking to skip cold-start type derivation entirely.
|
|
275
|
+
|
|
238
276
|
### k Object
|
|
239
277
|
|
|
240
278
|
A `k object` is a compiled semantic object.
|
|
@@ -242,8 +280,37 @@ A `k object` is a compiled semantic object.
|
|
|
242
280
|
It stores canonical type codes, partial functions, aliases, metadata,
|
|
243
281
|
type-pattern graphs, and type-derivation status.
|
|
244
282
|
|
|
245
|
-
An executable object has
|
|
246
|
-
|
|
283
|
+
An executable object (`.ko`) has an execution entrypoint (`main:
|
|
284
|
+
"__main__"`). A library object (`.klib`) contains reusable definitions
|
|
285
|
+
but no selected main relation (`main: null`).
|
|
286
|
+
|
|
287
|
+
### File Formats in the K Universe
|
|
288
|
+
|
|
289
|
+
The `k` toolchain defines four primary file formats (for comprehensive
|
|
290
|
+
details and workflows, see [`DOCS/FILE_FORMATS.md`](FILE_FORMATS.md)):
|
|
291
|
+
|
|
292
|
+
- **Source File (`.k`):** Plain UTF-8 source text defining algebraic data
|
|
293
|
+
shapes, partial functions, and expressions.
|
|
294
|
+
- **Executable Object (`.ko`):** AOT type-checked executable artifact
|
|
295
|
+
with binary header `KOBJ\n` and JSON payload containing `codes`, `rels`,
|
|
296
|
+
and entrypoint `main: "__main__"`. Executable directly via `k.mjs`,
|
|
297
|
+
WebAssembly, or LLVM.
|
|
298
|
+
- **Library Object (`.klib`):** AOT type-checked library container stored
|
|
299
|
+
as plain UTF-8 JSON without an entrypoint (`main: null`). Provides
|
|
300
|
+
reusable pre-converged relations and type graphs for downstream linking.
|
|
301
|
+
- **Polymorphic kVM Template (`.kvm`):** Register-IR bytecode template
|
|
302
|
+
(`format: "k-vm"`, `layer: "KVM-P"`) carrying principal pattern graphs.
|
|
303
|
+
Specialized on-the-fly at runtime (`specializeKVM`) against concrete
|
|
304
|
+
input envelopes $(v, P_v)$ without re-running type inference.
|
|
305
|
+
|
|
306
|
+
### Stream Transformer vs. Closed Constant Relation
|
|
307
|
+
|
|
308
|
+
- A **stream transformer** is a relation with an open domain (e.g. `{() x,
|
|
309
|
+
5 int y} plus`) that consumes external data arriving from a binary
|
|
310
|
+
stream or standard input.
|
|
311
|
+
- A **closed constant relation** is a relation with no free inputs (such
|
|
312
|
+
as `{10 int x, 5 int y} plus`). Its domain is the unit type `${}`,
|
|
313
|
+
requiring an empty unit `{}` when executed as a standalone script.
|
|
247
314
|
|
|
248
315
|
### KIR-P
|
|
249
316
|
|