@fraczak/k 4.0.2 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -128
- package/k-repl.cast +1913 -0
- package/k-repl.cast~ +1939 -0
- package/k.cast +618 -0
- package/package.json +1 -1
- package/repl.mjs +12 -13
- package/run.mjs +3 -1
- package/TYPES.md +0 -32
package/README.md
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
# k-language
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
```sh
|
|
4
|
+
npm i '@fraczak/k'
|
|
5
|
+
```
|
|
4
6
|
|
|
5
7
|
From javascript:
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
```javascript
|
|
10
|
+
import k from "@fraczak/k"
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
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:
|
|
24
|
+
|
|
25
|
+
[](https://asciinema.org/a/UZuFpX4a5CQ47JTQngv253EVv)
|
|
12
26
|
|
|
13
27
|
---
|
|
14
28
|
|
|
@@ -20,9 +34,11 @@ An example of a _partial function_ is the _projection_, e.g., "`.toto`",
|
|
|
20
34
|
which maps an object to its property named `toto`, or it is not defined if
|
|
21
35
|
the property doesn't exist. E.g.,
|
|
22
36
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
37
|
+
```text
|
|
38
|
+
1 .toto :
|
|
39
|
+
2 {"toto": 5, "titi": 10} --> 5
|
|
40
|
+
3 {"titi": 10} ... undefined // it is not a value!
|
|
41
|
+
```
|
|
26
42
|
|
|
27
43
|
> Note: The above 3 lines should be read as follows. A `k`-expression
|
|
28
44
|
> is printed in the first line (before "`:`"). The following lines
|
|
@@ -41,25 +57,30 @@ There are three ways of combining functions:
|
|
|
41
57
|
1. **composition**: `(f1 f2 ...)`, e.g. `(.toto .titi)` extracts
|
|
42
58
|
nested field.
|
|
43
59
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
60
|
+
```text
|
|
61
|
+
(.toto .titi) :
|
|
62
|
+
{"toto": {"titi": 10}} --> 10
|
|
63
|
+
{"toto": {"other": 8}} ... undefined
|
|
64
|
+
{"other": {}} ... undefined
|
|
65
|
+
```
|
|
48
66
|
|
|
49
67
|
2. **merge**: `< f1, f2,... >`, e.g., `<.toto, .titi>` extracts field
|
|
50
68
|
`toto` if present; otherwise extracts `titi`.
|
|
51
69
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
+
```
|
|
56
76
|
|
|
57
77
|
3. **product**: `{ f1 label1, f2 label2, ...}`, e.g., `{.toto TOTO,
|
|
58
|
-
.titi TITI}` extracts two fields and builds a record out of them.
|
|
78
|
+
.titi TITI}` extracts two fields and builds a record out of them.
|
|
59
79
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
80
|
+
```text
|
|
81
|
+
{.toto TOTO, .titi TITI} :
|
|
82
|
+
{"toto": 5, "titi": 10, "x": 3} --> {"TOTO": 5, "TITI": 10}
|
|
83
|
+
```
|
|
63
84
|
|
|
64
85
|
---
|
|
65
86
|
|
|
@@ -92,46 +113,54 @@ supported.
|
|
|
92
113
|
A constant defines a function which ignores its argument and produces
|
|
93
114
|
the constant value. E.g.:
|
|
94
115
|
|
|
95
|
-
|
|
96
|
-
|
|
116
|
+
```text
|
|
117
|
+
{123 int, "kScript" str, true bool, null null} :
|
|
118
|
+
"any" --> {"int":123,"str":"kScript","bool":true,"null":null}
|
|
119
|
+
```
|
|
97
120
|
|
|
98
121
|
Those values, i.e., _strings_, _integers_, _booleans_, and _null_, admit the
|
|
99
|
-
projection to the
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
122
|
+
projection, via (`.`), to the canonical string representation of the value, e.g.:
|
|
123
|
+
|
|
124
|
+
```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
|
+
```
|
|
118
148
|
|
|
119
149
|
#### Vector product
|
|
120
150
|
|
|
121
|
-
Vector product can be seen as an abbreviation for product whose
|
|
122
|
-
names are integers starting from zero.
|
|
151
|
+
Vector product can be seen as an abbreviation for product whose all fields
|
|
152
|
+
have the same type, and the filed names are integers starting from zero.
|
|
123
153
|
E.g., `{.toto 0, .titi 1, 123 2}` can be written as
|
|
124
154
|
`[.toto, .titi, 123]`.
|
|
125
155
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
.1 :
|
|
130
|
-
["A","B","C"] --> "B"
|
|
131
|
-
["a"] ... undefined
|
|
156
|
+
```text
|
|
157
|
+
[.toto, .titi, 12] :
|
|
158
|
+
{"toto": 5, "titi": 10 } --> [5, 10, 12]
|
|
132
159
|
|
|
133
|
-
|
|
134
|
-
|
|
160
|
+
. 2 :
|
|
161
|
+
["A","B","C"] --> "C"
|
|
162
|
+
["a"] ... undefined
|
|
163
|
+
```
|
|
135
164
|
|
|
136
165
|
---
|
|
137
166
|
|
|
@@ -164,7 +193,7 @@ is not supported in _code derivation_ (explained below).
|
|
|
164
193
|
|
|
165
194
|
CONCAT:
|
|
166
195
|
["a","bc","d"] --> "abcd"
|
|
167
|
-
[
|
|
196
|
+
[] --> ""
|
|
168
197
|
|
|
169
198
|
- `toJSON` and `fromJSON` -- conversion to and from JSON strings
|
|
170
199
|
|
|
@@ -173,8 +202,6 @@ is not supported in _code derivation_ (explained below).
|
|
|
173
202
|
|
|
174
203
|
fromJSON:
|
|
175
204
|
"{\"a\":12}" --> {"a":12}
|
|
176
|
-
"2.12" --> 2.12
|
|
177
|
-
"[1,2.11,0.3e-32]" --> [1,2.11,3e-33]
|
|
178
205
|
|
|
179
206
|
- other predefined parial functions are: `DIV`, `FDIV`, `CONS`,
|
|
180
207
|
`SNOC`, `toVEC`, `toDateMsec`, `toDateStr`, and `_log!`.
|
|
@@ -183,24 +210,47 @@ is not supported in _code derivation_ (explained below).
|
|
|
183
210
|
|
|
184
211
|
### Function and code (i.e., _type_) definitions
|
|
185
212
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
+
```
|
|
189
220
|
|
|
190
221
|
### Codes (schemas, i.e., _types_)
|
|
191
222
|
|
|
192
|
-
_Codes_
|
|
223
|
+
_Codes_ can be defined by tagged union and product. E.g.:
|
|
193
224
|
|
|
225
|
+
```k-repl
|
|
226
|
+
$ nat = < nat 1, {} 0 >;
|
|
227
|
+
$ pair = { nat x, nat y };
|
|
194
228
|
|
|
195
|
-
|
|
196
|
-
|
|
229
|
+
suc = { $ nat 1 };
|
|
230
|
+
add = $ pair <{.x.1 x, .y suc y} add, .y>;
|
|
231
|
+
```
|
|
197
232
|
|
|
198
|
-
|
|
199
|
-
|
|
233
|
+
Code definition statement starts with `$`.
|
|
234
|
+
Also, any code expression occurrig within a `k`-expression is prefixed by `$`.
|
|
200
235
|
|
|
201
236
|
Two codes are considered equal when they are isomorphic (preserving
|
|
202
237
|
union/product and field names). E.g., `$pair`, `${nat y, nat x}`, and
|
|
203
|
-
`${<nat 1, {} 0> x, nat y}` are all
|
|
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={};
|
|
253
|
+
```
|
|
204
254
|
|
|
205
255
|
#### Basic extension codes
|
|
206
256
|
|
|
@@ -209,26 +259,33 @@ there are three predefined types: `int`, `bool`, and `string`. A
|
|
|
209
259
|
vector product code can also be defined by `[ codeExp ]`. All members
|
|
210
260
|
of the vector are the same code. E.g.,
|
|
211
261
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
262
|
+
```k-repl
|
|
263
|
+
$ intVector = [ int ];
|
|
264
|
+
$ boolVector = [ bool ];
|
|
265
|
+
$ tree = [ tree ];
|
|
266
|
+
```
|
|
215
267
|
|
|
216
268
|
### Code derivation and Patterns
|
|
217
269
|
|
|
218
270
|
Intuitively, a _pattern_ represents some set of contraints on
|
|
219
271
|
codes. For example, expression `.toto` is a projection from a value of
|
|
220
|
-
a product or a union with field `toto`. Therefore, expression `.toto`
|
|
272
|
+
a product or a union code with field `toto`. Therefore, expression `.toto`
|
|
221
273
|
introduces two patterns `p_i` and `p_o` (for input and output codes,
|
|
222
274
|
respectively); `p_o` imposes no constraint on code, however `p_i` is a
|
|
223
275
|
product or union code with field `toto` leading to a code fulfilling
|
|
224
|
-
`p_o`,
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
276
|
+
`p_o`, which will be denoted by:
|
|
277
|
+
|
|
278
|
+
```k-repl
|
|
279
|
+
> toto = .toto;
|
|
280
|
+
--> {}
|
|
281
|
+
> --R toto
|
|
282
|
+
toto : ?(X0 toto, ...) --> ?X0
|
|
283
|
+
toto = .toto;
|
|
284
|
+
```
|
|
228
285
|
|
|
229
286
|
In a more complex expression each (occurrence of) subexpression will
|
|
230
287
|
introduce some new patterns.
|
|
231
|
-
For example, concider
|
|
288
|
+
For example, concider ` rel = <.toto, ()>; `.
|
|
232
289
|
|
|
233
290
|
< .toto , () >
|
|
234
291
|
p1 p2 p3 p4 p5 p6
|
|
@@ -238,28 +295,27 @@ and `p6` is the pattern for the output. We can deduce that patterns
|
|
|
238
295
|
(`p1`, `p2`, `p4`) defines the same code, as well as (`p6`, `p5`, `p3`),
|
|
239
296
|
because union combines partial functions with the same input and output codes.
|
|
240
297
|
Identity, `()`, implies that (`p4`, `p5`) define the
|
|
241
|
-
same code.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
Since the product code pattern (i.e., latter case) doesn't admmit any
|
|
251
|
-
(finite) value, we conclude that the code `c` is a union (i.e.,
|
|
252
|
-
former case).
|
|
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
|
+
```
|
|
253
307
|
|
|
254
308
|
For a given `kScript`, code derivation (as any static analysis) can
|
|
255
309
|
fail, indicating that the script is invalid. In some other cases the
|
|
256
310
|
code derivation can succeed even to the point of reducig every pattern
|
|
257
311
|
to a single code making the program fully annotated by codes.
|
|
258
312
|
|
|
259
|
-
The language `k` supports _type patterns_, which is used for
|
|
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.
|
|
260
316
|
|
|
261
|
-
```k
|
|
262
|
-
|
|
317
|
+
```k-repl
|
|
318
|
+
treePattern = ?<(...) leaf, {T left, T right} tree> = T;
|
|
263
319
|
```
|
|
264
320
|
|
|
265
321
|
---
|
|
@@ -267,13 +323,13 @@ The language `k` supports _type patterns_, which is used for type inference, how
|
|
|
267
323
|
### List comprehension
|
|
268
324
|
|
|
269
325
|
A vector can be "open" by PIPE (`|`) operator so the following partial function is applied to
|
|
270
|
-
each element of the vector
|
|
326
|
+
each element of the vector, yielding another open value. An open value can be "closed",
|
|
271
327
|
i.e., turn into a regular vector using `CARET` (`^`) operator. E.g.:
|
|
272
328
|
|
|
273
329
|
```k
|
|
274
330
|
| .x ^ :
|
|
275
|
-
[{x:12}, {x:8
|
|
276
|
-
[
|
|
331
|
+
[{x:12}, {x:8}, {y:98}] --> [12,8]
|
|
332
|
+
["a","x","b","x"] --> [{},{}]
|
|
277
333
|
```
|
|
278
334
|
|
|
279
335
|
The PIPE operator can be used for defining the Cartesian product:
|
|
@@ -314,8 +370,8 @@ times value `x` appears in the list. (see `Examples/list-comprehension.k` for a
|
|
|
314
370
|
1. projection:
|
|
315
371
|
|
|
316
372
|
.x
|
|
317
|
-
."field name"
|
|
318
|
-
.4
|
|
373
|
+
. "field name"
|
|
374
|
+
(. 4)
|
|
319
375
|
|
|
320
376
|
The function is defined if its argument "has" the field.
|
|
321
377
|
|
|
@@ -358,11 +414,11 @@ times value `x` appears in the list. (see `Examples/list-comprehension.k` for a
|
|
|
358
414
|
Another example could be finding the biggest (max) value in a vector:
|
|
359
415
|
|
|
360
416
|
max = <
|
|
361
|
-
SNOC #
|
|
362
|
-
[.car, .cdr max] #
|
|
363
|
-
<GT .0, .1> #
|
|
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,...)
|
|
364
420
|
, # when SNOC is not defined, i.e., if the input vector has one element:
|
|
365
|
-
.0 #
|
|
421
|
+
.0 # [x0] --> x0
|
|
366
422
|
>;
|
|
367
423
|
max
|
|
368
424
|
|
|
@@ -448,16 +504,16 @@ For example:
|
|
|
448
504
|
|
|
449
505
|
> k -k test.k
|
|
450
506
|
|
|
451
|
-
If we want to read `json` objects from a file, e.g., `my-objects.
|
|
507
|
+
If we want to read `json` objects from a file, e.g., `my-objects.jsonl`, we do
|
|
452
508
|
|
|
453
|
-
> k -k test.k my-objects.
|
|
509
|
+
> k -k test.k my-objects.jsonl
|
|
454
510
|
{"x&y":"x=432 & y=123"}
|
|
455
511
|
{"x&y":"only x=987"}
|
|
456
512
|
{"x&y":"no x nor y"}
|
|
457
513
|
|
|
458
514
|
where:
|
|
459
515
|
|
|
460
|
-
> cat my-objects.
|
|
516
|
+
> cat my-objects.jsonl
|
|
461
517
|
####################################################
|
|
462
518
|
# empty lines and lines starting with # are ignored
|
|
463
519
|
{"y": 123, "x": 432,"others": "..."}
|
|
@@ -469,40 +525,28 @@ For example:
|
|
|
469
525
|
|
|
470
526
|
### Short comparaison with `jq` tutorial examples: <https://stedolan.github.io/jq/tutorial/>
|
|
471
527
|
|
|
472
|
-
|
|
473
|
-
curl 'https://api.github.com/repositories/5101141/commits?per_page=5' | jq '.'
|
|
474
|
-
curl 'https://api.github.com/repositories/5101141/commits?per_page=5' | k '()' -1
|
|
475
|
-
2.
|
|
476
|
-
curl 'https://api.github.com/repositories/5101141/commits?per_page=5' | jq '.[0]'
|
|
477
|
-
curl 'https://api.github.com/repositories/5101141/commits?per_page=5' | k '.0' -1
|
|
478
|
-
3.
|
|
479
|
-
jq '.[0] | {message: .commit.message, name: .commit.committer.name}'
|
|
480
|
-
k '.0 {.commit.message message, .commit.committer.name name}' -1
|
|
481
|
-
4. note: `k`-expression defines a partial function yielding a single json object, i.e., as far as `k` is concerned,
|
|
482
|
-
examples 4 and 5 of the `jq` tutorial are equivalent.
|
|
483
|
-
5.
|
|
484
|
-
jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'
|
|
485
|
-
k '| .commit {.message message, .committer.name name} ^' -1
|
|
486
|
-
6.
|
|
487
|
-
jq '[.[] | {message: .commit.message, name: .commit.committer.name, parents: [.parents[].html_url]}]'
|
|
488
|
-
k '| {.commit.message message, .commit.committer.name name, .parents | .html_url ^ parents} ^' -1
|
|
528
|
+
[](https://asciinema.org/a/ItH7nkc5CwFOopH8Fsr23oCWj)
|
|
489
529
|
|
|
490
530
|
---
|
|
491
531
|
|
|
492
532
|
## k-REPL (Read-Evaluate-Print Loop)
|
|
493
533
|
|
|
494
|
-
Also there is a REPL, `k-repl` (`./node_modules/.bin/k-repl`),
|
|
495
|
-
shell for the language.
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
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
|
+
>
|
|
549
|
+
```
|
|
506
550
|
|
|
507
551
|
---
|
|
508
552
|
|