@fraczak/k 1.3.1 → 1.3.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/INTRO.md +36 -21
- package/README.md +4 -4
- package/package.json +4 -4
- package/parser.js +9 -8
- package/repl.coffee +3 -1
- package/repl.js +6 -3
- package/repl.sh +6 -3
- package/run.coffee +0 -5
- package/run.js +0 -13
- package/symbol-table.coffee +28 -2
- package/symbol-table.js +40 -3
package/INTRO.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# k - the way of building and manipulating JSON-like data
|
|
2
2
|
|
|
3
|
-
Technically
|
|
3
|
+
Technically, `k` is a notation for defining __first-order partial functions__.
|
|
4
4
|
|
|
5
|
-
An example of a _partial function_ is "`.toto`",
|
|
6
|
-
to its property named `toto`, or it is not defined if
|
|
7
|
-
doesn't exist. E.g.,
|
|
5
|
+
An example of a _partial function_ is the _projection_, e.g., "`.toto`",
|
|
6
|
+
which maps an object to its property named `toto`, or it is not defined if
|
|
7
|
+
the property doesn't exist. E.g.,
|
|
8
8
|
|
|
9
9
|
.toto :
|
|
10
10
|
{"toto": 5, "titi": 10} --> 5
|
|
@@ -51,6 +51,14 @@ __QUIZ__: What is:
|
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
+
#### Syntactic sugar:
|
|
55
|
+
|
|
56
|
+
- parenthesis can be omitted, except for the empty composition `()`,
|
|
57
|
+
- dot (`.`) in "projection" acts as a separator so the space around it can be omitted.
|
|
58
|
+
|
|
59
|
+
For example, `[(.toto .titi (.0 .1))]` can be written as `[.toto.titi.0.1]`.
|
|
60
|
+
|
|
61
|
+
|
|
54
62
|
## Basic extensions
|
|
55
63
|
|
|
56
64
|
### Constants, i.e., literals for `strings`, `integers`, `booleans`, and `null`
|
|
@@ -77,19 +85,25 @@ names are integers starting from zero. E.g., `{.toto "0", .titi "1",
|
|
|
77
85
|
|
|
78
86
|
## Pragmatic extensions, aka "standard library"
|
|
79
87
|
|
|
80
|
-
- `GT` :
|
|
88
|
+
- `GT` : -- identity for lists of decreasing elements; undefined otherwise
|
|
81
89
|
|
|
90
|
+
[4,3] --> [4,3]
|
|
91
|
+
[3,4] ... undefined
|
|
92
|
+
[] --> []
|
|
82
93
|
[4,3,0] --> [4,3,0]
|
|
83
|
-
[5,8] - undefined
|
|
84
94
|
|
|
85
|
-
- `EQ` :
|
|
95
|
+
- `EQ` : -- identity for lists of equal elements; undefined otherwise
|
|
86
96
|
|
|
97
|
+
[4,4] --> [4,4]
|
|
98
|
+
[4,5] ... undefined
|
|
87
99
|
[4,4,4] --> [4,4,4]
|
|
88
|
-
[
|
|
100
|
+
[] --> []
|
|
89
101
|
|
|
90
|
-
- `
|
|
102
|
+
- `{PLUS plus, TIMES times}` :
|
|
91
103
|
|
|
92
|
-
[
|
|
104
|
+
[1,2] --> {"plus":3,"times":2}
|
|
105
|
+
[2,2,2] --> {"plus":6,"times":8}
|
|
106
|
+
[] --> {"plus":0,"times":1}
|
|
93
107
|
|
|
94
108
|
- `CONCAT` :
|
|
95
109
|
|
|
@@ -97,24 +111,25 @@ names are integers starting from zero. E.g., `{.toto "0", .titi "1",
|
|
|
97
111
|
|
|
98
112
|
- `toJSON` :
|
|
99
113
|
|
|
100
|
-
{a: 12} --> "{\"a\":12}"
|
|
114
|
+
{"a": 12} --> "{\"a\":12}"
|
|
101
115
|
|
|
102
116
|
- `fromJSON` :
|
|
103
117
|
|
|
104
|
-
"{\"a\":12}" --> {a:
|
|
118
|
+
"{\"a\":12}" --> {"a":12}
|
|
105
119
|
|
|
106
|
-
- `DIV`, `FDIV`, `CONS`, `SNOC`, `
|
|
120
|
+
- other predefined parial functions are: `DIV`, `FDIV`, `CONS`, `SNOC`, `toDateMsec`,
|
|
121
|
+
`toDateStr`, and `_log!`.
|
|
107
122
|
|
|
108
123
|
---
|
|
109
124
|
|
|
110
125
|
## Recursive definitions
|
|
111
126
|
|
|
112
127
|
-- factorial.k
|
|
113
|
-
dec =
|
|
114
|
-
zero? =
|
|
128
|
+
dec = [(),-1] PLUS;
|
|
129
|
+
zero? = [(),0] EQ 0;
|
|
115
130
|
factorial = <
|
|
116
|
-
|
|
117
|
-
|
|
131
|
+
zero? 1,
|
|
132
|
+
[(dec factorial), ()] TIMES
|
|
118
133
|
>;
|
|
119
134
|
{ () x, factorial "x!" }
|
|
120
135
|
|
|
@@ -122,10 +137,10 @@ names are integers starting from zero. E.g., `{.toto "0", .titi "1",
|
|
|
122
137
|
|
|
123
138
|
_Codes_ (prefixed by `$`) can be defined by taged union and product. E.g.:
|
|
124
139
|
|
|
125
|
-
$nat = <nat
|
|
126
|
-
$pair = {nat x, nat y}; -- e.g., {{{}
|
|
140
|
+
$nat = <nat 1, {} 0>; -- e.g., {{{{} 0} 1} 1}
|
|
141
|
+
$pair = {nat x, nat y}; -- e.g., {{{} 0} x, {{{{} 0} 1} 1} y}
|
|
127
142
|
|
|
128
|
-
|
|
129
|
-
add =
|
|
143
|
+
suc = $nat {() 1} $nat;
|
|
144
|
+
add = $pair <{.x.1 x, .y suc y} add, .y> $nat;
|
|
130
145
|
|
|
131
146
|
|
package/README.md
CHANGED
|
@@ -51,14 +51,14 @@ the field (or a vector with the index).
|
|
|
51
51
|
false
|
|
52
52
|
null
|
|
53
53
|
|
|
54
|
-
6.
|
|
55
|
-
`TIMES`, `
|
|
56
|
-
`SNOC`, `_log
|
|
54
|
+
6. The other "built-in" functions: `GT`, `EQ`, `PLUS`,
|
|
55
|
+
`TIMES`, `DIV`, `CONCAT`, `toJSON`, `fromJSON`, `CONS`,
|
|
56
|
+
`SNOC`, `toDateMsec`, `toDateStr`, and `_log!`. For example:
|
|
57
57
|
|
|
58
58
|
[1, 2, 3] PLUS --> integer constant function 6
|
|
59
59
|
[4, 4] TIMES toJSON --> string constant function "16"
|
|
60
60
|
[3, 2] GT --> vector constant function [3, 2]
|
|
61
|
-
[3, 4] GT
|
|
61
|
+
[3, 4] GT ... is not defined!
|
|
62
62
|
|
|
63
63
|
A more interesting example could be:
|
|
64
64
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fraczak/k",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "k-language for JSON-like data transformation",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"prepare": "coffee -c symbol-table.coffee;
|
|
7
|
+
"prepare": "coffee -c symbol-table.coffee; jiwson parser.jison",
|
|
8
8
|
"prepublishOnly": "coffee -c *.coffee; echo '#!/usr/bin/env node' | cat - k.js > k.sh; echo '#!/usr/bin/env node' | cat - repl.js > repl.sh;",
|
|
9
9
|
"all": "coffee -c *.coffee; npm run prepare; npm run prepublishOnly",
|
|
10
|
-
"test": "coffee -c symbol-table.coffee;
|
|
10
|
+
"test": "coffee -c symbol-table.coffee; jiwson parser.jison; coffee test.coffee"
|
|
11
11
|
},
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
@@ -21,6 +21,6 @@
|
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"coffeescript": "^2.7.0",
|
|
24
|
-
"
|
|
24
|
+
"jiwson": "^0.1.1"
|
|
25
25
|
}
|
|
26
26
|
}
|
package/parser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* parser generated by jison 0.
|
|
1
|
+
/* parser generated by jison 0.1.1 */
|
|
2
2
|
/*
|
|
3
3
|
Returns a Parser object of the following structure:
|
|
4
4
|
|
|
@@ -71,6 +71,13 @@
|
|
|
71
71
|
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
|
|
72
72
|
}
|
|
73
73
|
*/
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
var s = require("./symbol-table");
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
74
81
|
var parser = (function(){
|
|
75
82
|
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[4,6,8,15,18,21,23,32,34],$V1=[1,7],$V2=[1,15],$V3=[1,16],$V4=[1,8],$V5=[1,9],$V6=[1,10],$V7=[1,11],$V8=[1,14],$V9=[1,20],$Va=[4,6,8,12,15,18,21,23,32,34],$Vb=[2,28],$Vc=[1,25],$Vd=[1,26],$Ve=[1,27],$Vf=[4,6,8,12,14,15,18,20,21,22,23,24,27,32,33,34],$Vg=[2,47],$Vh=[2,31],$Vi=[2,32],$Vj=[4,6,8,12,14,15,18,20,21,22,23,24,27,28,32,33,34],$Vk=[2,8],$Vl=[2,13],$Vm=[20,27],$Vn=[22,24,27],$Vo=[20,24,27],$Vp=[2,41],$Vq=[2,42],$Vr=[2,43];
|
|
76
83
|
var parser = {trace: function trace () { },
|
|
@@ -344,13 +351,7 @@ parse: function parse(input) {
|
|
|
344
351
|
}
|
|
345
352
|
}
|
|
346
353
|
return true;
|
|
347
|
-
}}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
var s = require("./symbol-table");
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
/* generated by jison-lex 0.3.4 */
|
|
354
|
+
}};/* generated by jison-lex */
|
|
354
355
|
var lexer = (function(){
|
|
355
356
|
var lexer = ({
|
|
356
357
|
|
package/repl.coffee
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
k = require "./"
|
|
3
3
|
run = require "./run"
|
|
4
4
|
{prettyCode, prettyRel} = require "./pretty"
|
|
5
|
+
fs = require "fs"
|
|
5
6
|
|
|
6
7
|
console.log "Very! experimental repl shell for 'k-language'..."
|
|
7
8
|
|
|
@@ -33,7 +34,8 @@ do (val = {}, buffer = []) ->
|
|
|
33
34
|
else if line.match re
|
|
34
35
|
file = line.match(re)[1]
|
|
35
36
|
console.log "-- loading file: #{file} ..."
|
|
36
|
-
|
|
37
|
+
kScript = fs.readFileSync(file).toString();
|
|
38
|
+
val = k.compile(kScript) val
|
|
37
39
|
console.log "=> #{JSON.stringify val}"
|
|
38
40
|
else if line.match /^[ \n\t]*(?:--a)?$/
|
|
39
41
|
console.log JSON.stringify run.defs, " ", 2
|
package/repl.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Generated by CoffeeScript 2.7.0
|
|
2
2
|
(function() {
|
|
3
3
|
//!/usr/bin/env coffee
|
|
4
|
-
var help, k, prettyCode, prettyRel, re, run,
|
|
4
|
+
var fs, help, k, prettyCode, prettyRel, re, run,
|
|
5
5
|
splice = [].splice;
|
|
6
6
|
|
|
7
7
|
k = require("./");
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
({prettyCode, prettyRel} = require("./pretty"));
|
|
12
12
|
|
|
13
|
+
fs = require("fs");
|
|
14
|
+
|
|
13
15
|
console.log("Very! experimental repl shell for 'k-language'...");
|
|
14
16
|
|
|
15
17
|
help = function() {
|
|
@@ -26,7 +28,7 @@
|
|
|
26
28
|
|
|
27
29
|
(function(val, buffer) {
|
|
28
30
|
return process.stdin.on('data', function(data) {
|
|
29
|
-
var e, file, first, i, last, len, line, ref, rest, results, todo;
|
|
31
|
+
var e, file, first, i, kScript, last, len, line, ref, rest, results, todo;
|
|
30
32
|
[first, ...rest] = data.toString("utf8").split("\n");
|
|
31
33
|
buffer.push(first);
|
|
32
34
|
if (rest.length > 0) {
|
|
@@ -45,7 +47,8 @@
|
|
|
45
47
|
} else if (line.match(re)) {
|
|
46
48
|
file = line.match(re)[1];
|
|
47
49
|
console.log(`-- loading file: ${file} ...`);
|
|
48
|
-
|
|
50
|
+
kScript = fs.readFileSync(file).toString();
|
|
51
|
+
val = k.compile(kScript)(val);
|
|
49
52
|
results.push(console.log(`=> ${JSON.stringify(val)}`));
|
|
50
53
|
} else if (line.match(/^[ \n\t]*(?:--a)?$/)) {
|
|
51
54
|
results.push(console.log(JSON.stringify(run.defs, " ", 2)));
|
package/repl.sh
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Generated by CoffeeScript 2.7.0
|
|
3
3
|
(function() {
|
|
4
4
|
//!/usr/bin/env coffee
|
|
5
|
-
var help, k, prettyCode, prettyRel, re, run,
|
|
5
|
+
var fs, help, k, prettyCode, prettyRel, re, run,
|
|
6
6
|
splice = [].splice;
|
|
7
7
|
|
|
8
8
|
k = require("./");
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
({prettyCode, prettyRel} = require("./pretty"));
|
|
13
13
|
|
|
14
|
+
fs = require("fs");
|
|
15
|
+
|
|
14
16
|
console.log("Very! experimental repl shell for 'k-language'...");
|
|
15
17
|
|
|
16
18
|
help = function() {
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
|
|
28
30
|
(function(val, buffer) {
|
|
29
31
|
return process.stdin.on('data', function(data) {
|
|
30
|
-
var e, file, first, i, last, len, line, ref, rest, results, todo;
|
|
32
|
+
var e, file, first, i, kScript, last, len, line, ref, rest, results, todo;
|
|
31
33
|
[first, ...rest] = data.toString("utf8").split("\n");
|
|
32
34
|
buffer.push(first);
|
|
33
35
|
if (rest.length > 0) {
|
|
@@ -46,7 +48,8 @@
|
|
|
46
48
|
} else if (line.match(re)) {
|
|
47
49
|
file = line.match(re)[1];
|
|
48
50
|
console.log(`-- loading file: ${file} ...`);
|
|
49
|
-
|
|
51
|
+
kScript = fs.readFileSync(file).toString();
|
|
52
|
+
val = k.compile(kScript)(val);
|
|
50
53
|
results.push(console.log(`=> ${JSON.stringify(val)}`));
|
|
51
54
|
} else if (line.match(/^[ \n\t]*(?:--a)?$/)) {
|
|
52
55
|
results.push(console.log(JSON.stringify(run.defs, " ", 2)));
|
package/run.coffee
CHANGED
|
@@ -20,11 +20,6 @@ builtin =
|
|
|
20
20
|
return args if ok
|
|
21
21
|
"PLUS": (args) -> valid args.reduce ((res, x) -> res + x), 0
|
|
22
22
|
"TIMES": (args) -> valid args.reduce ((res, x) -> res * x), 1
|
|
23
|
-
"MINUS": (args) ->
|
|
24
|
-
return valid(- args) if 'number' is typeof args
|
|
25
|
-
do ([res,args...] = args) ->
|
|
26
|
-
return valid (- res) if args.length is 0
|
|
27
|
-
valid args.reduce ((res, x) -> res - x), res
|
|
28
23
|
"DIV": ([x,y]) ->
|
|
29
24
|
div = x // y
|
|
30
25
|
rem = x %% y
|
package/run.js
CHANGED
|
@@ -49,19 +49,6 @@
|
|
|
49
49
|
return res * x;
|
|
50
50
|
}), 1));
|
|
51
51
|
},
|
|
52
|
-
"MINUS": function(args) {
|
|
53
|
-
if ('number' === typeof args) {
|
|
54
|
-
return valid(-args);
|
|
55
|
-
}
|
|
56
|
-
return (function([res, ...args]) {
|
|
57
|
-
if (args.length === 0) {
|
|
58
|
-
return valid(-res);
|
|
59
|
-
}
|
|
60
|
-
return valid(args.reduce((function(res, x) {
|
|
61
|
-
return res - x;
|
|
62
|
-
}), res));
|
|
63
|
-
})(args);
|
|
64
|
-
},
|
|
65
52
|
"DIV": function([x, y]) {
|
|
66
53
|
var div, rem;
|
|
67
54
|
div = Math.floor(x / y);
|
package/symbol-table.coffee
CHANGED
|
@@ -7,21 +7,37 @@ identity = op: "identity"
|
|
|
7
7
|
is_identity_rel = (rel) ->
|
|
8
8
|
rel.op is "identity"
|
|
9
9
|
|
|
10
|
+
is_constant_rel = (rel) ->
|
|
11
|
+
switch rel?.op
|
|
12
|
+
when "int", "str"
|
|
13
|
+
true
|
|
14
|
+
when "vector"
|
|
15
|
+
Object.values(rel[rel.op]).every is_constant_rel
|
|
16
|
+
when "product"
|
|
17
|
+
Object.values(rel[rel.op]).every ({exp}) ->
|
|
18
|
+
is_constant_rel exp
|
|
19
|
+
else
|
|
20
|
+
false
|
|
21
|
+
|
|
10
22
|
is_empty_rel = (rel) ->
|
|
11
23
|
rel.op is "union" and rel.union.length is 0
|
|
12
24
|
|
|
13
25
|
is_full_rel = (rel) ->
|
|
26
|
+
return true if is_constant_rel rel
|
|
14
27
|
switch rel.op
|
|
15
28
|
when "int", "str", "identity"
|
|
16
29
|
true
|
|
17
30
|
when "comp"
|
|
18
31
|
rel.comp.every is_full_rel
|
|
19
|
-
when "
|
|
32
|
+
when "vector"
|
|
20
33
|
Object.values(rel[rel.op]).every is_full_rel
|
|
34
|
+
when "product"
|
|
35
|
+
Object.values(rel[rel.op]).every ({exp}) ->
|
|
36
|
+
is_full_rel exp
|
|
21
37
|
else
|
|
22
38
|
false
|
|
23
39
|
|
|
24
|
-
|
|
40
|
+
comp_first = (e1, e2) ->
|
|
25
41
|
return e2 if is_identity_rel e1
|
|
26
42
|
return e1 if is_identity_rel e2
|
|
27
43
|
return e1 if is_empty_rel e1
|
|
@@ -34,6 +50,16 @@ comp = (e1, e2) ->
|
|
|
34
50
|
return {op: "comp", comp: [].concat([e1],e2.comp)}
|
|
35
51
|
{op: "comp", comp: [e1,e2]}
|
|
36
52
|
|
|
53
|
+
comp = (e1, e2) ->
|
|
54
|
+
result = comp_first e1, e2
|
|
55
|
+
return result unless result.op is "comp"
|
|
56
|
+
result.comp = result.comp.reduceRight (c, e) ->
|
|
57
|
+
if is_constant_rel(c[0]) and is_full_rel e
|
|
58
|
+
return c
|
|
59
|
+
return [e, c...]
|
|
60
|
+
, []
|
|
61
|
+
result
|
|
62
|
+
|
|
37
63
|
union = (rels) ->
|
|
38
64
|
list = []
|
|
39
65
|
do ->
|
package/symbol-table.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generated by CoffeeScript 2.7.0
|
|
2
2
|
(function() {
|
|
3
|
-
var add_code, add_rel, as_ref, codes, comp, identity, is_empty_rel, is_full_rel, is_identity_rel, rels, union;
|
|
3
|
+
var add_code, add_rel, as_ref, codes, comp, comp_first, identity, is_constant_rel, is_empty_rel, is_full_rel, is_identity_rel, rels, union;
|
|
4
4
|
|
|
5
5
|
rels = Object.create(null);
|
|
6
6
|
|
|
@@ -19,11 +19,30 @@
|
|
|
19
19
|
return rel.op === "identity";
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
is_constant_rel = function(rel) {
|
|
23
|
+
switch (rel != null ? rel.op : void 0) {
|
|
24
|
+
case "int":
|
|
25
|
+
case "str":
|
|
26
|
+
return true;
|
|
27
|
+
case "vector":
|
|
28
|
+
return Object.values(rel[rel.op]).every(is_constant_rel);
|
|
29
|
+
case "product":
|
|
30
|
+
return Object.values(rel[rel.op]).every(function({exp}) {
|
|
31
|
+
return is_constant_rel(exp);
|
|
32
|
+
});
|
|
33
|
+
default:
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
22
38
|
is_empty_rel = function(rel) {
|
|
23
39
|
return rel.op === "union" && rel.union.length === 0;
|
|
24
40
|
};
|
|
25
41
|
|
|
26
42
|
is_full_rel = function(rel) {
|
|
43
|
+
if (is_constant_rel(rel)) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
27
46
|
switch (rel.op) {
|
|
28
47
|
case "int":
|
|
29
48
|
case "str":
|
|
@@ -31,15 +50,18 @@
|
|
|
31
50
|
return true;
|
|
32
51
|
case "comp":
|
|
33
52
|
return rel.comp.every(is_full_rel);
|
|
34
|
-
case "product":
|
|
35
53
|
case "vector":
|
|
36
54
|
return Object.values(rel[rel.op]).every(is_full_rel);
|
|
55
|
+
case "product":
|
|
56
|
+
return Object.values(rel[rel.op]).every(function({exp}) {
|
|
57
|
+
return is_full_rel(exp);
|
|
58
|
+
});
|
|
37
59
|
default:
|
|
38
60
|
return false;
|
|
39
61
|
}
|
|
40
62
|
};
|
|
41
63
|
|
|
42
|
-
|
|
64
|
+
comp_first = function(e1, e2) {
|
|
43
65
|
if (is_identity_rel(e1)) {
|
|
44
66
|
return e2;
|
|
45
67
|
}
|
|
@@ -76,6 +98,21 @@
|
|
|
76
98
|
};
|
|
77
99
|
};
|
|
78
100
|
|
|
101
|
+
comp = function(e1, e2) {
|
|
102
|
+
var result;
|
|
103
|
+
result = comp_first(e1, e2);
|
|
104
|
+
if (result.op !== "comp") {
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
result.comp = result.comp.reduceRight(function(c, e) {
|
|
108
|
+
if (is_constant_rel(c[0]) && is_full_rel(e)) {
|
|
109
|
+
return c;
|
|
110
|
+
}
|
|
111
|
+
return [e, ...c];
|
|
112
|
+
}, []);
|
|
113
|
+
return result;
|
|
114
|
+
};
|
|
115
|
+
|
|
79
116
|
union = function(rels) {
|
|
80
117
|
var list;
|
|
81
118
|
list = [];
|