@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.
Files changed (115) hide show
  1. package/.codex +0 -0
  2. package/Code-derivation-tests/blowup.mjs +3 -3
  3. package/Code-derivation-tests/bnat.mjs +2 -2
  4. package/Code-derivation-tests/codec-witness-pattern.mjs +50 -0
  5. package/Code-derivation-tests/convergence-strategy.mjs +24 -0
  6. package/Code-derivation-tests/dot.mjs +12 -9
  7. package/Code-derivation-tests/filter-syntax.mjs +21 -0
  8. package/Code-derivation-tests/loop.mjs +8 -2
  9. package/Code-derivation-tests/nat.mjs +1 -1
  10. package/Code-derivation-tests/not-not.mjs +3 -3
  11. package/Code-derivation-tests/pattern-envelope.mjs +68 -0
  12. package/Code-derivation-tests/rlz.mjs +2 -2
  13. package/{BIG_PICTURE.md → DOCS/BIG_PICTURE.md} +103 -50
  14. package/DOCS/REPL.md +191 -0
  15. package/DOCS/a.html +398 -0
  16. package/DOCS/book/01-introduction.md +51 -0
  17. package/DOCS/book/02-syntax-and-values.md +111 -0
  18. package/DOCS/book/03-types-as-finite-automata.md +156 -0
  19. package/DOCS/book/04-partial-functions-and-composition.md +146 -0
  20. package/DOCS/book/05-typing-filters-and-normalization.md +111 -0
  21. package/DOCS/book-combined.html +3798 -0
  22. package/DOCS/book-combined.md +3745 -0
  23. package/DOCS/book-combined.pdf +0 -0
  24. package/DOCS/book-combined.tex +5682 -0
  25. package/DOCS/book.html +65 -0
  26. package/DOCS/book.md +54 -0
  27. package/DOCS/book.pdf +0 -0
  28. package/DOCS/book.tex +150 -0
  29. package/NAT.k~ +452 -0
  30. package/README.md +204 -508
  31. package/TypeGraph.mjs +43 -0
  32. package/TypePatternGraph.mjs +251 -0
  33. package/Value.mjs +192 -0
  34. package/augmentation.mjs +198 -0
  35. package/codecs/BINARY_FORMAT.html +471 -0
  36. package/codecs/BINARY_FORMAT.md +53 -0
  37. package/codecs/POLYMORPHIC_BINARY_FORMAT.html +355 -0
  38. package/codecs/POLYMORPHIC_BINARY_FORMAT.md +303 -0
  39. package/codecs/README.md +215 -0
  40. package/codecs/example-pipeline.mjs +149 -0
  41. package/codecs/ieee.mjs +140 -0
  42. package/codecs/int.mjs +104 -0
  43. package/codecs/json-codec.mjs +215 -0
  44. package/codecs/json.mjs +40 -0
  45. package/codecs/k-parse.mjs +90 -0
  46. package/codecs/k-pattern.mjs +75 -0
  47. package/codecs/k-print.mjs +46 -0
  48. package/codecs/runtime/codec.mjs +768 -0
  49. package/codecs/runtime/ieee-pattern.mjs +30 -0
  50. package/codecs/runtime/pattern-json.mjs +96 -0
  51. package/codecs/runtime/prefix-codec.mjs +425 -0
  52. package/codecs/runtime/show-value.mjs +68 -0
  53. package/codecs/runtime/typeFromValue.mjs +34 -0
  54. package/codecs/runtime/unicode-string.mjs +220 -0
  55. package/codecs/show.mjs +41 -0
  56. package/codecs/string-codec.mjs +80 -0
  57. package/codecs/unit.mjs +51 -0
  58. package/codecs/utf16.mjs +66 -0
  59. package/codecs/utf8.mjs +37 -0
  60. package/codes.mjs +146 -44
  61. package/compiler.mjs +111 -0
  62. package/convergence.mjs +197 -0
  63. package/core.k +197 -0
  64. package/export.mjs +22 -32
  65. package/hash.mjs +29 -31
  66. package/ieee.klib +0 -0
  67. package/index.mjs +41 -15
  68. package/k-vscode/.vscode/launch.json +14 -0
  69. package/k-vscode/README.md +65 -0
  70. package/k-vscode/language-configuration.json +42 -0
  71. package/k-vscode/package-lock.json +4176 -0
  72. package/k-vscode/package.json +57 -0
  73. package/k-vscode/snippets/k.json +92 -0
  74. package/k-vscode/syntaxes/k.tmLanguage.json +243 -0
  75. package/k.mjs +56 -54
  76. package/object.mjs +517 -0
  77. package/objects/README.md +38 -0
  78. package/objects/compile-lib.mjs +42 -0
  79. package/objects/compile.mjs +42 -0
  80. package/objects/decompile.mjs +32 -0
  81. package/package.json +13 -6
  82. package/parser.jison +27 -46
  83. package/parser.mjs +68 -100
  84. package/pretty.mjs +21 -40
  85. package/repl2.mjs +662 -0
  86. package/run.mjs +264 -231
  87. package/symbol-table.mjs +3 -17
  88. package/test-fingerprint.mjs +7 -7
  89. package/test-hash-fuzz.mjs +107 -0
  90. package/test-hash-normalization.mjs +134 -0
  91. package/test-k-object.mjs +74 -0
  92. package/test-repl2.mjs +106 -0
  93. package/test.mjs +45 -70
  94. package/tests.sh +10 -1
  95. package/type_registry/registry.mjs~ +105 -0
  96. package/type_registry/typeParser.jison~ +132 -0
  97. package/typing.mjs +129 -676
  98. package/unification.mjs +157 -0
  99. package/valueIO.mjs +54 -0
  100. package/valueParser.jison +143 -0
  101. package/valueParser.mjs +713 -0
  102. package/Code-derivation-tests/built-in.mjs +0 -19
  103. package/Code-derivation-tests/vector.mjs +0 -19
  104. package/Filters/bug.k +0 -3
  105. package/Filters/composing.k +0 -15
  106. package/Filters/filter.k +0 -9
  107. package/TODO.md +0 -53
  108. package/TYPING.md +0 -365
  109. package/k-repl.cast +0 -1913
  110. package/k.cast +0 -618
  111. package/my-objects.json +0 -6
  112. package/patterns.mjs +0 -543
  113. package/repl.mjs +0 -213
  114. package/test-filters.mjs +0 -45
  115. package/typing-test.mjs +0 -40
