@fraczak/k 6.10.2 → 6.10.4

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 (45) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/DOCS/BIG_PICTURE.md +174 -100
  3. package/DOCS/CODECS.md +74 -29
  4. package/DOCS/CODEC_ARCHITECTURE.md +87 -31
  5. package/DOCS/CONVERGENCE.md +42 -11
  6. package/DOCS/DICTIONARY.md +69 -2
  7. package/DOCS/FILE_FORMATS.md +420 -0
  8. package/DOCS/KIR_V1.md +53 -42
  9. package/DOCS/KVM_EXECUTION_MODEL.md +189 -147
  10. package/DOCS/OBJECT_FILE_AND_PATTERN.md +35 -17
  11. package/DOCS/PATTERNS.md +10 -6
  12. package/DOCS/REPL.md +100 -60
  13. package/DOCS/TEXTUAL_VALUES.md +24 -19
  14. package/DOCS/TYPE_DERIVATION.md +68 -22
  15. package/Examples/karatsuba-mult.k +215 -0
  16. package/README.md +92 -58
  17. package/backends/arm64/scripts/run-tests.mjs +16 -0
  18. package/backends/llvm/bin/k-llvm-build.mjs +40 -14
  19. package/backends/llvm/bin/k-llvm-compile.mjs +29 -12
  20. package/backends/llvm/runtime/krt.c +10 -10
  21. package/backends/llvm/runtime/krt.h +6 -1
  22. package/backends/llvm/scripts/run-tests.mjs +16 -0
  23. package/backends/llvm/src/cli.mjs +1 -1
  24. package/backends/llvm/src/executable.mjs +36 -0
  25. package/backends/llvm/src/kvm2llvm.mjs +10 -4
  26. package/backends/llvm/tests/integration.sh +11 -0
  27. package/backends/llvm/tests/test-llvm.mjs +15 -1
  28. package/backends/wasm/scripts/run-tests.mjs +16 -0
  29. package/browser/vfs-data.mjs +1 -1
  30. package/codecs/README.md +78 -67
  31. package/core.k +5 -5
  32. package/objects/README.md +57 -37
  33. package/package.json +2 -1
  34. package/scripts/benchmark-idempotency.mjs +27 -0
  35. package/scripts/benchmark.mjs +51 -0
  36. package/scripts/build-repl-html.mjs +17 -0
  37. package/scripts/generate-dependency-graph.mjs +25 -1
  38. package/scripts/perf-ieee.mjs +75 -0
  39. package/scripts/perf-int.mjs +67 -0
  40. package/scripts/perf-multiplication.mjs +644 -0
  41. package/scripts/perf-poly.mjs +67 -0
  42. package/scripts/render-benchmark.mjs +25 -0
  43. package/scripts/run-tests.mjs +19 -0
  44. package/tests/README.md +28 -17
  45. package/tests/test-karatsuba.mjs +133 -0
package/DOCS/REPL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # k Interpreter
2
2
 
3
- `repl.mjs` is the interactive k interpreter. After linking or installing the
4
- package, start it with `k-repl`.
3
+ `repl.mjs` is the interactive k interpreter. After linking or installing
4
+ the package, start it with `k-repl`.
5
5
 
6
6
  The interpreter keeps a live `.klib`-style state in memory:
7
7
 
@@ -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 active
15
- library closure as a `.klib` file or compile an executable `.ko` object from
16
- an expression in the session context.
14
+ Raw k snippets compile on top of that state. You can also export the
15
+ active library closure as a `.klib` file or compile an executable `.ko`
16
+ object from an expression in the session context.
17
17
 
18
18
  ## Prompt Model
19
19
 
@@ -22,11 +22,11 @@ There are two kinds of input:
22
22
  - commands, starting with `:`
23
23
  - raw k source
24
24
 
25
- Commands execute immediately, but only when there is no open raw snippet in the
26
- buffer.
25
+ Commands execute immediately, but only when there is no open raw snippet
26
+ in the buffer.
27
27
 
