@fraczak/k 1.1.1 → 1.1.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/README.md +68 -44
- package/code.k +3 -2
- package/codes.coffee +10 -5
- package/codes.js +19 -6
- package/error.k +8 -0
- package/package.json +1 -1
- package/run.coffee +2 -1
- package/run.js +2 -1
- package/typed-fib.k +19 -0
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# k-language
|
|
2
2
|
|
|
3
|
+
npm install @fraczak/k
|
|
4
|
+
|
|
3
5
|
Another JSON transformation notation. A `k`-expression
|
|
4
6
|
(script) defines a __partial function__, i.e., a function which, in
|
|
5
7
|
general, is not defined for every input. `k`-expressions can be
|
|
@@ -55,11 +57,11 @@ Elementary partial functions are:
|
|
|
55
57
|
|
|
56
58
|
A more interesting example could be:
|
|
57
59
|
|
|
58
|
-
<
|
|
60
|
+
< GT .0, .1>
|
|
59
61
|
|
|
60
|
-
which selects the
|
|
62
|
+
which selects the maximum element in two element vector, i.e.,
|
|
61
63
|
|
|
62
|
-
[3,8] <
|
|
64
|
+
[3,8] < GT .0, .1 > --> 8
|
|
63
65
|
|
|
64
66
|
## User defined functions
|
|
65
67
|
|
|
@@ -72,7 +74,18 @@ Elementary partial functions are:
|
|
|
72
74
|
>;
|
|
73
75
|
{ () x, factorial "x!" }
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
Another example could be finding the biggest (max) value in a vector:
|
|
78
|
+
|
|
79
|
+
max = <
|
|
80
|
+
SNOC -- [x0, x1, x2, ...] -> [x0, [x1, x2, ...]]
|
|
81
|
+
[.0, .1 max] -- [x0, [x1, x2, ...]] -> [x0, max(x1,x2,...)], i.e., recursive call
|
|
82
|
+
<GT.0,.1>, -- if x0 > max(x1,x2,...) then x0 else max(x1,x2,...)
|
|
83
|
+
-- when SNOC is not defined, e.g. the argument is a singleton vector [x0]
|
|
84
|
+
.0 -- [x0] -> x0,
|
|
85
|
+
>;
|
|
86
|
+
max
|
|
87
|
+
|
|
88
|
+
## Value encodings (also called _codes_)
|
|
76
89
|
|
|
77
90
|
There are three predefined value encodings: `int`, `string`, and `bool`. The language
|
|
78
91
|
supports `code`-expressions:
|
|
@@ -95,11 +108,12 @@ The above example defines new code called _tree_.
|
|
|
95
108
|
The code can be then used in a `k`-expression as a filter. A `code`-expression
|
|
96
109
|
within `k`-expression is again prefixed by `$`.
|
|
97
110
|
|
|
98
|
-
$tree = <string leaf, {tree left, tree right} tree>;
|
|
111
|
+
$ tree = <string leaf, {tree left, tree right} tree>;
|
|
99
112
|
inc = [(),1] PLUS;
|
|
113
|
+
max = <GT .0, .1>;
|
|
100
114
|
height = $ tree <
|
|
101
115
|
.leaf 0,
|
|
102
|
-
.tree [.left height, .right height]
|
|
116
|
+
.tree [.left height, .right height] max inc
|
|
103
117
|
> $ int;
|
|
104
118
|
height
|
|
105
119
|
|
|
@@ -124,7 +138,7 @@ run the language from command line.
|
|
|
124
138
|
2. By providing only `k`-expression, the script will compile the
|
|
125
139
|
`k`-expression and apply the generated function to the `stdin`, line by line:
|
|
126
140
|
|
|
127
|
-
$ ./k
|
|
141
|
+
$ ./node_modules/.bin/k '<["x=",.x," & y=",.y],["only x=",.x],["only y=",.y],["no x nor y"]>{CONCAT "x&y"}'
|
|
128
142
|
|
|
129
143
|
{"y": 123, "x": 432,"others": "..."} --> {"x&y":"x=432 & y=123"}
|
|
130
144
|
{"x":987} --> {"x&y":"only x=987"}
|
|
@@ -150,11 +164,11 @@ run the language from command line.
|
|
|
150
164
|
|
|
151
165
|
We can use it by:
|
|
152
166
|
|
|
153
|
-
$ ./k
|
|
167
|
+
$ ./node_modules/.bin/k -k test.k
|
|
154
168
|
|
|
155
169
|
If we want to read `json` objects from a file, e.g., `my-objects.json`, we do
|
|
156
170
|
|
|
157
|
-
$ ./k
|
|
171
|
+
$ ./node_modules/.bin/k -k test.k my-objects.json
|
|
158
172
|
{"x&y":"x=432 & y=123"}
|
|
159
173
|
{"x&y":"onlyx=987"}
|
|
160
174
|
{"x&y":"no x nor y"}
|
|
@@ -170,52 +184,62 @@ run the language from command line.
|
|
|
170
184
|
####################################################
|
|
171
185
|
|
|
172
186
|
# Using from `javascript`
|
|
173
|
-
|
|
174
|
-
|
|
187
|
+
|
|
188
|
+
var k = require("k");
|
|
189
|
+
|
|
190
|
+
k_expression = '()';
|
|
191
|
+
k.run(k_expression,"ANYTHING...");
|
|
192
|
+
// RETURNS: "ANYTHING..."
|
|
193
|
+
|
|
194
|
+
k_expression = '{"ala" name, 23 age}';
|
|
195
|
+
k.run(k_expression,"ANYTHING...");
|
|
196
|
+
// RETURNS: {"name":"ala","age":23}
|
|
197
|
+
|
|
198
|
+
k_expression = '[.year, .age]';
|
|
199
|
+
k.run(k_expression,{"year":2002,"age":19});
|
|
200
|
+
// RETURNS: [2002,19]
|
|
175
201
|
|
|
176
|
-
|
|
202
|
+
k_expression = '[(), ()]';
|
|
203
|
+
k.run(k_expression,"duplicate me");
|
|
204
|
+
// RETURNS: ["duplicate me","duplicate me"]
|
|
177
205
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
206
|
+
k_expression = '[[[()]]]';
|
|
207
|
+
k.run(k_expression,"nesting");
|
|
208
|
+
// RETURNS: [[["nesting"]]]
|
|
181
209
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
210
|
+
k_expression = '[[()]] {() nested, .0.0 val}';
|
|
211
|
+
k.run(k_expression,"nesting and accessing");
|
|
212
|
+
// RETURNS: {"nested":[["nesting and accessing"]],"val":"nesting and accessing"}
|
|
185
213
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
214
|
+
k_expression = '0000';
|
|
215
|
+
k.run(k_expression,{"test":"parse integer"});
|
|
216
|
+
// RETURNS: 0
|
|
189
217
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
218
|
+
k_expression = '[.y,.x] PLUS';
|
|
219
|
+
k.run(k_expression,{"x":3,"y":4});
|
|
220
|
+
// RETURNS: 7
|
|
193
221
|
|
|
194
|
-
|
|
195
|
-
k.run(k_expression,"nesting");
|
|
196
|
-
// RETURNS: [[["nesting"]]]
|
|
222
|
+
var k_fn = k.compile('{.name nom, <[.age, 18] GT .0, [.age, 12] GT "ado", "enfant"> age}');
|
|
197
223
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
// RETURNS: {"nested":[["nesting and accessing"]],"val":"nesting and accessing"}
|
|
224
|
+
k_fn({"age":23,"name":"Emily"});
|
|
225
|
+
// RETURNS: {"nom":"Emily","age":23}
|
|
201
226
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
// RETURNS: 0
|
|
227
|
+
k_fn({"age":16,"name":"Katrina"});
|
|
228
|
+
// RETURNS: {"nom":"Katrina","age":"ado"}
|
|
205
229
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// RETURNS: 7
|
|
230
|
+
k_fn({"age":2,"name":"Mark"});
|
|
231
|
+
// RETURNS: {"nom":"Mark","age":"enfant"}
|
|
209
232
|
|
|
210
|
-
|
|
233
|
+
var k_fn = k.compile('$t = < i: int, t: [ t ] > ; <$t, $int>');
|
|
211
234
|
|
|
212
|
-
|
|
235
|
+
k_fn(1);
|
|
236
|
+
// RETURNS: 1
|
|
213
237
|
|
|
214
|
-
|
|
215
|
-
|
|
238
|
+
k_fn({"i":1});
|
|
239
|
+
// RETURNS: {"i":1}
|
|
216
240
|
|
|
217
|
-
|
|
218
|
-
|
|
241
|
+
k_fn([{"i":2},{"i":3},{"t":[]}]);
|
|
242
|
+
// RETURNS: undefined
|
|
219
243
|
|
|
220
|
-
|
|
221
|
-
|
|
244
|
+
k_fn({"t":[{"i":2},{"i":3},{"t":[]}]});
|
|
245
|
+
// RETURNS: {"t":[{"i":2},{"i":3},{"t":[]}]}
|
package/code.k
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
inc = [(),1] PLUS;
|
|
2
|
+
max = <GT .0, .1>; -- max = < SNOC [.0, .1 max] <GT .0, .1>, .0 >;
|
|
2
3
|
$tree = < string leaf, {tree left, tree right} tree>;
|
|
3
4
|
height = $tree <
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
.leaf 0,
|
|
6
|
+
.tree [.left height, .right height] max inc
|
|
6
7
|
> $int;
|
|
7
8
|
|
|
8
9
|
<$tree,
|
package/codes.coffee
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
are_different = (classes, representatives, name1, name2, codes) ->
|
|
3
|
+
# console.log {classes, representatives, name1, name2, codes}
|
|
3
4
|
return false if name1 is name2
|
|
4
5
|
code1 = codes[name1]
|
|
5
6
|
code2 = codes[name2]
|
|
@@ -8,15 +9,19 @@ are_different = (classes, representatives, name1, name2, codes) ->
|
|
|
8
9
|
switch code1.code
|
|
9
10
|
when "union", "product"
|
|
10
11
|
[fields1,fields2] = [code1, code2]. map (code) ->
|
|
11
|
-
|
|
12
|
-
fields
|
|
13
|
-
|
|
12
|
+
do (arg = code[code.code]) ->
|
|
13
|
+
Object.keys(arg).reduce (fields, label) ->
|
|
14
|
+
fields[label] = representatives[arg[label]] ? arg[label]
|
|
15
|
+
fields
|
|
16
|
+
, {}
|
|
14
17
|
return true unless Object.keys(fields1).length is Object.keys(fields2).length
|
|
15
18
|
for field,rep of fields1
|
|
19
|
+
# console.log {field,rep1:rep,rep2:fields2[field]}
|
|
16
20
|
return true unless fields2[field] is rep
|
|
17
|
-
return false
|
|
18
21
|
when "vector"
|
|
19
|
-
|
|
22
|
+
[arg1,arg2] = [code1, code2]. map ({vector}) ->
|
|
23
|
+
representatives[vector] ? vector
|
|
24
|
+
return true unless arg1 is arg2
|
|
20
25
|
false
|
|
21
26
|
|
|
22
27
|
minimize = (codes) ->
|
package/codes.js
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
var are_different, compareAs, minimize, normalize, normalizeAll, pretty, pretty_labels;
|
|
4
4
|
|
|
5
5
|
are_different = function(classes, representatives, name1, name2, codes) {
|
|
6
|
-
var code1, code2, field, fields1, fields2, rep;
|
|
6
|
+
var arg1, arg2, code1, code2, field, fields1, fields2, rep;
|
|
7
7
|
if (name1 === name2) {
|
|
8
|
+
// console.log {classes, representatives, name1, name2, codes}
|
|
8
9
|
return false;
|
|
9
10
|
}
|
|
10
11
|
code1 = codes[name1];
|
|
@@ -17,9 +18,13 @@
|
|
|
17
18
|
case "union":
|
|
18
19
|
case "product":
|
|
19
20
|
[fields1, fields2] = [code1, code2].map(function(code) {
|
|
20
|
-
return
|
|
21
|
-
return fields
|
|
22
|
-
|
|
21
|
+
return (function(arg) {
|
|
22
|
+
return Object.keys(arg).reduce(function(fields, label) {
|
|
23
|
+
var ref;
|
|
24
|
+
fields[label] = (ref = representatives[arg[label]]) != null ? ref : arg[label];
|
|
25
|
+
return fields;
|
|
26
|
+
}, {});
|
|
27
|
+
})(code[code.code]);
|
|
23
28
|
});
|
|
24
29
|
if (Object.keys(fields1).length !== Object.keys(fields2).length) {
|
|
25
30
|
return true;
|
|
@@ -27,12 +32,20 @@
|
|
|
27
32
|
for (field in fields1) {
|
|
28
33
|
rep = fields1[field];
|
|
29
34
|
if (fields2[field] !== rep) {
|
|
35
|
+
|
|
36
|
+
// console.log {field,rep1:rep,rep2:fields2[field]}
|
|
30
37
|
return true;
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
|
-
|
|
40
|
+
break;
|
|
34
41
|
case "vector":
|
|
35
|
-
|
|
42
|
+
[arg1, arg2] = [code1, code2].map(function({vector}) {
|
|
43
|
+
var ref;
|
|
44
|
+
return (ref = representatives[vector]) != null ? ref : vector;
|
|
45
|
+
});
|
|
46
|
+
if (arg1 !== arg2) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
36
49
|
}
|
|
37
50
|
return false;
|
|
38
51
|
};
|
package/error.k
ADDED
package/package.json
CHANGED
package/run.coffee
CHANGED
package/run.js
CHANGED
|
@@ -111,7 +111,8 @@
|
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
verify = function(code, value) {
|
|
114
|
-
//
|
|
114
|
+
// representatives = run.defs.representatives
|
|
115
|
+
// console.log {code,value,representatives}
|
|
115
116
|
switch (code.code) {
|
|
116
117
|
case "vector":
|
|
117
118
|
return value.every(function(x) {
|
package/typed-fib.k
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
inc = [(),1] PLUS;
|
|
2
|
+
fib2 =
|
|
3
|
+
$ { int target, int x, int "fib(x)", int "fib(x-1)" }
|
|
4
|
+
_log!
|
|
5
|
+
<
|
|
6
|
+
{[.target,.x]GT.0 target ,
|
|
7
|
+
.x inc x ,
|
|
8
|
+
[."fib(x)",."fib(x-1)"]PLUS "fib(x)" ,
|
|
9
|
+
."fib(x)" "fib(x-1)" }
|
|
10
|
+
fib2,
|
|
11
|
+
|
|
12
|
+
{[.target,.x] EQ, ."fib(x)" result}
|
|
13
|
+
.result
|
|
14
|
+
>
|
|
15
|
+
$ int;
|
|
16
|
+
|
|
17
|
+
{() target, 0 x, 1 "fib(x)", 0 "fib(x-1)"} fib2
|
|
18
|
+
|
|
19
|
+
|