@fraczak/k 4.0.3 → 5.0.0

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/export.mjs ADDED
@@ -0,0 +1,177 @@
1
+
2
+ import { prettyRel, patterns2filters } from "./pretty.mjs";
3
+ import { hash } from "./hash.mjs";
4
+
5
+ function simplifyRel(relDef) {
6
+ // remove filters and codes
7
+ const prune = (rel) => {
8
+ const newRel = {...rel};
9
+ switch (rel.op) {
10
+ case "product":
11
+ newRel.product = rel.product.map(({label, exp}) => ({label, exp: prune(exp)}));
12
+ break;
13
+ case "union":
14
+ newRel.union = rel.union.map(exp => prune(exp));
15
+ break;
16
+ case "comp":
17
+ newRel.comp = rel.comp.reduce((list, exp) => {
18
+ const newExp = prune(exp);
19
+ if (newExp.op != "identity")
20
+ list.push(newExp);
21
+ return list;
22
+ },[]);
23
+ if (newRel.comp.length == 0)
24
+ newRel.op = "identity";
25
+ break;
26
+ case "vector":
27
+ newRel.vector = rel.vector.map(exp => prune(exp));
28
+ break;
29
+ case "caret":
30
+ newRel.caret = prune(rel.caret);
31
+ break;
32
+ case 'code':
33
+ case 'filter':
34
+ newRel.op = "identity";
35
+ default:
36
+ break;
37
+ };
38
+ return newRel;
39
+ };
40
+
41
+ const rel = relDef.def;
42
+ const filters = patterns2filters(relDef.typePatternGraph, ...rel.patterns).map( filter =>
43
+ ({op: "filter", filter: filter}));
44
+ const newRel = prune(rel);
45
+ let resultRel = {...newRel};
46
+ if (newRel.op == "identity")
47
+ return filters[0];
48
+
49
+ if (newRel.op == "comp") {
50
+ resultRel.comp = [ filters[0], ...newRel.comp, filters[1] ];
51
+ return resultRel;
52
+ }
53
+ return {
54
+ op: "comp",
55
+ comp: [filters[0], newRel, filters[1] ]
56
+ };
57
+ };
58
+
59
+
60
+ function theID(alias, rel, scc, name) {
61
+ const sccNames = new Set(scc);
62
+ const auxNames = {[name]: "X0"};
63
+ // rename and remove filters and codes
64
+ const reNameX = (rel) => {
65
+ const newRel = {...rel};
66
+ switch (rel.op) {
67
+ case "product":
68
+ newRel.product = rel.product.map(({label, exp}) => ({label, exp: reNameX(exp)}));
69
+ break;
70
+ case "union":
71
+ newRel.union = rel.union.map(exp => reNameX(exp));
72
+ break;
73
+ case "comp":
74
+ newRel.comp = rel.comp.map(exp => reNameX(exp));
75
+ break;
76
+ case "vector":
77
+ newRel.vector = rel.vector.map(exp => reNameX(exp));
78
+ break;
79
+ case "caret":
80
+ newRel.caret = reNameX(rel.caret);
81
+ break;
82
+ case "ref": {
83
+ const n = rel.ref;
84
+ if (alias[n] != undefined) {
85
+ newRel.ref = alias[n];
86
+ } else if (auxNames[n] != undefined) {
87
+ newRel.ref = auxNames[n];
88
+ } else if (sccNames.has(n)) {
89
+ auxNames[n] = `X${Object.keys(auxNames).length}`;
90
+ newRel.ref = auxNames[n];
91
+ };
92
+ }; break;
93
+ default:
94
+ break;
95
+ };
96
+ return newRel;
97
+ };
98
+
99
+ const newRel = reNameX(rel);
100
+ const resultRelStr = prettyRel(newRel);
101
+ // console.log(` ${name} = ${resultRelStr}`);
102
+ const newName = hash(resultRelStr);
103
+ return newName;
104
+ };
105
+
106
+ function assignCanonicalNames(scc, rels, relAlias) {
107
+ const newAlias = scc.reduce( (newAlias,relName) => {
108
+ const relDef = rels[relName];
109
+ if (relDef.def.op == "ref" && rels[relDef.def.ref] != undefined) {
110
+ // inlining if direct alias to a non built-in relation
111
+ relDef.simplified = simplifyRel(rels[relDef.def.ref]);
112
+ } else {
113
+ relDef.simplified = simplifyRel(relDef);
114
+ }
115
+ newAlias[relName] = theID(relAlias, relDef.simplified, scc, relName);
116
+ return newAlias;
117
+ }, {});
118
+ const newNames = [...new Set(Object.values(newAlias))];
119
+ // console.log(` --- SCC: {${scc.join(",")}} ---`);
120
+
121
+ const sccCanonicalName = newNames.sort().join(":");
122
+ for (let relName in newAlias) {
123
+ if (newNames.length > 1)
124
+ relAlias[relName] = hash(newAlias[relName]+":"+sccCanonicalName);
125
+ else
126
+ relAlias[relName] = newAlias[relName];
127
+ // console.log(` ${relName} -> ${relAlias[relName]}`);
128
+ };
129
+ }
130
+
131
+ function exportRelation(rels, alias, name) {
132
+ const queue = [name];
133
+ const inQueue = { [name]: true };
134
+ const result = {};
135
+ const reName = (rel) => {
136
+ const newRel = {...rel};
137
+ switch (rel.op) {
138
+ case "product":
139
+ newRel.product = rel.product.map(({label, exp}) => ({label, exp: reName(exp)}));
140
+ break;
141
+ case "union":
142
+ newRel.union = rel.union.map(exp => reName(exp));
143
+ break;
144
+ case "comp":
145
+ newRel.comp = rel.comp.map(exp => reName(exp));
146
+ break;
147
+ case "vector":
148
+ newRel.vector = rel.vector.map(exp => reName(exp));
149
+ break;
150
+ case "caret":
151
+ newRel.caret = reName(rel.caret);
152
+ break;
153
+ case "ref": {
154
+ const n = rel.ref;
155
+ if (alias[n] == undefined) // built-in
156
+ return newRel;
157
+ newRel.ref = alias[n];
158
+ if (! inQueue[n]) {
159
+ inQueue[n] = true;
160
+ queue.push(n);
161
+ }
162
+ }; break;
163
+ default:
164
+ break;
165
+ };
166
+ return newRel;
167
+ };
168
+ while (queue.length > 0 ) {
169
+ const name = queue.shift();
170
+ const canonicalName = alias[name];
171
+ result[canonicalName] = {...rels[name], def: reName(rels[name].def), name: name};
172
+ }
173
+ return result;
174
+ }
175
+
176
+ export default { assignCanonicalNames, exportRelation };
177
+ export { assignCanonicalNames, exportRelation };
package/index.mjs CHANGED
@@ -4,19 +4,7 @@ import run from "./run.mjs";
4
4
  import t from "./codes.mjs";
5
5
 
6
6
  function compile(script) {
7
- try {
8
- run.defs = annotate(script);
9
- } catch (e) {
10
- console.error(e.message);
11
- console.error("WARN: Recompiling without type reconciliation due to the type error above.");
12
- const { defs, exp } = parse(script);
13
- const { codes, representatives } = t.finalize(defs.codes);
14
- run.defs = {
15
- rels: {...defs.rels, "__main__": {def: exp}},
16
- codes, representatives
17
- };
18
-
19
- }
7
+ run.defs = annotate(script);
20
8
  return run.bind(null, run.defs.rels.__main__.def);
21
9
  }
22
10
 
@@ -35,9 +23,9 @@ function annotate(script) {
35
23
  const representatives = t.register(defs.codes);
36
24
  const rels = {...defs.rels, "__main__": {def: exp}};
37
25
 
38
- patterns(representatives, rels);
26
+ const relAlias = patterns(representatives, rels);
39
27
 
40
- return {rels, representatives}
28
+ return {rels, representatives, relAlias};
41
29
  }
42
30
  annotate.doc = "Annotate all the script expressions with patterns";
43
31