28
- Raw k source is accumulated until the interpreter can decide the snippet is
29
- complete.
28
+ Raw k source is accumulated until the interpreter can decide the snippet
29
+ is complete.
30
30
 
31
31
  ## Commands
32
32
 
@@ -74,8 +74,8 @@ Examples:
74
74
  The interpreter uses these rules, in order:
75
75
 
76
76
  1. If the line ends with `\` followed only by spaces, keep buffering.
77
- 2. If the line ends with `;` followed only by spaces, that line definitively
78
- closes the snippet.
77
+ 2. If the line ends with `;` followed only by spaces, that line
78
+ definitively closes the snippet.
79
79
  3. Otherwise, try to parse the buffered snippet:
80
80
  - if it is a complete k program, compile it now
81
81
  - if it is a valid prefix, wait for more input
@@ -83,13 +83,13 @@ The interpreter uses these rules, in order:
83
83
 
84
84
  After a snippet is accepted:
85
85
 
86
- - if it has a terminal expression, compile it and evaluate it on the current
87
- value
86
+ - if it has a terminal expression, compile it and evaluate it on the
87
+ current value
88
88
  - if it is definitions only, compile it into the current state and print
89
89
  nothing on success
90
90
 
91
- This makes raw snippets useful both for interactive evaluation and for growing
92
- the live library context.
91
+ This makes raw snippets useful both for interactive evaluation and for
92
+ growing the live library context.
93
93
 
94
94
  ## State
95
95
 
@@ -101,15 +101,16 @@ The interpreter keeps:
101
101
  - `relAliases`: human relation names to canonical hashes
102
102
  - `value`: current value, initially `{}`
103
103
 
104
- Definitions are content-addressed. Rebinding an alias changes the name-to-hash
105
- mapping, but older canonical definitions remain available by hash.
106
- They stay available in the live session, but `:klib` omits historical
107
- relations that are no longer reachable from an active relation alias.
104
+ Definitions are content-addressed. Rebinding an alias changes the
105
+ name-to-hash mapping, but older canonical definitions remain available
106
+ by hash. They stay available in the live session, but `:klib` omits
107
+ historical relations that are no longer reachable from an active
108
+ relation alias.
108
109
 
109
110
  ## Alias Resolution
110
111
 
111
- Before compiling user input, the interpreter injects an alias preamble so human
112
- names can be reused naturally:
112
+ Before compiling user input, the interpreter injects an alias preamble
113
+ so human names can be reused naturally:
113
114
 
114
115
  ```k
115
116
  $ nat = @...;
@@ -119,8 +120,8 @@ succ = @...;
119
120
 
120
121
  Type aliases use `$ name = @hash;`. Relation aliases use `name = @hash;`.
121
122
 
122
- Diagnostic locations are remapped back to the visible user snippet, so error
123
- line numbers do not count the hidden preamble.
123
+ Diagnostic locations are remapped back to the visible user snippet, so
124
+ error line numbers do not count the hidden preamble.
124
125
 
125
126
  ## Completion
126
127
 
@@ -134,36 +135,46 @@ Tab completion covers:
134
135
 
135
136
  Type aliases also complete in `$name` position inside raw k input.
136
137
 
137
- For codec commands, completion covers `:codec load`, `:codec unload`, `:codec list`,
138
- file paths after `:codec load`, and codec names after `:input`.
138
+ For codec commands, completion covers `:codec load`, `:codec unload`,
139
+ `:codec list`, file paths after `:codec load`, and codec names after
140
+ `:input`.
139
141
 
140
142
  ## Loading
141
143
 
142
144
  ### `:load [--no-alias] file.k`
143
145
 