package/README.md CHANGED
@@ -1,625 +1,321 @@
1
1
  # k-language
2
2
 
3
- ```sh
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
- [![asciicast](https://asciinema.org/a/UZuFpX4a5CQ47JTQngv253EVv.svg)](https://asciinema.org/a/UZuFpX4a5CQ47JTQngv253EVv)
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
- ## k - the way of building and manipulating JSON-like data
11
+ ## Quick Start
30
12
 
31
- Technically, `k` is a notation for defining **first-order partial functions**.
13
+ **Prerequisites:** Node.js 18+
32
14
 
33
- An example of a _partial function_ is the _projection_, e.g., "`.toto`",
34
- which maps an object to its property named `toto`, or it is not defined if
35
- the property doesn't exist. E.g.,
36
-
37
- ```text
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
- > Note: The above 3 lines should be read as follows. A `k`-expression
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
- ### Combining "partial functions"
26
+ ## CLI Binaries
54
27
 
55
- There are three ways of combining functions:
56
-
57
- 1. **Composition**: `(f1 f2 ...)`, e.g. `(.toto .titi)` extracts
58
- nested field.
59
-
60
- ```text
61
- (.toto .titi) :
62
- {"toto": {"titi": 10}} --> 10
63
- {"toto": {"other": 8}} ... undefined
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
- **QUIZ**: What is:
40
+ ## Data Model: Codes = ADTs
88
41
 
89
- - Empty composition: `()` ?
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
- ### Syntactic sugar
49
+ Native k-like notation is canonical; JSON-like is supported as syntactic sugar.
98
50
 
99
- - Parenthesis can be omitted, except for the empty composition `()`,
100
- - dot (`.`) in "projection" acts as a separator, so the surrounding
101
- space can be omitted.
51
+ ### Defining codes (`$`)
102
52
 
103
- For example, `(.toto .titi (.0 .1))` can be written as `.toto.titi.0.1`.
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
- Comments can be introduced by `//`, `--`, `%`, or `#` and extends to
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
- ### Basic extensions
62
+ ---
110
63
 
111
- #### Constants, i.e., literals for `string`, `int`, `bool`, and `null`
64
+ ## Partial Functions
112
65
 
113
- A constant defines a function which ignores its argument and produces
114
- the constant value. E.g.:
66
+ A partial function may be undefined on some inputs. Core primitives:
115
67
 
116
- ```text
117
- {123 int, "kScript" str, true bool, null null} :
118
- "any" --> {"int":123,"str":"kScript","bool":true,"null":null}
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
- Those values, i.e., _strings_, _integers_, _booleans_, and _null_, admit the
122
- projection, via (`.`), to the canonical string representation of the value, e.g.:
77
+ **Examples:**
123
78
 
124
79
  ```text
