@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/TypeGraph.mjs ADDED
@@ -0,0 +1,43 @@
1
+ export class TypePatternForest {
2
+ constructor() {
3
+ this.nodes = [];
4
+ this.parent = [];
5
+ }
6
+
7
+ // Find the root of the set containing `x`
8
+ find(x) {
9
+ if (this.nodes[x] == undefined)
10
+ throw new Error(`Node of id='${x}' not found in the forest`);
11
+ let result = x;
12
+ let parent = this.parent[result];
13
+ while (parent != undefined) {
14
+ parent = this.parent[result = parent];
15
+ if (parent == result) {
16
+ console.log("Can happen a loop in the forest? It shouldn't!");
17
+ break;
18
+ }
19
+
20
+ }
21
+ return result;
22
+ }
23
+
24
+ addChildren(parentId, childrenIds) {
25
+ const parent = this.find(parentId);
26
+ childrenIds.forEach(childId => {
27
+ const child = this.find(childId);
28
+ if (this.nodes[child].pattern != 'type')
29
+ this.parent[child] = parent;
30
+ });
31
+ }
32
+
33
+ addNewNode(flatTypePattern, children = []) {
34
+ const that = this;
35
+ const id = this.nodes.length;
36
+ // const node = {...flatTypePattern, _id: id};
37
+ const node = {...flatTypePattern}
38
+ that.nodes.push(node);
39
+ Array.from(new Set(children.map(that.find.bind(that))))
40
+ .forEach(rep => {that.parent[rep] = id});
41
+ return id;
42
+ }
43
+ }
@@ -0,0 +1,251 @@
1
+ import { Graph } from "./Graph.mjs";
2
+ import { unify_two_patterns } from "./unification.mjs";
3
+ import { TypePatternForest } from "./TypeGraph.mjs";
4
+
5
+ function asSet(vector) {
6
+ return Array.from(new Set(vector));
7
+ }
8
+
9
+ const matchAllPattern = {pattern: '(...)', fields: []};
10
+ /*
11
+ $Pattern = <
12
+ string code,
13
+ open? product,
14
+ open? union,
15
+ open? unknown
16
+ >;
17
+ $open? = < {} open, {} closed >;
18
+
19
+ we use the string notation:
20
+ '(...)' | '{...}' | '<...>' | '{}' | '<>' | 'type'
21
+ e.g.:
22
+ {pattern: '<...>'}
23
+ {pattern: 'type', type: code_name}
24
+ */
25
+
26
+ function assertValidPatternNode(pattern, fields = {}) {
27
+ if (pattern.pattern == '()') {
28
+ throw new Error("Closed unknown pattern '()' is not supported.");
29
+ }
30
+ if (pattern.pattern == '(...)' && Object.keys(fields).length !== 0) {
31
+ throw new Error("Unknown-kind pattern '(...)' cannot have fields.");
32
+ }
33
+ }
34
+
35
+ class TypePatternGraph {
36
+ constructor(registerCodeDef, findCode) {
37
+ this.patterns = new TypePatternForest();
38
+ this.edges = []; // an edge at index i is a map {lab: asMapSet([i1,...]), ...}
39
+ // representing `patterns.node[i] --[lab]--> {i1:i1,...}, ...
40
+ this.codeId = { }; // type-name -> index
41
+ this.registerCodeDef = registerCodeDef;
42
+ this.findCode = findCode;
43
+ }
44
+
45
+ turnSingletonPatternsIntoCodes() {
46
+ const singletonPatterns = this.findSingletonPatterns();
47
+ const newCodeDefs= {}
48
+ for(const patternId of singletonPatterns) {
49
+ const pattern = this.get_pattern(patternId);
50
+ switch (pattern.pattern) {
51
+ case '<>':
52
+ case '{}': {
53
+ const code = (pattern.pattern == '<>') ? 'union' : 'product';
54
+ const fieldsWithDest = this.edges[patternId];
55
+ newCodeDefs[`-${patternId}-`] = {
56
+ code: code,
57
+ [code]: Object.keys(fieldsWithDest).reduce((fields, lab) => {
58
+ const auxDests = Object.values(fieldsWithDest[lab]).map(id => this.find(id));
59
+ const destAsMapSet = auxDests.reduce( (mapSet, x) => ({...mapSet, [JSON.stringify(x)]: x}), {});
60
+ const dests = Object.values(destAsMapSet);
61
+ if (dests.length != 1) {
62
+ throw new Error(`Expected one destination for ${lab} in ${patternId}`);
63
+ }
64
+ const destPattern = this.get_pattern(dests[0]);
65
+ fields[lab] = (destPattern.pattern == 'type') ? destPattern.type : `-${dests[0]}-`;
66
+ return fields;
67
+ }, {})
68
+ };
69
+ }; break;
70
+
71
+ default:
72
+ throw new Error(`Unexpected pattern ${JSON.stringify(pattern)}`);
73
+ }
74
+ }
75
+ // - add them all to 'codes'
76
+ const representatives = this.registerCodeDef(newCodeDefs);
77
+
78
+ for( const id of singletonPatterns) {
79
+ this.unify('singleton', id, this.getTypeId(representatives[`-${id}-`]));
80
+ }
81
+ }
82
+
83
+
84
+ get_pattern(id) {
85
+ return this.patterns.nodes[this.find(id)];
86
+ }
87
+
88
+ find(id) {
89
+ return this.patterns.find(id);
90
+ }
91
+
92
+ findSingletonPatterns() {
93
+ const gNodes = this.patterns.nodes.map((x,i) => i).filter(x => this.patterns.parent[x] == undefined);
94
+ const gEdges = [].concat(
95
+ ...gNodes.map(x =>
96
+ [].concat(
97
+ ...Object.values(this.edges[x]).map( asMap =>
98
+ [].concat(...Object.values(asMap).map(y =>
99
+ ({src: x, dst: this.find(y)}))
100
+ )
101
+ )
102
+ )
103
+ )
104
+ );
105
+
106
+ const gEdgesWithoutParrallelEdges = Array.from(new Set(gEdges));
107
+ const gGraph = new Graph(gEdgesWithoutParrallelEdges);
108
+ const queue = gNodes.filter(x =>
109
+ this.patterns.nodes[x].pattern in {'(...)':1,'{...}':1, '<...>':1});
110
+ const excludedSet = new Set(queue);
111
+
112
+ while (queue.length > 0) {
113
+ const x = queue.pop();
114
+ for (const e of gGraph.dst[x] || []) {
115
+ const y = gGraph.edges[e].src;
116
+ if (excludedSet.has(y)) continue;
117
+ excludedSet.add(y);
118
+ queue.push(y);
119
+ }
120
+ }
121
+
122
+ return gNodes.filter(x => !((excludedSet.has(x)) || (this.patterns.nodes[x].pattern == 'type')));
123
+ }
124
+
125
+ clone(roots,targetGraph = this) {
126
+ const result = {}; // mapping from original ids to cloned ids
127
+ const find = (x) => this.find(x);
128
+ let ids = [...roots];
129
+ while (ids.length > 0) {
130
+ const old_id = ids.pop();
131
+ const i = find(old_id);
132
+ if (i in result) {
133
+ result[old_id] = result[i];
134
+ continue;
135
+ }
136
+ const cloned = (pattern => {
137
+ if (pattern.pattern == 'type') return targetGraph.getTypeId(pattern.type);
138
+ return targetGraph.patterns.addNewNode(pattern);
139
+ })(this.patterns.nodes[i]);
140
+ result[i] = cloned;
141
+ result[old_id] = cloned;
142
+ if (this.patterns.nodes[i].pattern == 'type')
143
+ continue;
144
+ const edges = this.edges[i];
145
+ for (const lab in edges) {
146
+ ids = ids.concat(Object.values(edges[lab]));
147
+ }
148
+ }
149
+ for (const i in result) {
150
+ if (i != find(i)) continue;
151
+ if (this.patterns.nodes[i].pattern == 'type')
152
+ continue;
153
+ const edges = this.edges[i];
154
+ const new_id = result[i];
155
+ targetGraph.edges[new_id] = {};
156
+ for (const lab in edges) {
157
+ targetGraph.edges[new_id][lab] = asSet(edges[lab].map(x => result[find(x)]));
158
+ }
159
+ }
160
+ return result;
161
+ }
162
+
163
+ cloneAll(targetGraph = this) {
164
+ return this.clone(this.patterns.nodes.map((x,i) => i), targetGraph);
165
+ }
166
+
167
+ unify_patterns(...patterns) {
168
+ const unifyFn = unify_two_patterns.bind(null, this.findCode);
169
+ return patterns.reduce(unifyFn, {pattern: '(...)', fields: []});
170
+ }
171
+
172
+ unify(rule, ...ids) {
173
+ const find = (x) => this.find(x);
174
+ const reps = Array.from(new Set(ids.map(find)));
175
+ if (reps.length < 2) return false;
176
+ const rep_patters = reps.map(x => {
177
+ const pattern = this.get_pattern(x);
178
+ const fields = Object.keys(this.edges[x] || {});
179
+ return {...pattern, fields: fields};
180
+ });
181
+
182
+ const new_pattern = (() => { try {
183
+ return {...this.unify_patterns(...rep_patters), rule : rule}
184
+ } catch (e) {
185
+ e.message = `Unification rule "${rule}"\n - ${e.message}`;
186
+ throw e;
187
+ } })();
188
+ const new_id = (() => {
189
+ if (new_pattern.pattern == 'type') {
190
+ const id = this.getTypeId(new_pattern.type);
191
+ this.patterns.addChildren(id, reps);
192
+ return id;
193
+ };
194
+ return this.patterns.addNewNode(new_pattern, reps);
195
+ })();
196
+ // console.log(" * new ", JSON.stringify({new_id, new_pattern}));
197
+ // console.log(" ", JSON.stringify(rep_patters));
198
+ this.edges[new_id] = this.edges[new_id] || {};
199
+
200
+ for (const i of reps) {
201
+ const edges = this.edges[i];
202
+ for (const lab in edges) {
203
+ const dests = asSet(edges[lab].map(find));
204
+ this.edges[new_id][lab] = asSet([...(this.edges[new_id][lab] || []), ...dests]);
205
+ }
206
+ }
207
+
208
+ for ( const lab of Object.keys(this.edges[new_id]) ) {
209
+ this.unify(rule+'.', ...this.edges[new_id][lab]);
210
+ }
211
+
212
+ return true;
213
+ }
214
+
215
+ addNewNode(pattern = matchAllPattern, fields = {}) {
216
+ assertValidPatternNode(pattern, fields);
217
+ const id = this.patterns.addNewNode(pattern);
218
+ const find = (x) => this.patterns.find(x);
219
+ this.edges[id] = {};
220
+ for (const [lab,dest] of Object.entries(fields)) {
221
+ this.edges[id][lab] = asSet(dest.map(find));
222
+ }
223
+ return id;
224
+ }
225
+
226
+ getTypeId(type) {
227
+ if (type == undefined) throw new Error("code name cannot be 'undefined'! "); //TODO: remove after testing
228
+ if ( this.codeId[type] == undefined ) {
229
+ const code = this.findCode(type);
230
+ if (code == undefined)
231
+ throw new Error(`Type '${type}' is not defined in codes.`);
232
+ const typeId = this.patterns.addNewNode({pattern: 'type', type: type});
233
+ this.codeId[type] = typeId
234
+ this.edges[typeId] = {};
235
+ for ( const [lab, destType] of Object.entries(code[code.code]) ) {
236
+ const destTypeId = this.getTypeId(destType);
237
+ this.edges[typeId][lab] = asSet([destTypeId]);
238
+ }
239
+ }
240
+ return this.codeId[type];
241
+
242
+ }
243
+
244
+ size() {
245
+ const typeNodes = this.patterns.nodes.filter(x => x.pattern == 'type').length;
246
+ return [this.patterns.nodes.length,typeNodes];
247
+ }
248
+ }
249
+
250
+ export { TypePatternGraph };
251
+ export default { TypePatternGraph };
package/Value.mjs ADDED
@@ -0,0 +1,192 @@
1
+
2
+ // const nameRE = /^[a-zA-Z0-9_][a-zA-Z0-9_?!]*$/;
3
+ const nameRE = /^[a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]*$/;
4
+
5
+ function pLabel(label) {
6
+ return nameRE.test(label) ? `${label}` : `${JSON.stringify(label)}`;
7
+ }
8
+ const getFields = obj => {
9
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
10
+ throw new Error("Not a map!");
11
+ }
12
+ return Object.keys(obj);
13
+ };
14
+
15
+ function fromObject(obj) {
16
+ const fields = getFields(obj);
17
+ if (fields.length === 1) {
18
+ const field = fields[0];
19
+ return new Variant(field, fromObject(obj[field]));
20
+ }
21
+ return new Product(
22
+ fields.reduce( (result, field) => {
23
+ result[field] = fromObject(obj[field]);
24
+ return result;
25
+ }, {})
26
+ );
27
+ };
28
+
29
+ class Value {
30
+ constructor(type, pattern = null) {
31
+ this.type = type;
32
+ this.pattern = pattern;
33
+ }
34
+ toString() {
35
+ return `${this.constructor.name}(type: ${this.type})`;
36
+ }
37
+ toJSON() {
38
+ return { type: this.type };
39
+ }
40
+ }
41
+
42
+ function toVector(m) {
43
+ let vector = [];
44
+ for (let i = 0; i < Object.keys(m).length; i++) {
45
+ if (m[i] === undefined) {
46
+ vector = [];
47
+ break;
48
+ }
49
+ vector.push(m[i]);
50
+ }
51
+ return vector;
52
+ }
53
+
54
+ function cloneSubpattern(pattern, root = 0) {
55
+ if (!pattern || pattern.length === 0) return null;
56
+ const visited = new Map();
57
+ const nodes = [];
58
+
59
+ function visit(nodeId) {
60
+ if (visited.has(nodeId)) return visited.get(nodeId);
61
+ const newId = nodes.length;
62
+ visited.set(nodeId, newId);
63
+ const [kind, edges] = pattern[nodeId];
64
+ nodes.push([kind, []]);
65
+ nodes[newId][1] = edges.map(([label, target]) => [label, visit(target)]);
66
+ return newId;
67
+ }
68
+
69
+ visit(root);
70
+ return nodes;
71
+ }
72
+
73
+ function edgeSubpattern(pattern, label) {
74
+ if (!pattern || pattern.length === 0) return null;
75
+ const [, edges] = pattern[0];
76
+ const edge = edges.find(([edgeLabel]) => edgeLabel === label);
77
+ if (!edge) return null;
78
+ return cloneSubpattern(pattern, edge[1]);
79
+ }
80
+
81
+ function composePattern(kind, entries) {
82
+ if (entries.some(([, childPattern]) => !childPattern)) return null;
83
+ const result = [[kind, []]];
84
+
85
+ for (const [label, childPattern] of entries) {
86
+ const offset = result.length;
87
+ result[0][1].push([label, offset]);
88
+ for (const [childKind, childEdges] of childPattern) {
89
+ result.push([
90
+ childKind,
91
+ childEdges.map(([edgeLabel, target]) => [edgeLabel, target + offset])
92
+ ]);
93
+ }
94
+ }
95
+
96
+ return result;
97
+ }
98
+
99
+ function mergePatterns(declared, observed) {
100
+ if (!declared || declared.length === 0) return observed;
101
+ if (!observed || observed.length === 0) return declared;
102
+ const nodes = [];
103
+ const cloneMemo = new Map();
104
+ const mergeMemo = new Map();
105
+
106
+ function cloneInto(sourceTag, pattern, nodeId) {
107
+ const key = `${sourceTag}:${nodeId}`;
108
+ if (cloneMemo.has(key)) return cloneMemo.get(key);
109
+ const newId = nodes.length;
110
+ cloneMemo.set(key, newId);
111
+ const [kind, edges] = pattern[nodeId];
112
+ nodes.push([kind, []]);
113
+ nodes[newId][1] = edges.map(([label, target]) => [label, cloneInto(sourceTag, pattern, target)]);
114
+ return newId;
115
+ }
116
+
117
+ function visit(declaredId, observedId) {
118
+ if (declaredId == null) return cloneInto("o", observed, observedId);
119
+ if (observedId == null) return cloneInto("d", declared, declaredId);
120
+
121
+ const key = `${declaredId}|${observedId}`;
122
+ if (mergeMemo.has(key)) return mergeMemo.get(key);
123
+
124
+ const [declaredKind, declaredEdges] = declared[declaredId];
125
+ const [observedKind, observedEdges] = observed[observedId];
126
+
127
+ if (declaredKind === "any") return cloneInto("o", observed, observedId);
128
+ if (observedKind === "any") return cloneInto("d", declared, declaredId);
129
+ if (declaredKind !== observedKind) return cloneInto("d", declared, declaredId);
130
+
131
+ const newId = nodes.length;
132
+ mergeMemo.set(key, newId);
133
+ nodes.push([declaredKind, []]);
134
+
135
+ nodes[newId][1] = declaredEdges.map(([label, declaredTarget]) => {
136
+ const observedEdge = observedEdges.find(([edgeLabel]) => edgeLabel === label);
137
+ return [label, visit(declaredTarget, observedEdge ? observedEdge[1] : null)];
138
+ });
139
+
140
+ return newId;
141
+ }
142
+
143
+ visit(0, 0);
144
+ return nodes;
145
+ }
146
+
147
+ function withPattern(value, pattern) {
148
+ if (!pattern) return value;
149
+ if (value.pattern === pattern) return value;
150
+ if (value instanceof Product) return new Product(value.product, pattern);
151
+ if (value instanceof Variant) return new Variant(value.tag, value.value, pattern);
152
+ return value;
153
+ }
154
+
155
+ class Product extends Value {
156
+ constructor(product, pattern = null) {
157
+ super("{}", pattern);
158
+ this.product = product;
159
+ }
160
+
161
+ toString() {
162
+ return `{${Object.entries(this.product).map(([k, v]) => `${JSON.stringify(k)}:${v.toString()}`).join(',')}}`;
163
+ }
164
+
165
+ toJSON() {
166
+ let vector = toVector(this.product);
167
+ if (vector.length > 0) return vector;
168
+ return this.product;
169
+ }
170
+ }
171
+
172
+ class Variant extends Value {
173
+ constructor(tag, value, pattern = null) {
174
+ super("<>", pattern);
175
+ this.tag = tag;
176
+ this.value = value;
177
+ }
178
+
179
+ toString() {
180
+ // return `{${JSON.stringify(this.tag)}:${this.value.toString()}}`;
181
+ return `${this.value.toString()}|${pLabel(this.tag)}`;
182
+ }
183
+
184
+ toJSON() {
185
+ if (this.value instanceof Product && Object.keys(this.value.product).length === 0) {
186
+ return this.tag;
187
+ }
188
+ return {[this.tag]: this.value.toJSON()};
189
+ }
190
+ }
191
+ export { Value, Product, Variant, fromObject, cloneSubpattern, edgeSubpattern, composePattern, mergePatterns, withPattern };
192
+ export default { Value, Product, Variant, fromObject, cloneSubpattern, edgeSubpattern, composePattern, mergePatterns, withPattern };
@@ -0,0 +1,198 @@
1
+ import codes from "./codes.mjs";
2
+
3
+ const unitCode = codes.unitCode;
4
+
5
+ export function augment(rel, rootDef, rels, representatives) {
6
+ try {
7
+ switch (rel.op) {
8
+ case "product":
9
+ rel["product"].forEach(({label, exp}) => {
10
+ augment(exp, rootDef, rels, representatives)
11
+ });
12
+ augmentProduct(rel,rootDef);
13
+ break;
14
+ case "union":
15
+ rel["union"].forEach((exp) => {
16
+ augment(exp,rootDef, rels, representatives);
17
+ });
18
+ augmentUnion(rel,rootDef);
19
+ break;
20
+ case "comp":
21
+ rel["comp"].forEach((exp) => {
22
+ augment(exp,rootDef, rels, representatives);
23
+ });
24
+ augmentComp(rel,rootDef);
25
+ break;
26
+ case "code":
27
+ rel["code"] = representatives[rel.code] || rel.code;
28
+ rel.patterns = [];
29
+ rel.patterns[0] = rootDef.typePatternGraph.getTypeId(rel["code"]);
30
+ rel.patterns[1] = rel.patterns[0];
31
+ break;
32
+ case "ref":
33
+ augmentRef(rel, rootDef, rels);
34
+ break;
35
+ //----------------
36
+ case "identity":
37
+ rel.patterns = [];
38
+ rel.patterns[0] = rel.patterns[1] = rootDef.typePatternGraph.addNewNode();
39
+ break;
40
+ case "dot":
41
+ rel.patterns = [];
42
+ rel.patterns[1] = rootDef.typePatternGraph.addNewNode();
43
+ rel.patterns[0] = rootDef.typePatternGraph.addNewNode({pattern: '{...}', fields: [rel.dot]}, { [rel.dot]: [rel.patterns[1]] });
44
+ break;
45
+ case "div":
46
+ rel.patterns = [];
47
+ rel.patterns[1] = rootDef.typePatternGraph.addNewNode();
48
+ rel.patterns[0] = rootDef.typePatternGraph.addNewNode({pattern: '<...>', fields: [rel.div]}, { [rel.div]: [rel.patterns[1]] });
49
+ //console.log(`AUGMENTED DIV: patterns=${JSON.stringify(rel.patterns.map(x => rootDef.typePatternGraph.get_pattern(x)))}`);
50
+ break;
51
+ case "vid":
52
+ rel.patterns = [];
53
+ rel.patterns[0] = rootDef.typePatternGraph.addNewNode();
54
+ rel.patterns[1] = rootDef.typePatternGraph.addNewNode({pattern: '<...>', fields: [rel.vid]}, { [rel.vid]: [rel.patterns[0]] });
55
+ break;
56
+ case "filter":
57
+ rel.patterns = [];
58
+ rel.patterns[1] = rel.patterns[0] = filterToPattern(rel.filter, rootDef, representatives);
59
+ break;
60
+ default:
61
+ console.error("NOT EXPECTED OP for augmentation:", JSON.stringify(rel, null, 2));
62
+ break;
63
+ }
64
+ } catch (e) {
65
+ e.message = `Type Error in '${rel.op}' (lines ${rel.start?.line}:${rel.start?.column}...${rel.end?.line}:${rel.end?.column})\n - ${e.message}`;
66
+ throw e;
67
+ }
68
+ }
69
+
70
+ function filterToPattern(filter, rootDef, representatives) {
71
+ const context = rootDef.patternVars;
72
+ const getFields = () =>
73
+ Object.keys(filter.fields || {}).reduce( (fields, label) => {
74
+ const patternId = filterToPattern(filter.fields[label], rootDef, representatives);
75
+ fields[label] = [patternId];
76
+ return fields;
77
+ }, {});
78
+ if (filter.name && ! (filter.name in context)) {
79
+ context[filter.name] = rootDef.typePatternGraph.addNewNode();
80
+ }
81
+ let newPatternId = null;
82
+ switch (filter.type) {
83
+ case "name":
84
+ newPatternId = context[filter.name];
85
+ break;
86
+ case "code":
87
+ newPatternId = rootDef.typePatternGraph.getTypeId(representatives[filter.code] || filter.code);
88
+ break;
89
+ case "union":
90
+ newPatternId = rootDef.typePatternGraph.addNewNode(
91
+ {pattern: filter.open ? '<...>' : '<>', fields: Object.keys(filter.fields || {})},
92
+ getFields());
93
+ break;
94
+ case "product":
95
+ newPatternId = rootDef.typePatternGraph.addNewNode(
96
+ {pattern: filter.open ? '{...}' : '{}', fields: Object.keys(filter.fields || {})},
97
+ getFields());
98
+ break;
99
+ default:
100
+ if (!filter.open || Object.keys(filter.fields || {}).length !== 0) {
101
+ throw new Error("Unknown-kind filters must be exactly '(...)'. Use '{}'/'<>' for closed product/union or '{...}'/'<...>' for open product/union.");
102
+ }
103
+ newPatternId = rootDef.typePatternGraph.addNewNode({pattern: '(...)'});
104
+ }
105
+ if (filter.name) {
106
+ rootDef.typePatternGraph.unify(`filter: ${filter.name}`, newPatternId, context[filter.name]);
107
+ }
108
+ return newPatternId;
109
+ }
110
+
111
+ function augmentProduct(rel,rootDef) {
112
+ rel.patterns = [];
113
+ if (rel.product.length == 0) {
114
+ rel.patterns[0] = rootDef.typePatternGraph.addNewNode();
115
+ rel.patterns[1] = rootDef.typePatternGraph.getTypeId(unitCode);
116
+ } else {
117
+ // product constructor %old_i { %exp0_i exp0 %exp0_o field0, ... %expk_i expk %expk_o fieldk } %old_o
118
+ rel.patterns[0] = rootDef.typePatternGraph.addNewNode();
119
+ rootDef.typePatternGraph.unify(
120
+ "product:input",
121
+ rel.patterns[0],
122
+ ...rel.product.map(({exp}) => exp.patterns[0]));
123
+
124
+ rel.patterns[1] = rootDef.typePatternGraph.addNewNode(
125
+ {pattern: '{}', fields: rel.product.map(({label}) => label)},
126
+ rel.product.reduce((edges, {label, exp}) => {
127
+ edges[label] = [ rootDef.typePatternGraph.find(exp.patterns[1])];
128
+ return edges;
129
+ }, {})
130
+ );
131
+ };
132
+ }
133
+
134
+ function augmentUnion(rel,rootDef) {
135
+ rel.patterns = [];
136
+ if (rel.union.length == 0) {
137
+ rel.patterns[0] = rootDef.typePatternGraph.addNewNode();
138
+ rel.patterns[1] = rootDef.typePatternGraph.addNewNode();
139
+ } else {
140
+ rel.patterns[0] = rootDef.typePatternGraph.addNewNode();
141
+ rootDef.typePatternGraph.unify(
142
+ "union:input",
143
+ rel.patterns[0],
144
+ ...rel.union.map(exp => exp.patterns[0]));
145
+
146
+ rel.patterns[1] = rootDef.typePatternGraph.addNewNode();
147
+ rootDef.typePatternGraph.unify(
148
+ "union:output",
149
+ rel.patterns[1],
150
+ ...rel.union.map(exp => exp.patterns[1]));
151
+ }
152
+ }
153
+
154
+ function augmentComp(rel,rootDef) {
155
+ // console.log(`AUGMENTING COMP: ${JSON.stringify(rel.comp)}`);
156
+ rel.patterns = [];
157
+ if (rel.comp.length == 0) {
158
+ rel.patterns[0] = rel.patterns[1] = rootDef.typePatternGraph.addNewNode();
159
+ } else {
160
+ for (let i = 0; i < rel.comp.length - 1; i++) {
161
+ rootDef.typePatternGraph.unify(
162
+ "comp:chain",
163
+ rel.comp[i].patterns[1],
164
+ rel.comp[i+1].patterns[0]
165
+ );
166
+ }
167
+
168
+ rel.patterns[0] = rel.comp[0].patterns[0];
169
+ rel.patterns[1] = rel.comp[rel.comp.length - 1].patterns[1];
170
+ }
171
+ // console.log(`AUGMENTED COMP: patterns=${JSON.stringify(rel.patterns.map(i => {
172
+ // const x = rootDef.typePatternGraph.find(i);
173
+ // return [x,rootDef.typePatternGraph.get_pattern(x)];
174
+ // }))}`);
175
+ }
176
+
177
+ function augmentRef(rel,rootDef,rels) {
178
+ rel.patterns = [];
179
+ if (rel.ref in rels) {
180
+ rel.patterns = [rootDef.typePatternGraph.addNewNode(), rootDef.typePatternGraph.addNewNode()];
181
+ rootDef.varRefs.push( {
182
+ varName: rel.ref,
183
+ inputPatternId: rel.patterns[0],
184
+ outputPatternId: rel.patterns[1],
185
+ start: rel.start,
186
+ end: rel.end
187
+ });
188
+ return;
189
+ }
190
+ // it is built-in
191
+ switch (rel.ref) {
192
+ case "_log!":
193
+ rel.patterns[0] = rel.patterns[1] = rootDef.typePatternGraph.addNewNode();
194
+ break;
195
+ default:
196
+ throw new Error(`No definition found for '${rel.ref}'`);
197
+ }
198
+ }