144
- Compiles the source in the current library context, merges the resulting codes
145
- and relations into the session, and recovers aliases from user-defined names in
146
- the file unless `--no-alias` is used.
146
+ Compiles the source in the current library context, merges the resulting
147
+ codes and relations into the session, and recovers aliases from
148
+ user-defined names in the file unless `--no-alias` is used.
147
149
 
148
150
  ### `:load [--no-alias] file.klib`
149
151
 
150
- Reads the plain-JSON library file and merges its codes, relations, aliases, and
151
- metadata into the session. Aliases are recovered from `meta[hash].origins[]`
152
- unless `--no-alias` is used.
152
+ Reads the plain-JSON library file and merges its codes, relations,
153
+ aliases, and metadata into the session. Aliases are recovered from
154
+ `meta[hash].origins[]` unless `--no-alias` is used.
153
155
 
154
- ## Codecs
156
+ ## Codecs and Numerical Values
155
157
 
156
- A codec is a recipe for translating between external text and enveloped *k* values:
158
+ In `k`, there are no primitive numbers or built-in numerical literals.
159
+ Values such as integers are represented as algebraic bit trees (e.g.
160
+ `$bits = < {} _, bits 0, bits 1 >`).
161
+
162
+ A codec translates between external text and enveloped *k* values:
157
163
  - `parse(text)`: parses an external string into an enveloped *k* value.
158
- - `print(value)`: serializes an enveloped *k* value to external string, throwing an `Error` if the value is not representable.
164
+ - `print(value)`: serializes an enveloped *k* value to external string,
165
+ throwing an `Error` if the value is not representable.
166
+
167
+ Codecs can define a family of target patterns (e.g. `int` parses/prints
168
+ single integers as well as lists like `[0,1,2]`).
159
169
 
160
- Codecs can define a family of target patterns (e.g. `int` parses/prints single integers as well as lists like `[0,1,2]`).
170
+ For printing in the REPL, every value is printed with the standard *k*
171
+ envelope representation, followed by lines for all loaded codecs that can
172
+ format it:
161
173
 
162
- For printing in the REPL, every value is printed with the standard *k* envelope representation, followed by lines for all loaded codecs that can format it:
163
174
  ```text
164
- > 42 int
175
+ > :input int.mjs 42
165
176
  {}|_|0|1|0|1|0|1|+ ?<{} _, ...>
166
- int: 42
177
+ int.mjs: 42
167
178
  ```
168
179
 
169
180
  For a complete guide to writing a new codec module, see
@@ -171,7 +182,9 @@ For a complete guide to writing a new codec module, see
171
182
 
172
183
  ### `:codec load file`
173
184
 
174
- Loads a codec module from an ES module file (e.g. `:codec load codecs/int.mjs`). Codecs are identified by their file name, and export `parse(text)` and `print(value)` functions.
185
+ Loads a codec module from an ES module file (e.g.
186
+ `:codec load codecs/int.mjs`). Codecs are identified by their file name,
187
+ and export `parse(text)` and `print(value)` functions.
175
188
 
176
189
  ### `:codec unload name`
177
190
 
@@ -185,7 +198,8 @@ Lists all currently loaded codecs and their source files.
185
198
 
186
199
  Parses external input using the specified codec file.
187
200
 
188
- - **Interactive mode**: `:input <codec.mjs>` switches the REPL prompt to `<codec.mjs>> `, and the next input line is parsed using that codec:
201
+ - **Interactive mode**: `:input <codec.mjs>` switches the REPL prompt
202
+ to `<codec.mjs>> `, and the next input line is parsed using that codec:
189
203
  ```text
190
204
  > :input json.mjs
191
205
  json.mjs> {"hello": "world"}
@@ -193,7 +207,8 @@ Parses external input using the specified codec file.
193
207
  json.mjs: {"hello":"world"}
194
208
  ```
195
209
 