125
- ."a string" :
126
- "a string" --> {}
127
- "other" ... undefined
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
- The vector product can be seen as a shorthand for a product in which all fields
152
- have the same type, and the field names are integers starting from zero.
153
- E.g., `{.toto 0, .titi 1, 123 2}` can be written as
154
- `[.toto, .titi, 123]`.
84
+ /toto :
85
+ {"toto": {}} --> {}
86
+ {"other": {}} ... undefined
155
87
 
156
- ```text
157
- [.toto, .titi, 12] :
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
- ### Pragmatic extensions, aka "standard library"
94
+ ## Combining Functions
168
95
 
169
- - `GT` -- identity for lists of decreasing elements; undefined otherwise
96
+ ### 1. Composition — sequential application
170
97
 
171
- GT:
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
- - `EQ` -- identity for lists of equal elements; undefined otherwise
100
+ ```text
101
+ (.toto .titi) :
102
+ { "toto": { "titi": {} } } --> {}
103
+ { "toto": { "other": {} } } ... undefined
104
+ ```
178
105
 
179
- EQ:
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
- - `PLUS` and `TIMES` -- sum and product of lists of numbers
108
+ `<f, g>` tries `f` first; if undefined, tries `g`.
186
109
 
187
- {PLUS plus, TIMES times} :
188
- [1,2] --> {"plus":3,"times":2}
189
- [2,2,2] --> {"plus":6,"times":8}
190
- [] --> {"plus":0,"times":1}
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
- - `CONCAT` -- concatenation of lists of strings
117
+ ### 3. Product — parallel, labelled collection
193
118
 
194
- CONCAT:
195
- ["a","bc","d"] --> "abcd"
196
- [] --> ""
119
+ `{f label1, g label2}` applies `f` and `g` in parallel and builds a record.
197
120
 
198
- - `toJSON` and `fromJSON` -- conversion to and from JSON strings
121
+ ```text
122
+ { .toto TOTO, .titi TITI } :
123
+ { "toto": {"5":{}}, "titi": {"10":{}}, "x":{} }
124
+ --> { "TOTO": {"5":{}}, "TITI": {"10":{}} }
125
+ ```
199
126
 
200
- toJSON:
201
- {"a": 12} --> "{\"a\":12}"
127
+ ---
202
128
 
203
- fromJSON:
204
- "{\"a\":12}" --> {"a":12}
129
+ ## Syntactic Sugar
205
130
 
206
- - other predefined parial functions are: `DIV`, `FDIV`, `CONS`,
207
- `SNOC`, `toVEC`, `toDateMsec`, `toDateStr`, and `_log!`.
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
- ### Function and code (i.e., _type_) definitions
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
- ### Codes (schemas, i.e., _types_)
140
+ Start with `k-repl` (or `node repl2.mjs`). The prompt is `> `.
222
141
 
223
- _Codes_ can be defined by tagged union and product. E.g.:
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
- Code definition statement starts with `$`.
234
- Also, any code expression occurrig within a `k`-expression is prefixed by `$`.
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
- #### Basic extension codes
150
+ ### REPL commands
256
151
 
257
- Since _basic extension_ introduces integers, booleans, and strings,
258
- there are three predefined types: `int`, `bool`, and `string`. A
259
- vector product code can also be defined by `[ codeExp ]`. All members
260
- of the vector are the same code. E.g.,
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
- ```k-repl
263
- $ intVector = [ int ];
264
- $ boolVector = [ bool ];
265
- $ tree = [ tree ];
266
- ```
158
+ **Example session:**
267
159
 
268
- ### Code derivation and Patterns
269
-
270
- Intuitively, a _pattern_ represents some set of contraints on
271
- codes. For example, expression `.toto` is a projection from a value of
272
- a product or a union code with field `toto`. Therefore, expression `.toto`
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 : ?(X0 toto, ...) --> ?X0
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
- ### List comprehension
172
+ ## Code Derivation and Patterns
324
173
 
325
- A vector can be "open" by PIPE (`|`) operator so the following partial function is applied to
326
- each element of the vector, yielding another open value. An open value can be "closed",
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
- | .x ^ :
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
- The PIPE operator can be used for defining the Cartesian product:
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
- ## Examples
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
- [1, 2, 3] PLUS -- integer constant function 6
390
- [4, 4] TIMES toJSON -- string constant function "16"
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
- A more interesting example could be:
395
-
396
- < GT .0, .1>
397
-
398
- which selects the maximum element in two element vector, i.e.,
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
- $tree = <string leaf, {tree left, tree right} tree>;
196
+ console.log(fn({ "true": {} })); // { false: {} }
438
197
 
439
- Each _code_ definition starts with a `$`.
440
- The above example defines new code called _tree_.
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
- The code can be then used in a `k`-expression as a filter. A `code`-expression
443
- within `k`-expression is again prefixed by `$`.
205
+ ### Convergence strategies
444
206
 
445
- $ tree = <string leaf, {tree left, tree right} tree>;
446
- inc = [(),1] PLUS;
447
- max = <GT .0, .1>;
448
- height = $ tree <
449
- .leaf 0,
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
- ## `k` (a command-line JSON processor using `k` syntax)
215
+ ## Standard Library — `core.k`
457
216
 
458
- There is a wrapper, `k` (`./node_modules/.bin/k`), which makes it easy to
459
- run the language from command line.
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
- > k
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
- For example:
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
- 1. One `k`-expression with one `json`-object:
469
-
470
- > echo '{"x": 12, "y": 13}' | k '{ <.x, "no x"> x, () input}'
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
- 3. If the `k`-expression is long, it can be put in a file, e.g.:
230
+ Built-in functions: `inv`, `concat`, `succ`, `plus`, `times`, and integer constants `0`–`10`.
487
231
 
488
- > cat test.k
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
- We can use it by:
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
- > k -k test.k
237
+ ```k
238
+ $ string = < {} nil, { unicode car, string cdr } cons >;
239
+ ```
506
240
 
507
- If we want to read `json` objects from a file, e.g., `my-objects.jsonl`, we do
241
+ ### §4 — `$pattern`
508
242
 
509
- > k -k test.k my-objects.jsonl
510
- {"x&y":"x=432 & y=123"}
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
- where:
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
- > cat my-objects.jsonl
517
- ####################################################
518
- # empty lines and lines starting with # are ignored
519
- {"y": 123, "x": 432,"others": "..."}
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
- ### Short comparaison with `jq` tutorial examples: <https://stedolan.github.io/jq/tutorial/>
259
+ ## Binary Codec Pipeline
527
260
 
528
- [![asciicast](https://asciinema.org/a/ItH7nkc5CwFOopH8Fsr23oCWj.svg)](https://asciinema.org/a/ItH7nkc5CwFOopH8Fsr23oCWj)
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
- ## k-REPL (Read-Evaluate-Print Loop)
533
-
534
- Also, there is a REPL, `k-repl` (`./node_modules/.bin/k-repl`),
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
- ```javascript
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
- k_expression = '[.y,.x] PLUS';
587
- k.run(k_expression,{"x":3,"y":4});
588
- // RETURNS: 7
274
+ ## Examples
589
275
 
