@fraczak/k 6.10.2 → 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 +30 -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/objects/README.md +57 -37
- package/package.json +1 -1
- package/tests/README.md +28 -17
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
|
|
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
|
|
15
|
-
library closure as a `.klib` file or compile an executable `.ko`
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
105
|
-
mapping, but older canonical definitions remain available
|
|
106
|
-
They stay available in the live session, but `:klib` omits
|
|
107
|
-
relations that are no longer reachable from an active
|
|
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
|
|
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
|
|
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`,
|
|
138
|
-
file paths after `:codec load`, and codec names after
|
|
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
|
|
145
|
-
and relations into the session, and recovers aliases from
|
|
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,
|
|
151
|
-
metadata into the session. Aliases are recovered from
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
>
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
214
|
-
|
|
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`
|
|
219
|
-
- `:engine wasm` (or `:wasm`)
|
|
220
|
-
- `:engine js` (or `:js`)
|
|
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
|
|
234
|
-
broken down into compilation and runtime execution,
|
|
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:
|
|
265
|
+
The repository provides a standalone, single-file browser REPL:
|
|
266
|
+
`repl.html`.
|
|
245
267
|
|
|
246
|
-
- **Zero-install in-browser execution**: Powered by WebAssembly
|
|
247
|
-
|
|
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
|
|
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
|
|
259
|
-
Relations referenced by those aliases are included
|
|
260
|
-
relations retained in the live session are
|
|
261
|
-
depends on them. The registered code
|
|
262
|
-
has `main: null`; it has no binary
|
|
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
|
|
267
|
-
writes the resulting executable `.ko`
|
|
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
|
package/DOCS/TEXTUAL_VALUES.md
CHANGED
|
@@ -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
|
|
6
|
-
is not a generic JSON format. It is a readable
|
|
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
|
|
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,
|
|
34
|
-
single-entry object is ambiguous in plain JSON, but in k it is
|
|
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
|
|
65
|
-
notation because it is easy to pipe, inspect, and round-trip
|
|
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
|
|
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
|
|
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
|
|
93
|
-
meant as a union or a singleton product. That is why patterns
|
|
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
|
|
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
|
|
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)
|
package/DOCS/TYPE_DERIVATION.md
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## 1. Overview
|
|
4
4
|
|
|
5
|
-
This algorithm infers type constraints for programs consisting of
|
|
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
|
|
8
|
-
|
|
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
|
-
|
|
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,
|
|
26
|
-
|
|
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
|
|
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,
|
|
33
|
-
|
|
34
|
-
|
|
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,
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
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
|
|
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))
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|