196
- - **One-line mode**: `:input <codec.mjs> <text>` immediately parses `<text>`:
210
+ - **One-line mode**: `:input <codec.mjs> <text>` immediately parses
211
+ `<text>`:
197
212
  ```text
198
213
  > :input int.mjs 42
199
214
  {}|_|0|1|0|1|0|1|+ ?<{} _, ...>
@@ -204,20 +219,25 @@ Parses external input using the specified codec file.
204
219
  int.mjs: [0,1,2]
205
220
  ```
206
221
 
207
- Entering `:input` with no arguments displays usage and a list of loaded codecs.
222
+ Entering `:input` with no arguments displays usage and a list of loaded
223
+ codecs.
208
224
 
209
225
  ## Evaluation Engines: WASM and JS
210
226
 
211
227
  The REPL supports two evaluation engines:
212
228
 
213
- - **`wasm`** (default): Compiles k expressions into WebAssembly bytecode via polymorphic kVM lowering. Provides near-native execution speed, tail-call optimization (TCO), and stack safety on deep recursion.
214
- - **`js`**: The tree-walking JavaScript interpreter. Provides near-zero compilation latency (interprets parsed definitions directly) and convenient runtime inspection.
229
+ - **`wasm`** (default): Compiles k expressions into WebAssembly
230
+ bytecode via polymorphic kVM lowering. Provides near-native execution
231
+ speed, tail-call optimization (TCO), and stack safety on deep recursion.
232
+ - **`js`**: The tree-walking JavaScript interpreter. Provides near-zero
233
+ compilation latency (interprets parsed definitions directly) and
234
+ convenient runtime inspection.
215
235
 
216
236
  ### Engine Commands
217
237
 
218
- - `:engine` &mdash; displays active engine (`wasm` or `js`)
219
- - `:engine wasm` (or `:wasm`) &mdash; switches to the WebAssembly engine
220
- - `:engine js` (or `:js`) &mdash; switches to the JavaScript engine
238
+ - `:engine` — displays active engine (`wasm` or `js`)
239
+ - `:engine wasm` (or `:wasm`) — switches to the WebAssembly engine
240
+ - `:engine js` (or `:js`) — switches to the JavaScript engine
221
241
 
222
242
  ### CLI Options
223
243
 
@@ -230,8 +250,9 @@ k-repl --engine=wasm # or k-repl --wasm (default)
230
250
 
231
251
  ## Timing and Profiling
232
252
 
233
- Timing reporting is enabled by default for all evaluations, reporting elapsed time
234
- broken down into compilation and runtime execution, annotated with the active engine:
253
+ Timing reporting is enabled by default for all evaluations, reporting
254
+ elapsed time broken down into compilation and runtime execution,
255
+ annotated with the active engine:
235
256
 
236
257
  ```text
237
258
  > {10 int x, 5 int y} plus
@@ -241,30 +262,42 @@ broken down into compilation and runtime execution, annotated with the active en
241
262
 
242
263
  ## Web REPL (Studio)
243
264
 
244
- The repository provides a standalone, single-file browser REPL: `repl.html`.
265
+ The repository provides a standalone, single-file browser REPL:
266
+ `repl.html`.
245
267
 
246
- - **Zero-install in-browser execution**: Powered by WebAssembly (`wasm-in-process`) and virtual filesystem (VFS).
247
- - **Interactive UI**: Tab autocompletion, persistent text selection, execution timing badges (`comp: Xms | exec: Yms`), interactive Codecs management modal, and interactive `:input` popup modal.
268
+ - **Zero-install in-browser execution**: Powered by WebAssembly
269
+ (`wasm-in-process`) and virtual filesystem (VFS).
270
+ - **Interactive UI**: Tab autocompletion, persistent text selection,
271
+ execution timing badges (`comp: Xms | exec: Yms`), interactive Codecs
272
+ management modal, and interactive `:input` popup modal.
248
273
  - **Build**: Generate `repl.html` locally using:
249
274
  ```bash
250
275
  npm run build:repl-html