590
- var k_fn = k.compile('{.name nom, <[.age, 18] GT .0, [.age, 12] GT "ado", "enfant"> age}');
276
+ The [`Examples/`](Examples/) directory contains ready-to-run `.k` scripts:
591
277
 
592
- k_fn({"age":23,"name":"Emily"});
593
- // RETURNS: {"nom":"Emily","age":23}
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
- k_fn({"age":16,"name":"Katrina"});
596
- // RETURNS: {"nom":"Katrina","age":"ado"}
287
+ ---
597
288
 
598
- k_fn({"age":2,"name":"Mark"});
599
- // RETURNS: {"nom":"Mark","age":"enfant"}
289
+ ## Development
600
290
 
601
- k_fn = k.compile('$t = < i: int, t: [ t ] > ; <$t, $int>');
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
- k_fn(1);
604
- // RETURNS: 1
296
+ The test suite covers:
605
297
 
606
- k_fn({"i":1});
607
- // RETURNS: {"i":1}
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
- k_fn([{"i":2},{"i":3},{"t":[]}]);
610
- // RETURNS: undefined
305
+ ---
611
306
 
612
- k_fn({"t":[{"i":2},{"i":3},{"t":[]}]});
613
- // RETURNS: {"t":[{"i":2},{"i":3},{"t":[]}]}
307
+ ## Quiz
614
308
 
615
- k_fn = k.compile('$ < < [ int ] ints, [ bool ] bools > list, string None>');
309
+ What does each of the following evaluate to?
616
310
 
617
- k_fn({"None":"None"});
618
- // RETURNS: {"None":"None"}
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
- k_fn({"list":{"ints":[]}});
621
- // RETURNS: {"list":{"ints":[]}}
319
+ ---
622
320
 
623
- k_fn({"list":{"ints":[1,2,3]}});
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.