@fraczak/k 5.1.2 → 6.0.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/.codex +0 -0
- package/Code-derivation-tests/blowup.mjs +3 -3
- package/Code-derivation-tests/bnat.mjs +2 -2
- package/Code-derivation-tests/codec-witness-pattern.mjs +50 -0
- package/Code-derivation-tests/convergence-strategy.mjs +24 -0
- package/Code-derivation-tests/dot.mjs +12 -9
- package/Code-derivation-tests/filter-syntax.mjs +21 -0
- package/Code-derivation-tests/loop.mjs +8 -2
- package/Code-derivation-tests/nat.mjs +1 -1
- package/Code-derivation-tests/not-not.mjs +3 -3
- package/Code-derivation-tests/pattern-envelope.mjs +68 -0
- package/Code-derivation-tests/rlz.mjs +2 -2
- package/{BIG_PICTURE.md → DOCS/BIG_PICTURE.md} +103 -50
- package/DOCS/REPL.md +191 -0
- package/DOCS/a.html +398 -0
- package/DOCS/book/01-introduction.md +51 -0
- package/DOCS/book/02-syntax-and-values.md +111 -0
- package/DOCS/book/03-types-as-finite-automata.md +156 -0
- package/DOCS/book/04-partial-functions-and-composition.md +146 -0
- package/DOCS/book/05-typing-filters-and-normalization.md +111 -0
- package/DOCS/book-combined.html +3798 -0
- package/DOCS/book-combined.md +3745 -0
- package/DOCS/book-combined.pdf +0 -0
- package/DOCS/book-combined.tex +5682 -0
- package/DOCS/book.html +65 -0
- package/DOCS/book.md +54 -0
- package/DOCS/book.pdf +0 -0
- package/DOCS/book.tex +150 -0
- package/NAT.k~ +452 -0
- package/README.md +204 -508
- package/TypeGraph.mjs +43 -0
- package/TypePatternGraph.mjs +251 -0
- package/Value.mjs +192 -0
- package/augmentation.mjs +198 -0
- package/codecs/BINARY_FORMAT.html +471 -0
- package/codecs/BINARY_FORMAT.md +53 -0
- package/codecs/POLYMORPHIC_BINARY_FORMAT.html +355 -0
- package/codecs/POLYMORPHIC_BINARY_FORMAT.md +303 -0
- package/codecs/README.md +215 -0
- package/codecs/example-pipeline.mjs +149 -0
- package/codecs/ieee.mjs +140 -0
- package/codecs/int.mjs +104 -0
- package/codecs/json-codec.mjs +215 -0
- package/codecs/json.mjs +40 -0
- package/codecs/k-parse.mjs +90 -0
- package/codecs/k-pattern.mjs +75 -0
- package/codecs/k-print.mjs +46 -0
- package/codecs/runtime/codec.mjs +768 -0
- package/codecs/runtime/ieee-pattern.mjs +30 -0
- package/codecs/runtime/pattern-json.mjs +96 -0
- package/codecs/runtime/prefix-codec.mjs +425 -0
- package/codecs/runtime/show-value.mjs +68 -0
- package/codecs/runtime/typeFromValue.mjs +34 -0
- package/codecs/runtime/unicode-string.mjs +220 -0
- package/codecs/show.mjs +41 -0
- package/codecs/string-codec.mjs +80 -0
- package/codecs/unit.mjs +51 -0
- package/codecs/utf16.mjs +66 -0
- package/codecs/utf8.mjs +37 -0
- package/codes.mjs +146 -44
- package/compiler.mjs +111 -0
- package/convergence.mjs +197 -0
- package/core.k +197 -0
- package/export.mjs +22 -32
- package/hash.mjs +29 -31
- package/ieee.klib +0 -0
- package/index.mjs +41 -15
- package/k-vscode/.vscode/launch.json +14 -0
- package/k-vscode/README.md +65 -0
- package/k-vscode/language-configuration.json +42 -0
- package/k-vscode/package-lock.json +4176 -0
- package/k-vscode/package.json +57 -0
- package/k-vscode/snippets/k.json +92 -0
- package/k-vscode/syntaxes/k.tmLanguage.json +243 -0
- package/k.mjs +56 -54
- package/object.mjs +517 -0
- package/objects/README.md +38 -0
- package/objects/compile-lib.mjs +42 -0
- package/objects/compile.mjs +42 -0
- package/objects/decompile.mjs +32 -0
- package/package.json +13 -6
- package/parser.jison +27 -46
- package/parser.mjs +68 -100
- package/pretty.mjs +21 -40
- package/repl2.mjs +662 -0
- package/run.mjs +264 -231
- package/symbol-table.mjs +3 -17
- package/test-fingerprint.mjs +7 -7
- package/test-hash-fuzz.mjs +107 -0
- package/test-hash-normalization.mjs +134 -0
- package/test-k-object.mjs +74 -0
- package/test-repl2.mjs +106 -0
- package/test.mjs +45 -70
- package/tests.sh +10 -1
- package/type_registry/registry.mjs~ +105 -0
- package/type_registry/typeParser.jison~ +132 -0
- package/typing.mjs +129 -676
- package/unification.mjs +157 -0
- package/valueIO.mjs +54 -0
- package/valueParser.jison +143 -0
- package/valueParser.mjs +713 -0
- package/Code-derivation-tests/built-in.mjs +0 -19
- package/Code-derivation-tests/vector.mjs +0 -19
- package/Filters/bug.k +0 -3
- package/Filters/composing.k +0 -15
- package/Filters/filter.k +0 -9
- package/TODO.md +0 -53
- package/TYPING.md +0 -365
- package/k-repl.cast +0 -1913
- package/k.cast +0 -618
- package/my-objects.json +0 -6
- package/patterns.mjs +0 -543
- package/repl.mjs +0 -213
- package/test-filters.mjs +0 -45
- package/typing-test.mjs +0 -40
package/README.md
CHANGED
|
@@ -1,625 +1,321 @@
|
|
|
1
1
|
# k-language
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
npm i '@fraczak/k'
|
|
5
|
-
```
|
|
6
|
-
|
|
7
|
-
From javascript:
|
|
8
|
-
|
|
9
|
-
```javascript
|
|
10
|
-
import k from "@fraczak/k"
|
|
11
|
-
|
|
12
|
-
const fn = k.compile(` -- complete "pure" k-program
|
|
13
|
-
$ nat = < {} o, nat i >; -- unary natural number encoding
|
|
14
|
-
succ = {() i} $nat; -- increment relation definition
|
|
15
|
-
succ succ succ -- +3 (in the above encoding)
|
|
16
|
-
`);
|
|
17
|
-
const three = {i:{i:{i:{o:{}}}}};
|
|
18
|
-
const six = fn(three);
|
|
19
|
-
console.log(JSON.stringify( six ));
|
|
20
|
-
// {"i":{"i":{"i":{"i":{"i":{"i":{"o":{}}}}}}}}
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Working with REPL:
|
|
3
|
+
> **k** is a language for composing first-order partial functions over algebraic data types.
|
|
24
4
|
|
|
25
|
-
|
|
5
|
+
Values are tree-shaped and built solely from **products** (records) and **tagged unions** (variants).
|
|
6
|
+
There are no built-in primitive types — the only leaf in a non-recursive definition is the empty product `{}`.
|
|
7
|
+
Types (called *codes*) are finite tree automata; equivalence is bisimilarity.
|
|
26
8
|
|
|
27
9
|
---
|
|
28
10
|
|
|
29
|
-
##
|
|
11
|
+
## Quick Start
|
|
30
12
|
|
|
31
|
-
|
|
13
|
+
**Prerequisites:** Node.js 18+
|
|
32
14
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
the
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
1 .toto :
|
|
39
|
-
2 {"toto": 5, "titi": 10} --> 5
|
|
40
|
-
3 {"titi": 10} ... undefined // it is not a value!
|
|
15
|
+
```bash
|
|
16
|
+
npm install # install dev deps and generate parsers
|
|
17
|
+
npm test # run the full test suite
|
|
18
|
+
k-repl # start the interactive REPL (or: node repl2.mjs)
|
|
19
|
+
./k.mjs <file.k> # execute a k script
|
|
41
20
|
```
|
|
42
21
|
|
|
43
|
-
>
|
|
44
|
-
> is printed in the first line (before "`:`"). The following lines
|
|
45
|
-
> are examples of the function defined by the `k`-expression applayed
|
|
46
|
-
> to JSON values (first part of each line). If the function for the
|
|
47
|
-
> value is defined, then the result is printed after "`-->`" (line 2 in
|
|
48
|
-
> the above example). If the function is not defined for the value,
|
|
49
|
-
> then "`... undefined`" is printed (line 3).
|
|
22
|
+
> After `npm link` (or `npm install -g .`) the binaries `k`, `k-repl`, `k-parse`, `k-print`, etc. are available globally.
|
|
50
23
|
|
|
51
24
|
---
|
|
52
25
|
|
|
53
|
-
|
|
26
|
+
## CLI Binaries
|
|
54
27
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
{"other": {}} ... undefined
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
2. **Merge**: `< f1, f2,... >`, e.g., `<.toto, .titi>` extracts field
|
|
68
|
-
`toto` if present; otherwise extracts `titi`.
|
|
69
|
-
|
|
70
|
-
```text
|
|
71
|
-
< .x.y, .z.y > :
|
|
72
|
-
{"x":{"y": 5}, "z": {"y":10}} --> 5
|
|
73
|
-
{"x":{"o":{}}, "z": {"y":10}} --> 10
|
|
74
|
-
{"x":{"o":{}}, "z": {"o":{}}} ... undefined
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
3. **Product**: `{ f1 label1, f2 label2, ...}`, e.g., `{.toto TOTO,
|
|
78
|
-
.titi TITI}` extracts two fields and builds a record out of them.
|
|
79
|
-
|
|
80
|
-
```text
|
|
81
|
-
{.toto TOTO, .titi TITI} :
|
|
82
|
-
{"toto": 5, "titi": 10, "x": 3} --> {"TOTO": 5, "TITI": 10}
|
|
83
|
-
```
|
|
28
|
+
| Binary | Source | Purpose |
|
|
29
|
+
|--------|--------|---------|
|
|
30
|
+
| `k` | `k.mjs` | Execute a `.k` script; reads binary pattern+value stream from stdin |
|
|
31
|
+
| `k-repl` / `k-repl2` | `repl2.mjs` | Interactive REPL |
|
|
32
|
+
| `k-parse` | `codecs/k-parse.mjs` | Encode a JSON value to the binary pattern+value wire format |
|
|
33
|
+
| `k-print` | `codecs/k-print.mjs` | Decode binary pattern+value stream back to JSON |
|
|
34
|
+
| `k-pattern` | `codecs/k-pattern.mjs` | Print the pattern of a binary-encoded value |
|
|
35
|
+
| `k-compile-object` | `objects/compile.mjs` | Compile a `.k` source to a `.kobj` object file |
|
|
36
|
+
| `k-decompile-object` | `objects/decompile.mjs` | Decompile a `.kobj` file back to k source |
|
|
84
37
|
|
|
85
38
|
---
|
|
86
39
|
|
|
87
|
-
|
|
40
|
+
## Data Model: Codes = ADTs
|
|
88
41
|
|
|
89
|
-
|
|
90
|
-
- Empty merge: `<>` ?
|
|
91
|
-
- Empty product: `{}` ?
|
|
92
|
-
- `{{{{} s} s} s}` ?
|
|
93
|
-
- `({{{() a} b} c} .c .b .a)` ?
|
|
42
|
+
Codes are algebraic data types built from two constructors:
|
|
94
43
|
|
|
95
|
-
|
|
44
|
+
| Constructor | Native k notation | JSON-like notation |
|
|
45
|
+
|-------------|------------------|--------------------|
|
|
46
|
+
| **Product** (record) | `{ A label1, B label2 }` | `{ label1: A, label2: B }` |
|
|
47
|
+
| **Tagged union** (variant) | `< A tag1, B tag2 >` | `< tag1: A, tag2: B >` |
|
|
96
48
|
|
|
97
|
-
|
|
49
|
+
Native k-like notation is canonical; JSON-like is supported as syntactic sugar.
|
|
98
50
|
|
|
99
|
-
|
|
100
|
-
- dot (`.`) in "projection" acts as a separator, so the surrounding
|
|
101
|
-
space can be omitted.
|
|
51
|
+
### Defining codes (`$`)
|
|
102
52
|
|
|
103
|
-
|
|
53
|
+
```k
|
|
54
|
+
$ nat = < {} zero, nat succ >; -- Peano naturals
|
|
55
|
+
$ bit = < {} 0, {} 1 >;
|
|
56
|
+
$ byte = { bit 0, bit 1, bit 2, bit 3, bit 4, bit 5, bit 6, bit 7 };
|
|
57
|
+
$ list = < {} nil, { bit car, list cdr } cons >;
|
|
58
|
+
```
|
|
104
59
|
|
|
105
|
-
|
|
106
|
-
the end of line. Multiline `C`-like comments, `/* ... */`, are also
|
|
107
|
-
supported.
|
|
60
|
+
Two codes are equal iff they are bisimilar: same label/tag sets, same constructor kind (product vs. union), and subcodes relate pointwise under each label/tag.
|
|
108
61
|
|
|
109
|
-
|
|
62
|
+
---
|
|
110
63
|
|
|
111
|
-
|
|
64
|
+
## Partial Functions
|
|
112
65
|
|
|
113
|
-
A
|
|
114
|
-
the constant value. E.g.:
|
|
66
|
+
A partial function may be undefined on some inputs. Core primitives:
|
|
115
67
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
68
|
+
| Syntax | Name | Meaning |
|
|
69
|
+
|--------|------|---------|
|
|
70
|
+
| `.field` | product projection | extract `field` from a product value |
|
|
71
|
+
| `/tag` | union projection | assert value has tag `tag`, extract payload |
|
|
72
|
+
| `\|tag` | variant introduction | wrap value in tag `tag` |
|
|
73
|
+
| `()` | identity | pass value through unchanged |
|
|
74
|
+
| `<>` | always-undefined | undefined for all inputs |
|
|
75
|
+
| `{}` | empty product | map any input to `{}` |
|
|
120
76
|
|
|
121
|
-
|
|
122
|
-
projection, via (`.`), to the canonical string representation of the value, e.g.:
|
|
77
|
+
**Examples:**
|
|
123
78
|
|
|
124
79
|
```text
|
|
125
|
-
.
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
11 ... undefined
|
|
129
|
-
null ... undefined
|
|
130
|
-
.2 :
|
|
131
|
-
2 --> {}
|
|
132
|
-
"2" --> {}
|
|
133
|
-
4 ... undefined
|
|
134
|
-
true ... undefined
|
|
135
|
-
|
|
136
|
-
.true :
|
|
137
|
-
true --> {}
|
|
138
|
-
"true" --> {}
|
|
139
|
-
4 ... undefined
|
|
140
|
-
"toto" ... undefined
|
|
141
|
-
|
|
142
|
-
.null :
|
|
143
|
-
null --> {}
|
|
144
|
-
"null" --> {}
|
|
145
|
-
4 ... undefined
|
|
146
|
-
false ... undefined
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
#### Vector product
|
|
80
|
+
.toto :
|
|
81
|
+
{ "toto": {"5":{}}, "titi": {"10":{}} } --> {"5":{}}
|
|
82
|
+
{ "titi": {"10":{}} } ... undefined
|
|
150
83
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
`[.toto, .titi, 123]`.
|
|
84
|
+
/toto :
|
|
85
|
+
{"toto": {}} --> {}
|
|
86
|
+
{"other": {}} ... undefined
|
|
155
87
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
{"toto": 5, "titi": 10 } --> [5, 10, 12]
|
|
159
|
-
|
|
160
|
-
. 2 :
|
|
161
|
-
["A","B","C"] --> "C"
|
|
162
|
-
["a"] ... undefined
|
|
88
|
+
|toto :
|
|
89
|
+
{"5":{}} --> { "toto": {"5":{}} }
|
|
163
90
|
```
|
|
164
91
|
|
|
165
92
|
---
|
|
166
93
|
|
|
167
|
-
|
|
94
|
+
## Combining Functions
|
|
168
95
|
|
|
169
|
-
|
|
96
|
+
### 1. Composition — sequential application
|
|
170
97
|
|
|
171
|
-
|
|
172
|
-
[4,3] --> [4,3]
|
|
173
|
-
[3,4] ... undefined
|
|
174
|
-
[] --> []
|
|
175
|
-
[4,3,0] --> [4,3,0]
|
|
98
|
+
`(f g h)` applies `f`, then `g`, then `h`. Parentheses can be omitted.
|
|
176
99
|
|
|
177
|
-
|
|
100
|
+
```text
|
|
101
|
+
(.toto .titi) :
|
|
102
|
+
{ "toto": { "titi": {} } } --> {}
|
|
103
|
+
{ "toto": { "other": {} } } ... undefined
|
|
104
|
+
```
|
|
178
105
|
|
|
179
|
-
|
|
180
|
-
[4,4] --> [4,4]
|
|
181
|
-
[4,5] ... undefined
|
|
182
|
-
[4,4,4] --> [4,4,4]
|
|
183
|
-
[] --> []
|
|
106
|
+
### 2. Merge — first-defined wins
|
|
184
107
|
|
|
185
|
-
|
|
108
|
+
`<f, g>` tries `f` first; if undefined, tries `g`.
|
|
186
109
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
110
|
+
```text
|
|
111
|
+
< .x .y, .z .y > :
|
|
112
|
+
{ "x": {"y": {"5":{}}}, "z": {"y": {"10":{}}} } --> {"5":{}}
|
|
113
|
+
{ "x": {"o": {}}, "z": {"y": {"10":{}}} } --> {"10":{}}
|
|
114
|
+
{ "x": {"o": {}}, "z": {"o": {}} } ... undefined
|
|
115
|
+
```
|
|
191
116
|
|
|
192
|
-
|
|
117
|
+
### 3. Product — parallel, labelled collection
|
|
193
118
|
|
|
194
|
-
|
|
195
|
-
["a","bc","d"] --> "abcd"
|
|
196
|
-
[] --> ""
|
|
119
|
+
`{f label1, g label2}` applies `f` and `g` in parallel and builds a record.
|
|
197
120
|
|
|
198
|
-
|
|
121
|
+
```text
|
|
122
|
+
{ .toto TOTO, .titi TITI } :
|
|
123
|
+
{ "toto": {"5":{}}, "titi": {"10":{}}, "x":{} }
|
|
124
|
+
--> { "TOTO": {"5":{}}, "TITI": {"10":{}} }
|
|
125
|
+
```
|
|
199
126
|
|
|
200
|
-
|
|
201
|
-
{"a": 12} --> "{\"a\":12}"
|
|
127
|
+
---
|
|
202
128
|
|
|
203
|
-
|
|
204
|
-
"{\"a\":12}" --> {"a":12}
|
|
129
|
+
## Syntactic Sugar
|
|
205
130
|
|
|
206
|
-
-
|
|
207
|
-
|
|
131
|
+
- Parentheses may be omitted (except for empty composition `()`).
|
|
132
|
+
- `.a .b /c` is equivalent to `(.a (.b /c))`.
|
|
133
|
+
- Comments: `//`, `--`, `%`, `#` (single-line) or `/* ... */` (multi-line).
|
|
134
|
+
- Both notation forms work in the same file.
|
|
208
135
|
|
|
209
136
|
---
|
|
210
137
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
```k-repl
|
|
214
|
-
dec = [(),-1] PLUS;
|
|
215
|
-
max = <SNOC [.car, .cdr max] <GT.0, .1>, .0> ;
|
|
216
|
-
factorial = < [(),0] GT .0 [dec factorial, ()] TIMES, 1 >;
|
|
217
|
-
6 factorial
|
|
218
|
-
--> 720
|
|
219
|
-
```
|
|
138
|
+
## REPL
|
|
220
139
|
|
|
221
|
-
|
|
140
|
+
Start with `k-repl` (or `node repl2.mjs`). The prompt is `> `.
|
|
222
141
|
|
|
223
|
-
|
|
142
|
+
### Defining names and codes
|
|
224
143
|
|
|
225
|
-
```k-repl
|
|
226
|
-
$ nat = < nat 1, {} 0 >;
|
|
227
|
-
$ pair = { nat x, nat y };
|
|
228
|
-
|
|
229
|
-
suc = { $ nat 1 };
|
|
230
|
-
add = $ pair <{.x.1 x, .y suc y} add, .y>;
|
|
231
144
|
```
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
Two codes are considered equal when they are isomorphic (preserving
|
|
237
|
-
union/product and field names). E.g., `$pair`, `${nat y, nat x}`, and
|
|
238
|
-
`${<nat 1, {} 0> x, nat y}` are all equivalent and corresponds its cannonical form
|
|
239
|
-
`$C0={C1"x",C1"y"};$C1=<C2"0",C1"1">;$C2={};`.
|
|
240
|
-
|
|
241
|
-
Try in `k-repl`:
|
|
242
|
-
|
|
243
|
-
```k-repl
|
|
244
|
-
> $ nat = < nat 1, {} 0 >; \
|
|
245
|
-
$ pair = { nat x, nat y };
|
|
246
|
-
--> {}
|
|
247
|
-
> --C pair
|
|
248
|
-
$ IxLVRLECv = {BADJOX x, BADJOX y}; -- $C0={C1"x",C1"y"};$C1=<C2"0",C1"1">;$C2={};
|
|
249
|
-
$ myCode = {<nat 1, {} 0> x, nat y};
|
|
250
|
-
--> {}
|
|
251
|
-
> --C myCode
|
|
252
|
-
$ IxLVRLECv = {BADJOX x, BADJOX y}; -- $C0={C1"x",C1"y"};$C1=<C2"0",C1"1">;$C2={};
|
|
145
|
+
> $ nat = < {} zero, nat succ >;
|
|
146
|
+
> succ = |succ;
|
|
147
|
+
> zero = {} |zero $nat;
|
|
253
148
|
```
|
|
254
149
|
|
|
255
|
-
|
|
150
|
+
### REPL commands
|
|
256
151
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
152
|
+
| Command | Effect |
|
|
153
|
+
|---------|--------|
|
|
154
|
+
| `--C name` | Show canonical (hash-addressed) form of a code |
|
|
155
|
+
| `--R name` | Show the type derivation (pattern graph) for a function |
|
|
156
|
+
| `--help` | List available commands |
|
|
261
157
|
|
|
262
|
-
|
|
263
|
-
$ intVector = [ int ];
|
|
264
|
-
$ boolVector = [ bool ];
|
|
265
|
-
$ tree = [ tree ];
|
|
266
|
-
```
|
|
158
|
+
**Example session:**
|
|
267
159
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
introduces two patterns `p_i` and `p_o` (for input and output codes,
|
|
274
|
-
respectively); `p_o` imposes no constraint on code, however `p_i` is a
|
|
275
|
-
product or union code with field `toto` leading to a code fulfilling
|
|
276
|
-
`p_o`, which will be denoted by:
|
|
277
|
-
|
|
278
|
-
```k-repl
|
|
160
|
+
```
|
|
161
|
+
> $ nat = < {} zero, nat succ >;
|
|
162
|
+
> $ pair = { nat x, nat y };
|
|
163
|
+
> --C pair
|
|
164
|
+
$ @wq9VvJgYt8sASQfevD23... = { @w8iSHe... x, @w8iSHe... y };
|
|
279
165
|
> toto = .toto;
|
|
280
|
-
--> {}
|
|
281
166
|
> --R toto
|
|
282
|
-
toto : ?
|
|
283
|
-
toto = .toto;
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
In a more complex expression each (occurrence of) subexpression will
|
|
287
|
-
introduce some new patterns.
|
|
288
|
-
For example, concider ` rel = <.toto, ()>; `.
|
|
289
|
-
|
|
290
|
-
< .toto , () >
|
|
291
|
-
p1 p2 p3 p4 p5 p6
|
|
292
|
-
|
|
293
|
-
where `p1` is the pattern for the input code of the whole expression,
|
|
294
|
-
and `p6` is the pattern for the output. We can deduce that patterns
|
|
295
|
-
(`p1`, `p2`, `p4`) defines the same code, as well as (`p6`, `p5`, `p3`),
|
|
296
|
-
because union combines partial functions with the same input and output codes.
|
|
297
|
-
Identity, `()`, implies that (`p4`, `p5`) define the
|
|
298
|
-
same code. In `k-repl`:
|
|
299
|
-
|
|
300
|
-
```k-repl
|
|
301
|
-
> rel = < .toto, () >;
|
|
302
|
-
--> {}
|
|
303
|
-
> --R rel
|
|
304
|
-
rel : ?(X0 toto, ...)=X0 --> ?X0
|
|
305
|
-
rel = <.toto, ()>;
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
For a given `kScript`, code derivation (as any static analysis) can
|
|
309
|
-
fail, indicating that the script is invalid. In some other cases the
|
|
310
|
-
code derivation can succeed even to the point of reducig every pattern
|
|
311
|
-
to a single code making the program fully annotated by codes.
|
|
312
|
-
|
|
313
|
-
The language `k` supports _type patterns_, which is used for code
|
|
314
|
-
derivation, however the patterns are not concidered in the
|
|
315
|
-
evaluation of the program.
|
|
316
|
-
|
|
317
|
-
```k-repl
|
|
318
|
-
treePattern = ?<(...) leaf, {T left, T right} tree> = T;
|
|
167
|
+
toto : ?{ X0 toto, ... } --> ?X0
|
|
319
168
|
```
|
|
320
169
|
|
|
321
170
|
---
|
|
322
171
|
|
|
323
|
-
|
|
172
|
+
## Code Derivation and Patterns
|
|
324
173
|
|
|
325
|
-
A
|
|
326
|
-
|
|
327
|
-
i.e., turn into a regular vector using `CARET` (`^`) operator. E.g.:
|
|
174
|
+
A **pattern** (or *filter*) is a constraint on the type of values flowing through a function.
|
|
175
|
+
The type derivation engine infers patterns automatically and can optionally be guided with filter expressions:
|
|
328
176
|
|
|
329
177
|
```k
|
|
330
|
-
|
|
331
|
-
[{x:12}, {x:8}, {y:98}] --> [12,8]
|
|
332
|
-
["a","x","b","x"] --> [{},{}]
|
|
178
|
+
treeFilter = ?< (...) leaf, { T left, T right } tree > = T;
|
|
333
179
|
```
|
|
334
180
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
```k
|
|
338
|
-
[.0 |, .1 |] ^ :
|
|
339
|
-
[[1,2], [3,4]] --> [[1,3],[1,4],[2,3],[2,4]]
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
or
|
|
343
|
-
|
|
344
|
-
```k
|
|
345
|
-
{ | x, | y } ^ :
|
|
346
|
-
[1,2] --> [{"x":1,"y":1},{"x":2,"y":1},{"x":1,"y":2},{"x":2,"y":2}]
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
**QUIZ**: Write a function which will take a list of integers and an integer `x`, and count how many
|
|
350
|
-
times value `x` appears in the list. (see `Examples/list-comprehension.k` for a solution)
|
|
351
|
-
|
|
352
|
-
```k
|
|
353
|
-
count_occurrences =
|
|
354
|
-
$ { [int] list, int x }
|
|
355
|
-
-- ???
|
|
356
|
-
$ int;
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
**WARNING**: When using `CARET` operator paranthesis may be required, e.g., like in:
|
|
360
|
-
|
|
361
|
-
```k
|
|
362
|
-
| ( [|,|] ^ ) ^ :
|
|
363
|
-
[[1,2],[3,4]] --> [[[1,1],[1,2],[2,1],[2,2]],[[3,3],[3,4],[4,3],[4,4]]]
|
|
364
|
-
```
|
|
181
|
+
This tells the derivation engine that `treeFilter` operates on values that are either a `leaf` or a `tree` with matched left/right subtypes.
|
|
365
182
|
|
|
366
183
|
---
|
|
367
184
|
|
|
368
|
-
##
|
|
369
|
-
|
|
370
|
-
1. projection:
|
|
371
|
-
|
|
372
|
-
.x
|
|
373
|
-
. "field name"
|
|
374
|
-
(. 4)
|
|
375
|
-
|
|
376
|
-
The function is defined if its argument "has" the field.
|
|
377
|
-
|
|
378
|
-
2. _constants_, literals for Strings, Booleans, and
|
|
379
|
-
Integers. Examples:
|
|
380
|
-
|
|
381
|
-
"a string"
|
|
382
|
-
'another "String"'
|
|
383
|
-
123
|
|
384
|
-
false
|
|
385
|
-
null
|
|
386
|
-
|
|
387
|
-
3. "built-in" functions:
|
|
185
|
+
## Using k as a Library (Node.js)
|
|
388
186
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
[3, 2] GT -- vector constant function [3, 2]
|
|
392
|
-
[3, 4] GT -- ... undefined
|
|
187
|
+
```js
|
|
188
|
+
import k from "@fraczak/k"; // or "./index.mjs"
|
|
393
189
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
[3,8] < GT .0, .1 > --> 8
|
|
401
|
-
|
|
402
|
-
### User defined functions
|
|
403
|
-
|
|
404
|
-
`k`-expression can be prefixed by function definitions. E.g.:
|
|
405
|
-
|
|
406
|
-
dec = [(),-1] PLUS;
|
|
407
|
-
zero? = [(),0] EQ 0;
|
|
408
|
-
factorial = <
|
|
409
|
-
zero? 1,
|
|
410
|
-
[dec factorial, ()] TIMES
|
|
411
|
-
>;
|
|
412
|
-
{ () x, factorial "x!" }
|
|
413
|
-
|
|
414
|
-
Another example could be finding the biggest (max) value in a vector:
|
|
415
|
-
|
|
416
|
-
max = <
|
|
417
|
-
SNOC # [x0, x1, x2, ...] --> {x0 car, [x1, x2, ...] cdr}
|
|
418
|
-
[.car, .cdr max] # {car:x0, cdr:[x1, x2, ...]} --> [x0, max(x1,x2,...)], recursive call
|
|
419
|
-
<GT .0, .1> # if x0 > max(x1,x2,...) then x0 else max(x1,x2,...)
|
|
420
|
-
, # when SNOC is not defined, i.e., if the input vector has one element:
|
|
421
|
-
.0 # [x0] --> x0
|
|
422
|
-
>;
|
|
423
|
-
max
|
|
424
|
-
|
|
425
|
-
### Value encodings (_codes_)
|
|
426
|
-
|
|
427
|
-
There are three predefined value encodings: `int`, `string`, and
|
|
428
|
-
`bool`. The language supports `code`-expressions:
|
|
429
|
-
|
|
430
|
-
- product, e.g., `{int x, int y, bool flag}`
|
|
431
|
-
- disjoint union, e.g., `<{} true, {} false>`
|
|
432
|
-
- vector, e.g., `[ int ]` (all elements of the vector use the same
|
|
433
|
-
encoding)
|
|
434
|
-
|
|
435
|
-
One can define recursive codes. E.g.:
|
|
190
|
+
// compile + run
|
|
191
|
+
const fn = k.compile(`
|
|
192
|
+
$ bool = < {} true, {} false >;
|
|
193
|
+
not = < /true {} |false $bool, /false {} |true $bool >
|
|
194
|
+
`);
|
|
436
195
|
|
|
437
|
-
|
|
196
|
+
console.log(fn({ "true": {} })); // { false: {} }
|
|
438
197
|
|
|
439
|
-
|
|
440
|
-
|
|
198
|
+
// annotate only (type-check without running)
|
|
199
|
+
const annotated = k.annotate(source, {
|
|
200
|
+
convergence: { strategy: "auto" } // "auto" | "single_pass" | "fixed_point"
|
|
201
|
+
});
|
|
202
|
+
console.log(annotated.compileStats); // per-SCC strategy and iteration counts
|
|
203
|
+
```
|
|
441
204
|
|
|
442
|
-
|
|
443
|
-
within `k`-expression is again prefixed by `$`.
|
|
205
|
+
### Convergence strategies
|
|
444
206
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
.tree [.left height, .right height] max inc
|
|
451
|
-
> $ int;
|
|
452
|
-
height
|
|
207
|
+
| Strategy | Behaviour |
|
|
208
|
+
|----------|-----------|
|
|
209
|
+
| `auto` *(default)* | Single-pass for non-recursive SCCs; fixed-point for recursive ones |
|
|
210
|
+
| `single_pass` | Force single-pass (fast, use for acyclic modules) |
|
|
211
|
+
| `fixed_point` | Force the full convergence loop (useful for debugging) |
|
|
453
212
|
|
|
454
213
|
---
|
|
455
214
|
|
|
456
|
-
##
|
|
215
|
+
## Standard Library — `core.k`
|
|
457
216
|
|
|
458
|
-
|
|
459
|
-
|
|
217
|
+
`core.k` is the k standard core library. It is loaded automatically by the codec pipeline and
|
|
218
|
+
is available as a reference for any k program that needs canonical types.
|
|
219
|
+
It defines four things, in order:
|
|
460
220
|
|
|
461
|
-
|
|
462
|
-
... errors ...
|
|
463
|
-
Usage: ./node_modules/.bin/k ( k-expr | -k k-file) [ -1 ] [ json-file ]
|
|
464
|
-
E.g., cat '{"a": 10}' | ./node_modules/.bin/k '[(),()]'
|
|
221
|
+
### §1 & §2 — `$bits` and arithmetic
|
|
465
222
|
|
|
466
|
-
|
|
223
|
+
`$bits` is the canonical binary number type (LSB-first trie: empty `_`, extend with `0` or `1`).
|
|
224
|
+
It is also used as node-index encoding inside pattern graphs.
|
|
467
225
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
{"x":12,"input":{"x":12,"y":13}}
|
|
472
|
-
|
|
473
|
-
2. By providing only `k`-expression, the script will compile the
|
|
474
|
-
`k`-expression and apply the generated function to the `stdin`,
|
|
475
|
-
line by line:
|
|
476
|
-
|
|
477
|
-
> k '<["x=",.x," & y=",.y],["only x=",.x],["only y=",.y],["no x nor y"]>{CONCAT "x&y"}'
|
|
478
|
-
|
|
479
|
-
{"y": 123, "x": 432,"others": "..."} --> {"x&y":"x=432 & y=123"}
|
|
480
|
-
{"x": 987} --> {"x&y":"only x=987"}
|
|
481
|
-
{"z": 123} --> {"x&y":"no x nor y"}
|
|
482
|
-
^D - to interrupt
|
|
483
|
-
|
|
484
|
-
If the input is a multiline json object, we need to add `-1` to the command-line options.
|
|
226
|
+
```k
|
|
227
|
+
$ bits = < {} _, bits 0, bits 1 >;
|
|
228
|
+
```
|
|
485
229
|
|
|
486
|
-
|
|
230
|
+
Built-in functions: `inv`, `concat`, `succ`, `plus`, `times`, and integer constants `0`–`10`.
|
|
487
231
|
|
|
488
|
-
|
|
489
|
-
--------- comments start by #, --, or // ----------------------------------
|
|
490
|
-
< -- merge of 4 partial functions...
|
|
491
|
-
["x=", .x, " & y=", .y], -- produces a vector of 4 values, if fields 'x' and 'y' are present
|
|
492
|
-
["only x=", .x], -- produces a pair '["only x=", "value-of-x"]', for input like {"x":"value-of-x"}
|
|
493
|
-
-- it is defined only if field 'x' is present
|
|
494
|
-
["only y=", .y],
|
|
495
|
-
["no x nor y"] -- defined for all input, returns always the same one element vector
|
|
496
|
-
>
|
|
497
|
-
-- one of the string vectors is passed to the following partial function,
|
|
498
|
-
-- which produces a record (map) with one field "x&y", whose value is the
|
|
499
|
-
-- result of concatenating elements of the passed in vector
|
|
500
|
-
{ CONCAT "x&y" }
|
|
501
|
-
------------------------------------------------------------------------------
|
|
232
|
+
### §3 — `$unicode` and `$string`
|
|
502
233
|
|
|
503
|
-
|
|
234
|
+
Full Unicode scalar-value type, partitioned by plane and BMP range, built up from `$bit` and `$byte`.
|
|
235
|
+
`$string` is a linked-list of `$unicode` values — used for field/tag label names in pattern graphs.
|
|
504
236
|
|
|
505
|
-
|
|
237
|
+
```k
|
|
238
|
+
$ string = < {} nil, { unicode car, string cdr } cons >;
|
|
239
|
+
```
|
|
506
240
|
|
|
507
|
-
|
|
241
|
+
### §4 — `$pattern`
|
|
508
242
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
{"x&y":"only x=987"}
|
|
512
|
-
{"x&y":"no x nor y"}
|
|
243
|
+
The self-describing type of k pattern graphs. A pattern is a cons-list of `$pattern-node` values;
|
|
244
|
+
node 0 is the root; edges carry `$string` labels and `$bits` target indices.
|
|
513
245
|
|
|
514
|
-
|
|
246
|
+
```k
|
|
247
|
+
$ pattern-node = < {} any, edges open-product, edges open-union,
|
|
248
|
+
edges closed-product, edges closed-union >;
|
|
249
|
+
$ pattern = < {} nil, { pattern-node car, pattern cdr } cons >;
|
|
250
|
+
```
|
|
515
251
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
{"x": 987}
|
|
521
|
-
{"z": 123}
|
|
522
|
-
####################################################
|
|
252
|
+
The singleton pattern of `$pattern` itself is the fixed framing constant for the wire format:
|
|
253
|
+
every k binary stream starts with a `$pattern` encoded under that constant,
|
|
254
|
+
followed by the value encoded under the pattern just decoded.
|
|
255
|
+
This is why `core.k` ends with a bare `$pattern` expression — it pins that canonical hash.
|
|
523
256
|
|
|
524
257
|
---
|
|
525
258
|
|
|
526
|
-
|
|
259
|
+
## Binary Codec Pipeline
|
|
527
260
|
|
|
528
|
-
|
|
261
|
+
The `k` CLI reads and writes a binary stream: a serialised pattern followed by the value encoded under that pattern.
|
|
529
262
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
which acts like a toy shell for the language.
|
|
536
|
-
|
|
537
|
-
```k-repl
|
|
538
|
-
$ k-repl
|
|
539
|
-
Very! experimental repl shell for 'k-language'...
|
|
540
|
-
--c print aliased codes
|
|
541
|
-
--C code print 'code' definition
|
|
542
|
-
--r print relations
|
|
543
|
-
--R rel print 'rel' definition with type patterns
|
|
544
|
-
--p (--pp) pretty-print last value
|
|
545
|
-
--s (--g) reg store (get) the current value in (from) register 'reg'
|
|
546
|
-
--regs print register names
|
|
547
|
-
--l file.k load 'file.k'
|
|
548
|
-
>
|
|
263
|
+
```bash
|
|
264
|
+
echo '{"cons":{"car":{"1":{}},"cdr":{"nil":{}}}}' \
|
|
265
|
+
| k-parse \
|
|
266
|
+
| k ./Examples/nat.k \
|
|
267
|
+
| k-print
|
|
549
268
|
```
|
|
550
269
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
## Using `k` from `javascript`
|
|
270
|
+
See [`codecs/README.md`](codecs/README.md) for codec internals and format details.
|
|
554
271
|
|
|
555
|
-
|
|
556
|
-
import k from "@fraczak/k";
|
|
557
|
-
|
|
558
|
-
let k_expression = '()';
|
|
559
|
-
k.run(k_expression,"ANYTHING...");
|
|
560
|
-
// RETURNS: "ANYTHING..."
|
|
561
|
-
|
|
562
|
-
k_expression = '{"ala" name, 23 age}';
|
|
563
|
-
k.run(k_expression,"ANYTHING...");
|
|
564
|
-
// RETURNS: {"name":"ala","age":23}
|
|
565
|
-
|
|
566
|
-
k_expression = '[.year, .age]';
|
|
567
|
-
k.run(k_expression,{"year":2002,"age":19});
|
|
568
|
-
// RETURNS: [2002,19]
|
|
569
|
-
|
|
570
|
-
k_expression = '[(), ()]';
|
|
571
|
-
k.run(k_expression,"duplicate me");
|
|
572
|
-
// RETURNS: ["duplicate me","duplicate me"]
|
|
573
|
-
|
|
574
|
-
k_expression = '[[[()]]]';
|
|
575
|
-
k.run(k_expression,"nesting");
|
|
576
|
-
// RETURNS: [[["nesting"]]]
|
|
577
|
-
|
|
578
|
-
k_expression = '[[()]] {() nested, .0.0 val}';
|
|
579
|
-
k.run(k_expression,"nesting and accessing");
|
|
580
|
-
// RETURNS: {"nested":[["nesting and accessing"]],"val":"nesting and accessing"}
|
|
581
|
-
|
|
582
|
-
k_expression = '0000';
|
|
583
|
-
k.run(k_expression,{"test":"parse integer"});
|
|
584
|
-
// RETURNS: 0
|
|
272
|
+
---
|
|
585
273
|
|
|
586
|
-
|
|
587
|
-
k.run(k_expression,{"x":3,"y":4});
|
|
588
|
-
// RETURNS: 7
|
|
274
|
+
## Examples
|
|
589
275
|
|
|
590
|
-
|
|
276
|
+
The [`Examples/`](Examples/) directory contains ready-to-run `.k` scripts:
|
|
591
277
|
|
|
592
|
-
|
|
593
|
-
|
|
278
|
+
| File | Contents |
|
|
279
|
+
|------|----------|
|
|
280
|
+
| `nat.k` | Peano natural numbers |
|
|
281
|
+
| `list.k` | Polymorphic lists |
|
|
282
|
+
| `byte.k` | Byte type (8 bits) |
|
|
283
|
+
| `ieee.k` | IEEE 754 floating-point layout |
|
|
284
|
+
| `bnat.k` | Binary natural numbers |
|
|
285
|
+
| `arithmetics.k` | Integer and rational arithmetic (binary encoding) |
|
|
594
286
|
|
|
595
|
-
|
|
596
|
-
// RETURNS: {"nom":"Katrina","age":"ado"}
|
|
287
|
+
---
|
|
597
288
|
|
|
598
|
-
|
|
599
|
-
// RETURNS: {"nom":"Mark","age":"enfant"}
|
|
289
|
+
## Development
|
|
600
290
|
|
|
601
|
-
|
|
291
|
+
```bash
|
|
292
|
+
npm run prepare # regenerate parsers from .jison grammars (after editing them)
|
|
293
|
+
npm test # run full test suite
|
|
294
|
+
```
|
|
602
295
|
|
|
603
|
-
|
|
604
|
-
// RETURNS: 1
|
|
296
|
+
The test suite covers:
|
|
605
297
|
|
|
606
|
-
|
|
607
|
-
|
|
298
|
+
- `test.mjs` — core runtime and parser unit tests
|
|
299
|
+
- `Code-derivation-tests/*.mjs` — type derivation suite
|
|
300
|
+
- `test-fingerprint.mjs` — hash/fingerprint stability
|
|
301
|
+
- `test-k-object.mjs` — object file round-trip
|
|
302
|
+
- `test-repl2.mjs` — REPL scripted interaction
|
|
303
|
+
- `tests.sh` — shell integration tests
|
|
608
304
|
|
|
609
|
-
|
|
610
|
-
// RETURNS: undefined
|
|
305
|
+
---
|
|
611
306
|
|
|
612
|
-
|
|
613
|
-
// RETURNS: {"t":[{"i":2},{"i":3},{"t":[]}]}
|
|
307
|
+
## Quiz
|
|
614
308
|
|
|
615
|
-
|
|
309
|
+
What does each of the following evaluate to?
|
|
616
310
|
|
|
617
|
-
|
|
618
|
-
|
|
311
|
+
| Expression | Hint |
|
|
312
|
+
|------------|------|
|
|
313
|
+
| `()` | Empty composition |
|
|
314
|
+
| `<>` | Empty merge |
|
|
315
|
+
| `{}` | Empty product |
|
|
316
|
+
| `\|s\|s\|s/s/s/s` | Tag and untag three times |
|
|
317
|
+
| `({{{() a} b} c} .c .b .a)` | Nest and project |
|
|
619
318
|
|
|
620
|
-
|
|
621
|
-
// RETURNS: {"list":{"ints":[]}}
|
|
319
|
+
---
|
|
622
320
|
|
|
623
|
-
|
|
624
|
-
// RETURNS: {"list":{"ints":[1,2,3]}}
|
|
625
|
-
```
|
|
321
|
+
For more details see the [`DOCS/`](DOCS/) folder, and especially [`DOCS/book.md`](DOCS/book.md) for the language reference.
|