251
276
  ```
252
- - **Live Demo**: Automatically deployed to GitHub Pages via `.github/workflows/pages.yml`.
277
+ - **Live Demo**: Automatically deployed to GitHub Pages via
278
+ `.github/workflows/pages.yml`.
253
279
 
254
280
  ## Export
255
281
 
282
+ The REPL can export session state to ahead-of-time (AOT) compiled
283
+ artifacts. For full details on all formats, see
284
+ [`DOCS/FILE_FORMATS.md`](./FILE_FORMATS.md).
285
+
256
286
  ### `:klib file`
257
287
 
258
- Writes a plain-JSON `.klib` library rooted at the current relation aliases.
259
- Relations referenced by those aliases are included transitively. Historical
260
- relations retained in the live session are omitted when no active alias
261
- depends on them. The registered code snapshot is still included. The library
262
- has `main: null`; it has no binary header and no object payload version.
288
+ Writes a plain-JSON `.klib` library rooted at the current relation
289
+ aliases. Relations referenced by those aliases are included
290
+ transitively. Historical relations retained in the live session are
291
+ omitted when no active alias depends on them. The registered code
292
+ snapshot is included. The library has `main: null`; it has no binary
293
+ header and no object payload version.
263
294
 
264
295
  ### `:ko file expr`
265
296
 
266
- Compiles `expr` as the main expression in the current interpreter context and
267
- writes the resulting executable `.ko` object.
297
+ Compiles `expr` as the main expression (`main: "__main__"`) in the
298
+ current interpreter context and writes the resulting executable `.ko`
299
+ object container (prefixed by magic header `KOBJ\n`). Running this `.ko`
300
+ skips parsing and type derivation for instant execution.
268
301
 
269
302
  ## Output
270
303
 
@@ -297,3 +330,10 @@ saved nat.klib
297
330
  > :ko inc.ko inc
298
331
  saved inc.ko (inc)
299
332
  ```
333
+
334
+ ## Further Reading
335
+
336
+ - [DOCS/FILE_FORMATS.md](./FILE_FORMATS.md) —
337
+ guide to .k, .ko, .klib, and .kvm formats
338
+ - [DOCS/DICTIONARY.md](./DICTIONARY.md) — concept names and terminology
339
+ - [DOCS/CODECS.md](./CODECS.md) — guide to writing codecs
@@ -2,9 +2,9 @@
2
2
 
3
3
  `k-parse` and `k-print` work with a textual notation for k values.
4
4
 
5
- It looks like JSON because products print as JSON objects, but semantically it
6
- is not a generic JSON format. It is a readable notation for values built from
7
- the two k data constructors:
5
+ It looks like JSON because products print as JSON objects, but
6
+ semantically it is not a generic JSON format. It is a readable
7
+ notation for values built from the two k data constructors:
8
8
 
9
9
  - product
10
10
  - tagged union
@@ -16,7 +16,8 @@ A k value is a tree.
16
16
  - A product is a mapping from field labels to child values.
17
17
  - A union is a single chosen tag together with its payload value.
18
18
 
19
- There are no primitive leaves. The base leaf is the empty product:
19
+ There are no primitive leaves or built-in numbers. The base leaf is
20
+ the empty product (the unit):
20
21
 
21
22
  ```text
22
23
  {}
@@ -30,9 +31,9 @@ The textual notation used by `k-parse` and `k-print` is:
30
31
  - `{"field": value, ...}` for a product
31
32
  - `{"tag": value}` for a union
32
33
 
33
- The last form is why the notation only looks like JSON. Syntactically, a
34
- single-entry object is ambiguous in plain JSON, but in k it is interpreted
35
- through the inferred or supplied pattern.
34
+ The last form is why the notation only looks like JSON. Syntactically,
35
+ a single-entry object is ambiguous in plain JSON, but in k it is
36
+ interpreted through the inferred or supplied pattern.
36
37
 
37
38
  Examples:
38
39
 
@@ -61,9 +62,9 @@ The native k notation is more explicit for interactive work:
61
62
  - product construction: `{ v field, w other }`
62
63
  - union introduction: `v |tag`
63
64
 
64
- `k-print` does not emit that native notation. It emits the JSON-like tree
65
- notation because it is easy to pipe, inspect, and round-trip through standard
66
- text tooling.
65
+ `k-print` does not emit that native notation. It emits the JSON-like
66
+ tree notation because it is easy to pipe, inspect, and round-trip
67
+ through standard text tooling.
67
68
 
68
69
  ## `k-parse`
69
70
 
@@ -73,8 +74,8 @@ text tooling.
73
74
  2. optionally takes an input type or input pattern
74
75
  3. produces the binary `pattern + value` stream
75
76
 
76
- When no explicit pattern or type is supplied, `k-parse` derives a witness
77
- pattern from the textual tree.
77
+ When no explicit pattern or type is supplied, `k-parse` derives a
78
+ witness pattern from the textual tree.
78
79
 
79
80
  ## `k-print`
80
81
 
@@ -84,25 +85,29 @@ pattern from the textual tree.
84
85
  2. decodes it to a runtime value with its carried pattern
85
86
  3. prints the value tree in JSON-like notation
86
87
 
87
- So `k-print` is not a JSON decoder in the general sense. It is a renderer from
88
- k runtime values to a JSON-shaped textual notation.
88
+ So `k-print` is not a JSON decoder in the general sense. It is a
89
+ renderer from k runtime values to a JSON-shaped textual notation.
89
90
 
90
91
  ## Ambiguity and Patterns
91
92
 
92
- The textual tree alone does not always determine whether a single-child node is
93
- meant as a union or a singleton product. That is why patterns matter.
93
+ The textual tree alone does not always determine whether a single-child
94
+ node is meant as a union or a singleton product. That is why patterns
95
+ matter.
94
96
 
95
- When `k-parse` has no explicit input pattern, it applies the current witness
96
- rule:
97
+ When `k-parse` has no explicit input pattern, it applies the current
98
+ witness rule:
97
99
 
98
100
  - empty node => closed product
99
101
  - node with multiple children => closed product
100
102
  - node with one child => open union by default
101
103
 
102
- An explicit input pattern or input type can force a different interpretation.
104
+ An explicit input pattern or input type can force a different
105
+ interpretation.
103
106
 
104
107
  ## See Also
105
108
 
109
+ - [DOCS/FILE_FORMATS.md](./FILE_FORMATS.md) — guide to
110
+ .k, .ko, .klib, and .kvm formats
106
111
  - [codecs/README.md](../codecs/README.md)
107
112
  - [DOCS/PATTERNS.md](./PATTERNS.md)
108
113
  - [DOCS/OBJECT_FILE_AND_PATTERN.md](./OBJECT_FILE_AND_PATTERN.md)
@@ -2,12 +2,17 @@
2
2
 
3
3
  ## 1. Overview
4
4
 
5
- This algorithm infers type constraints for programs consisting of mutually recursive partial functions over algebraic data types (products and unions).
5
+ This algorithm infers type constraints for programs consisting of
6
+ mutually recursive partial functions over algebraic data types
7
+ (products and unions).
6
8
 
7
- **Input:** AST of a `k` program, consisting of function definitions (expressions), which can be seen as a set of recursive equations.
8
- **Output:** Annotated AST with type patterns (also called filters)
9
+ **Input:** AST of a `k` program, consisting of function definitions
10
+ (expressions), which can be seen as a set of recursive equations.
11
+ **Output:** Annotated AST with type patterns (also called filters).
9
12
 
10
- It is assumed that we have access (through APIs) to a universal "type registry", which provides us with unique (canonical) names for each type.
13
+ All types and relations are canonically identified by immutable
14
+ content-addressed hashes (`@hash`). Human-readable names are local
15
+ aliases.
11
16
 
12
17
  ## 2. Patterns
13
18
 
@@ -22,27 +27,39 @@ A **pattern** represents a set of types:
22
27
  | `<>` | Closed union | Exactly specified |
23
28
  | `T` | Named type | From type definition |
24
29
 
25
- **Fields:** Each pattern has associated field labels. For open patterns, additional fields may exist. For closed patterns, the field set is exact.
26
- Unknown-kind patterns have only the open form `(...)`; a closed filter must choose product `{...}`/`{}` or union `<...>`/`<>`.
30
+ **Fields:** Each pattern has associated field labels. For open patterns,
31
+ additional fields may exist. For closed patterns, the field set is exact.
32
+ Unknown-kind patterns have only the open form `(...)`; a closed filter
33
+ must choose product `{...}`/`{}` or union `<...>`/`<>`.
27
34
 
28
- A type pattern is a singleton pattern, i.e., only one type is captured by such a pattern.
35
+ A type pattern is a singleton pattern, i.e., only one type is captured
36
+ by such a pattern.
29
37
 
30
38
  ## 3. Pattern Graph - A Data Structure Used During Type Derivation
31
39
 
32
- **Nodes:** Patterns organized in a "reps" (representatives) forest, similar to union-find. However, a union of two (or more) different trees always produces a new "rep" (root) node, joining the trees.
33
- **Edges:** Labeled by field names, pointing to other patterns
34
- **Representatives:** Root nodes (called reps) represent equivalence classes
40
+ **Nodes:** Patterns organized in a "reps" (representatives) forest,
41
+ similar to union-find. However, a union of two (or more) different trees
42
+ always produces a new "rep" (root) node, joining the trees.
43
+ **Edges:** Labeled by field names, pointing to other patterns.
44
+ **Representatives:** Root nodes (called reps) represent equivalence
45
+ classes.
35
46
 
36
47
  **Operations:**
37
48
 
38
49
  - `find(p)` - get representative of pattern `p`
39
- - `unify(p₁, ..., pₙ)` - merge patterns into equivalence class, potentially adding a new rep (root); the rep gathers all edges of their children
40
- - `clone(p₁, ..., pₙ)` - generate a copy of the pattern graph connected to the patterns
41
- - `compact()` - discovers all singleton patterns and replaces them by "Named types"
50
+ - `unify(p₁, ..., pₙ)` - merge patterns into equivalence class,
51
+ potentially adding a new rep (root); the rep gathers all edges of
52
+ their children
53
+ - `clone(p₁, ..., pₙ)` - generate a copy of the pattern graph connected
54
+ to the patterns
55
+ - `compact()` - discovers all singleton patterns and replaces them by
56
+ named canonical types
42
57
 
43
58
  ## 4. Unification
44
59
 
45
- `unify(p₁, ..., pₙ)` computes the least upper bound (most specific common pattern); it may add a new node (rep) into the reps forest, but it does not modify any existing pattern node.
60
+ `unify(p₁, ..., pₙ)` computes the least upper bound (most specific
61
+ common pattern); it may add a new node (rep) into the reps forest, but
62
+ it does not modify any existing pattern node.
46
63
 
47
64
  **Rules:**
48
65
 
@@ -50,7 +67,7 @@ A type pattern is a singleton pattern, i.e., only one type is captured by such a
50
67
  - **Open + Closed:** Check field inclusion, then become closed
51
68
  - **Closed + Closed:** Check field equality, then stay closed
52
69
  - **Product ⊥ Union:** Error (incompatible)
53
- - **Type T:** Unique (canonical name)
70
+ - **Type T:** Unique (canonical `@hash` name)
54
71
 
55
72
  **Algorithm:**
56
73
 
@@ -122,7 +139,8 @@ in(f) = LOOKUP(in(f))
122
139
  out(f) = LOOKUP(out(f))
123
140
  ```
124
141
 
125
- Once the type derivation for the defining expression for `f` is done, the input and output patterns are stored and will be used.
142
+ Once the type derivation for the defining expression for `f` is done, the
143
+ input and output patterns are stored and will be used.
126
144
 
127
145
  ### Type `$ T`
128
146
 
@@ -165,19 +183,23 @@ For each SCC (in topological order):
165
183
  Repeat until convergence (max 10 iterations):
166
184
  For each function `f` in SCC:
167
185
  1. Compact `f`'s pattern graph
168
- 2. For each occurrence `o` of `g` in `f`, clone(in(g), out(g)) and unify input and output patterns of `o` with the corresponding cloned patterns
186
+ 2. For each occurrence `o` of `g` in `f`, clone(in(g), out(g))
187
+ and unify input and output patterns of `o` with the
188
+ corresponding cloned patterns
169
189
 
170
190
  If pattern graphs unchanged: break
171
191
  ```
172
192
 
173
193
  ## 7. Compaction
174
194
 
175
- **Purpose:** Replace all pattern nodes with their reps and replace all singleton patterns with types.
195
+ **Purpose:** Replace all pattern nodes with their reps and replace all
196
+ singleton patterns with types.
176
197
 
177
198
  **Algorithm:**
178
199
 
179
200
  ```text
180
- 1. Build a new graph only on reps (keep the mappings from pattern node to its rep)
201
+ 1. Build a new graph only on reps (keep the mappings from pattern
202
+ node to its rep)
181
203
  2. Identify singleton patterns (closed patterns with no open ancestors)
182
204
  3. Register singletons as named types and use them as type pattern nodes
183
205
  ```
@@ -202,7 +224,8 @@ For each function f in SCC:
202
224
  Converged = (current_state == previous_state)
203
225
  ```
204
226
 
205
- **Guarantee:** Monotonic refinement + iteration bound ensures termination
227
+ **Guarantee:** Monotonic refinement + iteration bound ensures
228
+ termination.
206
229
 
207
230
  ## 9. Error Handling
208
231
 
@@ -210,7 +233,8 @@ Converged = (current_state == previous_state)
210
233
 
211
234
  - Product vs Union
212
235
  - Closed pattern field mismatch
213
- - Two distinct type patterns (types with different canonical names) are always incompatible
236
+ - Two distinct type patterns (types with different canonical `@hash`
237
+ names) are always incompatible
214
238
 
215
239
  **Other errors:**
216
240
 
@@ -227,4 +251,26 @@ Converged = (current_state == previous_state)
227
251
  ## 10. Implementation Notes
228
252
 
229
253
  - Use reps forest for performing and tracing unification
230
- - Compact only at the end of an iteration to keep unification reasons for error messages
254
+ - Compact only at the end of an iteration to keep unification reasons
255
+ for error messages
256
+
257
+ ## 11. Role in Ahead-Of-Time (AOT) Compilation
258
+
259
+ This type derivation algorithm forms the core of Ahead-Of-Time (AOT)
260
+ type checking in `k`.
261
+
262
+ When compiling `.k` source code into an executable object (`.ko`),
263
+ a library (`.klib`), or a polymorphic kVM template (`.kvm`), type
264
+ derivation converges all principal type graphs beforehand. The resulting
265
+ artifacts store fully derived principal pattern graphs, allowing
266
+ downstream execution and linking to bypass cold-start type derivation
267
+ entirely.
268
+
269
+ ## Further Reading
270
+
271
+ - [DOCS/FILE_FORMATS.md](./FILE_FORMATS.md) — guide to
272
+ .k, .ko, .klib, and .kvm formats
273
+ - [DOCS/CONVERGENCE.md](./CONVERGENCE.md) — convergence strategies
274
+ - [DOCS/OBJECT_FILE_AND_PATTERN.md](./OBJECT_FILE_AND_PATTERN.md) —
275
+ object format and pattern encoding
276
+ - [DOCS/DICTIONARY.md](./DICTIONARY.md) — concept names and terminology