@fraczak/k 5.1.2 → 6.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.
Files changed (99) hide show
  1. package/Code-derivation-tests/blowup.mjs +3 -3
  2. package/Code-derivation-tests/bnat.mjs +2 -2
  3. package/Code-derivation-tests/codec-witness-pattern.mjs +50 -0
  4. package/Code-derivation-tests/convergence-strategy.mjs +24 -0
  5. package/Code-derivation-tests/dot.mjs +12 -9
  6. package/Code-derivation-tests/filter-syntax.mjs +21 -0
  7. package/Code-derivation-tests/loop.mjs +8 -2
  8. package/Code-derivation-tests/nat.mjs +1 -1
  9. package/Code-derivation-tests/not-not.mjs +3 -3
  10. package/Code-derivation-tests/pattern-envelope.mjs +68 -0
  11. package/Code-derivation-tests/rlz.mjs +2 -2
  12. package/{BIG_PICTURE.md → DOCS/BIG_PICTURE.md} +103 -50
  13. package/DOCS/REPL.md +191 -0
  14. package/DOCS/book/01-introduction.md +51 -0
  15. package/DOCS/book/02-syntax-and-values.md +111 -0
  16. package/DOCS/book/03-types-as-finite-automata.md +156 -0
  17. package/DOCS/book/04-partial-functions-and-composition.md +146 -0
  18. package/DOCS/book/05-typing-filters-and-normalization.md +111 -0
  19. package/DOCS/book.md +54 -0
  20. package/README.md +204 -508
  21. package/TypeGraph.mjs +43 -0
  22. package/TypePatternGraph.mjs +251 -0
  23. package/Value.mjs +192 -0
  24. package/augmentation.mjs +198 -0
  25. package/codecs/BINARY_FORMAT.md +53 -0
  26. package/codecs/POLYMORPHIC_BINARY_FORMAT.md +303 -0
  27. package/codecs/README.md +215 -0
  28. package/codecs/example-pipeline.mjs +149 -0
  29. package/codecs/ieee.mjs +140 -0
  30. package/codecs/int.mjs +104 -0
  31. package/codecs/json-codec.mjs +215 -0
  32. package/codecs/json.mjs +40 -0
  33. package/codecs/k-parse.mjs +90 -0
  34. package/codecs/k-pattern.mjs +75 -0
  35. package/codecs/k-print.mjs +46 -0
  36. package/codecs/runtime/codec.mjs +768 -0
  37. package/codecs/runtime/ieee-pattern.mjs +30 -0
  38. package/codecs/runtime/pattern-json.mjs +96 -0
  39. package/codecs/runtime/prefix-codec.mjs +425 -0
  40. package/codecs/runtime/show-value.mjs +68 -0
  41. package/codecs/runtime/typeFromValue.mjs +34 -0
  42. package/codecs/runtime/unicode-string.mjs +220 -0
  43. package/codecs/show.mjs +41 -0
  44. package/codecs/string-codec.mjs +80 -0
  45. package/codecs/unit.mjs +51 -0
  46. package/codecs/utf16.mjs +66 -0
  47. package/codecs/utf8.mjs +37 -0
  48. package/codes.mjs +146 -44
  49. package/compiler.mjs +111 -0
  50. package/convergence.mjs +197 -0
  51. package/core.k +197 -0
  52. package/export.mjs +22 -32
  53. package/hash.mjs +29 -31
  54. package/index.mjs +41 -15
  55. package/k-vscode/.vscode/launch.json +14 -0
  56. package/k-vscode/README.md +65 -0
  57. package/k-vscode/language-configuration.json +42 -0
  58. package/k-vscode/package.json +57 -0
  59. package/k-vscode/snippets/k.json +92 -0
  60. package/k-vscode/syntaxes/k.tmLanguage.json +243 -0
  61. package/k.mjs +56 -54
  62. package/object.mjs +517 -0
  63. package/objects/README.md +38 -0
  64. package/objects/compile-lib.mjs +42 -0
  65. package/objects/compile.mjs +42 -0
  66. package/objects/decompile.mjs +32 -0
  67. package/package.json +18 -8
  68. package/parser.jison +27 -46
  69. package/parser.mjs +68 -100
  70. package/pretty.mjs +21 -40
  71. package/repl2.mjs +652 -0
  72. package/run.mjs +264 -231
  73. package/symbol-table.mjs +3 -17
  74. package/test-fingerprint.mjs +7 -7
  75. package/test-hash-fuzz.mjs +107 -0
  76. package/test-hash-normalization.mjs +134 -0
  77. package/test-k-object.mjs +74 -0
  78. package/test-repl2.mjs +95 -0
  79. package/test.mjs +45 -70
  80. package/tests.sh +10 -1
  81. package/typing.mjs +129 -676
  82. package/unification.mjs +157 -0
  83. package/valueIO.mjs +54 -0
  84. package/valueParser.jison +143 -0
  85. package/valueParser.mjs +713 -0
  86. package/Code-derivation-tests/built-in.mjs +0 -19
  87. package/Code-derivation-tests/vector.mjs +0 -19
  88. package/Filters/bug.k +0 -3
  89. package/Filters/composing.k +0 -15
  90. package/Filters/filter.k +0 -9
  91. package/TODO.md +0 -53
  92. package/TYPING.md +0 -365
  93. package/k-repl.cast +0 -1913
  94. package/k.cast +0 -618
  95. package/my-objects.json +0 -6
  96. package/patterns.mjs +0 -543
  97. package/repl.mjs +0 -213
  98. package/test-filters.mjs +0 -45
  99. package/typing-test.mjs +0 -40
package/run.mjs CHANGED
@@ -1,269 +1,302 @@
1
1
  import assert from "assert";
2
- import { find } from "./codes.mjs";
2
+ import { Product, Variant, edgeSubpattern, composePattern, withPattern } from "./Value.mjs"
3
+ import { exportPatternGraph, intersectPropertyListPatterns } from "./codecs/runtime/codec.mjs";
4
+ import { patternToPropertyList } from "./codecs/runtime/pattern-json.mjs";
3
5
 
4
- const modulo = (a, b) => ((+a % (b = +b)) + b) % b;
5
- const valid = (x) => (isNaN(x) ? undefined : x);
6
+ const builtin = {
7
+ "_log!": (arg) => {
8
+ console.error(`_log!: ${arg}`);
9
+
10
+ return arg;
11
+ }
12
+ };
6
13
 
7
- function isOpen(x) {
8
- return (Array.isArray(x) && x.open);
14
+ const codes = { };
15
+ const staticPatternCache = new WeakMap();
16
+ const intersectionCache = new Map();
17
+ const singletonCheckCache = new WeakMap();
18
+ const patternPairCache = new WeakMap();
19
+ const NULL_INTERSECTION = {};
20
+
21
+ function staticPattern(typePatternGraph, exp, index) {
22
+ if (!typePatternGraph || !exp.patterns) return null;
23
+ return exportedPattern(typePatternGraph, exp.patterns[index]);
24
+ }
25
+
26
+ function outputPattern(typePatternGraph, exp) {
27
+ return staticPattern(typePatternGraph, exp, 1);
9
28
  }
10
29
 
11
- function isClosed(x) {
12
- return (Array.isArray(x) && !x.open);
30
+ function isSingletonPattern(pattern) {
31
+ if (singletonCheckCache.has(pattern)) return singletonCheckCache.get(pattern);
32
+ const result = pattern.every(([kind]) => kind === "closed-product" || kind === "closed-union");
33
+ singletonCheckCache.set(pattern, result);
34
+ return result;
13
35
  }
14
36
 
15
- Array.prototype.toJSON = function () {
16
- if (this.open) {
17
- // throw new Error(`Cannot serialize open vector: ${JSON.stringify([...this])}.`);
18
- return {"OPEN VECTOR": [...this]};
37
+ function intersectPatterns(left, right) {
38
+ if (!left || left.length === 0) return right;
39
+ if (!right || right.length === 0) return left;
40
+ if (left === right) return left;
41
+ if (left[0]?.[0] === "any") return right;
42
+ if (right[0]?.[0] === "any") return left;
43
+
44
+ const cached = patternPairCache.get(left)?.get(right);
45
+ if (cached !== undefined) return cached === NULL_INTERSECTION ? null : cached;
46
+
47
+ function cache(result) {
48
+ let rightMap = patternPairCache.get(left);
49
+ if (!rightMap) {
50
+ rightMap = new WeakMap();
51
+ patternPairCache.set(left, rightMap);
52
+ }
53
+ rightMap.set(right, result || NULL_INTERSECTION);
54
+ return result;
19
55
  }
20
- return this;
21
- };
22
56
 
23
- function closeVector(val) {
24
- if (isOpen(val)) {
25
- return [...val];
57
+ if (isSingletonPattern(left) || isSingletonPattern(right)) {
58
+ try {
59
+ return cache(intersectPropertyListPatterns(left, right));
60
+ } catch {
61
+ return cache(null);
62
+ }
63
+ }
64
+
65
+ const leftKey = JSON.stringify(left);
66
+ const rightKey = JSON.stringify(right);
67
+ if (leftKey === rightKey) return left;
68
+
69
+ const key = `${leftKey}\n${rightKey}`;
70
+ if (intersectionCache.has(key)) return cache(intersectionCache.get(key));
71
+
72
+ try {
73
+ const pattern = intersectPropertyListPatterns(left, right);
74
+ intersectionCache.set(key, pattern);
75
+ return cache(pattern);
76
+ } catch {
77
+ intersectionCache.set(key, null);
78
+ return cache(null);
26
79
  }
27
- console.error("Can close only an open vector.");
28
- return val;
29
80
  }
30
81
 
31
- const builtin = {
32
- "_log!": (arg) => {
33
- console.error(`_log!: ${JSON.stringify(arg)}`);
34
- return arg;
35
- },
36
- GT: (args) => {
37
- const [last, ...rest] = args;
38
- const [ok, _] = rest.reduce(
39
- ([ok, last], x) => [ok && last > x, x],
40
- [true, last]
82
+ function exportedPattern(typePatternGraph, patternId) {
83
+ let graphCache = staticPatternCache.get(typePatternGraph);
84
+ if (!graphCache) {
85
+ graphCache = new Map();
86
+ staticPatternCache.set(typePatternGraph, graphCache);
87
+ }
88
+ patternId = typePatternGraph.find(patternId);
89
+ if (!graphCache.has(patternId)) {
90
+ graphCache.set(
91
+ patternId,
92
+ patternToPropertyList(exportPatternGraph(typePatternGraph, patternId))
41
93
  );
42
- if (ok) return args;
43
- },
44
- EQ: (args) => {
45
- const [first, ...rest] = args;
46
- const ok = rest.reduce((ok, x) => ok && first === x, true);
47
- if (ok) return args;
48
- },
49
- PLUS: (args) => valid(args.reduce((res, x) => res + x, 0)),
50
- TIMES: (args) => valid(args.reduce((res, x) => res * x, 1)),
51
- DIV: ([x, y]) => {
52
- const div = Math.floor(x / y);
53
- const rem = modulo(x, y);
54
- if (x === div * y + rem) return { div, rem };
55
- },
56
- FDIV: ([x, y]) => x / y,
57
- CONCAT: (strs) => strs.join(""),
58
- toVEC: (str) => [...`${str}`],
59
- true: () => true,
60
- false: () => false,
61
- null: () => null,
62
- toJSON: (x) => JSON.stringify(x),
63
- fromJSON: (x) => JSON.parse(x),
64
- CONS: ({car, cdr}) => { try { return [car, ...cdr]; } catch (e) { return undefined; } },
65
- SNOC: (x) => (x.length > 0 ? {car: x[0], cdr: x.slice(1)} : undefined),
66
- toDateMsec: (x) => new Date(x).getTime(),
67
- toDateStr: (x) => new Date(x).toISOString(),
68
- };
94
+ }
95
+ return graphCache.get(patternId);
96
+ }
69
97
 
70
- const codes = {
71
- "@int": (x) => Number.isInteger(x),
72
- "@string": (x) => x instanceof String || "string" === typeof x,
73
- "@bool": (x) => x === true || x === false,
74
- };
98
+ function expLocation(exp) {
99
+ return exp.start ? ` (lines ${exp.start.line}:${exp.start.column}...${exp.end?.line}:${exp.end?.column})` : "";
100
+ }
101
+
102
+ function patternPreview(pattern) {
103
+ return JSON.stringify(pattern);
104
+ }
105
+
106
+ function constrainInput(value, typePatternGraph, exp) {
107
+ const constraint = staticPattern(typePatternGraph, exp, 0);
108
+ return constrainWithPattern(value, constraint, exp);
109
+ }
110
+
111
+ function constrainWithPattern(value, constraint, exp) {
112
+ if (!constraint) return value;
113
+ const pattern = intersectPatterns(constraint, value.pattern);
114
+ if (!pattern) {
115
+ throw new TypeError(
116
+ `Type Error in '${exp.op}'${expLocation(exp)}\n` +
117
+ ` - Value envelope does not intersect expression input pattern.\n` +
118
+ ` - input pattern: ${patternPreview(constraint)}\n` +
119
+ ` - value envelope: ${patternPreview(value.pattern)}`
120
+ );
121
+ }
122
+ return withPattern(value, pattern);
123
+ }
124
+
125
+ function compiledExp(findCode, exp, typePatternGraph) {
126
+ const cached = exp._compiledRun;
127
+ if (cached?.findCode === findCode && cached?.typePatternGraph === typePatternGraph && cached?.defs === run.defs) {
128
+ return cached.fn;
129
+ }
75
130
 
76
- function verify(code, value) {
131
+ const compiled = {
132
+ findCode,
133
+ typePatternGraph,
134
+ defs: run.defs,
135
+ target: null,
136
+ fn(value) {
137
+ return compiled.target(value);
138
+ }
139
+ };
140
+ exp._compiledRun = compiled;
141
+
142
+ const inputPattern = staticPattern(typePatternGraph, exp, 0);
143
+ const staticOutputPattern = outputPattern(typePatternGraph, exp);
144
+ const constrain = (value) => {
145
+ if (value === undefined) return undefined;
146
+ return constrainWithPattern(value, inputPattern, exp);
147
+ };
148
+ const defined = (value) => value;
149
+
150
+ let fn;
151
+ switch (exp.op) {
152
+ case "code":
153
+ fn = (value) => {
154
+ value = constrain(value);
155
+ if (value === undefined) return undefined;
156
+ return verify(findCode, exp.code, value) ? value : undefined;
157
+ };
158
+ break;
159
+ case "identity":
160
+ fn = defined;
161
+ break;
162
+ case "filter":
163
+ fn = constrain;
164
+ break;
165
+ case "ref":
166
+ {
167
+ const defn = run.defs.rels[exp.ref];
168
+ if (defn != undefined) {
169
+ const refFn = compiledExp(findCode, defn.def, defn.typePatternGraph);
170
+ fn = (value) => {
171
+ return value === undefined ? undefined : refFn(value);
172
+ };
173
+ } else {
174
+ const builtin_func = builtin[exp.ref];
175
+ if (builtin_func != null) {
176
+ fn = (value) => {
177
+ value = constrain(value);
178
+ return value === undefined ? undefined : builtin_func(value);
179
+ };
180
+ } else {
181
+ fn = () => {
182
+ throw(`Unknown ref: '${exp.ref}'`);
183
+ };
184
+ }
185
+ }
186
+ }
187
+ break;
188
+ case "dot":
189
+ fn = (value) => {
190
+ if (value === undefined) return undefined;
191
+ return withPattern(value.product[exp.dot], staticOutputPattern || edgeSubpattern(value.pattern, exp.dot));
192
+ };
193
+ break;
194
+ case "div":
195
+ fn = (value) => {
196
+ if (value === undefined || value.tag !== exp.div) return undefined;
197
+ return withPattern(value.value, staticOutputPattern || edgeSubpattern(value.pattern, exp.div));
198
+ };
199
+ break;
200
+ case "comp": {
201
+ const parts = exp.comp.map((part) => compiledExp(findCode, part, typePatternGraph));
202
+ fn = (value) => {
203
+ value = constrain(value);
204
+ for (let i = 0, len = parts.length; i < len; i++) {
205
+ value = parts[i](value);
206
+ if (value === undefined) return undefined;
207
+ }
208
+ return value;
209
+ };
210
+ break;
211
+ }
212
+ case "union": {
213
+ const parts = exp.union.map((part) => compiledExp(findCode, part, typePatternGraph));
214
+ fn = (value) => {
215
+ if (value === undefined) return undefined;
216
+ for (let i = 0, len = parts.length; i < len; i++) {
217
+ const result = parts[i](value);
218
+ if (result !== undefined) return result;
219
+ }
220
+ return undefined;
221
+ };
222
+ break;
223
+ }
224
+ case "product": {
225
+ const labels = exp.product.map(({ label }) => label);
226
+ const fieldFns = exp.product.map(({ exp: e }) => compiledExp(findCode, e, typePatternGraph));
227
+ if (staticOutputPattern) {
228
+ fn = (value) => {
229
+ if (value === undefined) return undefined;
230
+ const result = {};
231
+ for (let i = 0, len = labels.length; i < len; i++) {
232
+ const r = fieldFns[i](value);
233
+ if (r === undefined) return undefined;
234
+ result[labels[i]] = r;
235
+ }
236
+ return new Product(result, staticOutputPattern);
237
+ };
238
+ } else {
239
+ fn = (value) => {
240
+ if (value === undefined) return undefined;
241
+ const result = {};
242
+ const patternEntries = [];
243
+ for (let i = 0, len = labels.length; i < len; i++) {
244
+ const r = fieldFns[i](value);
245
+ if (r === undefined) return undefined;
246
+ const label = labels[i];
247
+ result[label] = r;
248
+ patternEntries.push([label, r.pattern]);
249
+ }
250
+ return new Product(result, composePattern("closed-product", patternEntries));
251
+ };
252
+ }
253
+ break;
254
+ }
255
+ case "vid":
256
+ fn = (value) => {
257
+ if (value === undefined) return undefined;
258
+ return new Variant(exp.vid, value, composePattern("open-union", [[exp.vid, value.pattern]]));
259
+ };
260
+ break;
261
+ default:
262
+ assert(false,`Unknown operation: '${exp.op}'`);
263
+ }
264
+
265
+ compiled.target = fn;
266
+ return compiled.fn;
267
+ }
268
+
269
+ function verify(findCode, code, value) {
77
270
  "use strict";
78
271
  if (code == null) return false;
79
- code = find(code);
272
+ code = findCode(code);
80
273
  switch (code.code) {
81
- case "vector":
82
- if (!Array.isArray(value)) return false;
83
- return value.every((x) => verify(code.vector, x));
84
274
  case "product":
85
- if ("object" !== typeof value) return false;
275
+ if (! (value instanceof Product)) return false;
86
276
  else {
87
- const fields = Object.keys(value);
277
+ const fields = Object.keys(value.product);
88
278
  if (fields.length !== Object.keys(code.product).length) return false;
89
279
  return fields.every((label) =>
90
- verify(code.product[label], value[label])
280
+ verify(findCode, code.product[label], value.product[label])
91
281
  );
92
282
  }
93
283
  case "union":
94
- if ("object" !== typeof value) return false;
284
+ if (! (value instanceof Product)) return false;
95
285
  else {
96
- const fields = Object.keys(value);
286
+ const fields = Object.keys(value.product);
97
287
  if (fields.length !== 1) return false;
98
- return verify(code.union[fields[0]], value[fields[0]]);
288
+ return verify(findCode, code.union[fields[0]], value.product[fields[0]]);
99
289
  }
100
290
  default:
101
291
  return codes[code.code](value);
102
292
  }
103
293
  }
104
294
 
105
- function run(exp, value) {
106
- "use strict";
107
- if (value === undefined) return;
108
- while (true) {
109
- if (isOpen(value)) {
110
- if (exp.op === "caret2") return [...value];
111
- const result = [];
112
- result.open = true
113
- for (const v of value) {
114
- const r = run(exp, v);
115
- if (r !== undefined) result.push(r);
116
- }
117
- return result;
118
- }
119
- switch (exp.op) {
120
- case "code":
121
- if (verify(exp.code, value)) {
122
- return value;
123
- }
124
- return;
125
- case "identity":
126
- return value;
127
- case "str":
128
- case "int":
129
- return exp[exp.op];
130
- case "ref": {
131
- const defn = run.defs.rels[exp.ref];
132
- if (defn != undefined) {
133
- exp = defn.def;
134
- continue;
135
- }
136
- const builtin_func = builtin[exp.ref];
137
- if (builtin_func != null) {
138
- return builtin_func(value);
139
- }
140
- throw(`Unknown ref: '${exp.ref}'`);
141
- }
142
- case "dot":
143
- // a hack to allow something like 'null . null' or '0 . 0' to work by returning unit
144
- if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
145
- if (`${value}` === `${exp.dot}`) return {};
146
- return;
147
- }
148
- return value[exp.dot];
149
- case "pipe": {
150
- assert(isClosed(value), `PIPE (|): Only a regular vector value can be "open".`);
151
- const result = [...value];
152
- result.open = true;
153
- return result;
154
- }
155
- case "comp":
156
- for (let i = 0, len = exp.comp.length - 1; i < len; i++) {
157
- const result = run(exp.comp[i], value);
158
- if (result === undefined) return;
159
- value = result;
160
- }
161
- exp = exp.comp[exp.comp.length - 1];
162
- continue;
163
- case "union":
164
- if (exp.union.length === 0) return;
165
- for (let i = 0, len = exp.union.length -1; i < len; i++) {
166
- const result = run(exp.union[i], value);
167
- if (result !== undefined) {
168
- return result;
169
- }
170
- }
171
- exp = exp.union[exp.union.length - 1];
172
- continue;
173
- case "vector": {
174
- let result = [];
175
- let open = false;
176
- for (let i = 0, len = exp.vector.length; i < len; i++) {
177
- const r = run(exp.vector[i], value);
178
- if (r === undefined) return;
179
- if (open) {
180
- if (isOpen(r)) {
181
- const newResult = [];
182
- newResult.open = true;
183
- for (const x of result) {
184
- for (const y of r) {
185
- newResult.push([...x, y]);
186
- }
187
- }
188
- result = newResult;
189
- } else {
190
- for (const x of result) x.push(r);
191
- }
192
- } else {
193
- if (isOpen(r)) {
194
- open = true;
195
- const newResult = [];
196
- newResult.open = true;
197
- for (const x of r) {
198
- newResult.push([...result, x]);
199
- }
200
- result = newResult;
201
- } else {
202
- result.push(r);
203
- }
204
- }
205
- }
206
- return result;
207
- }
208
- case "product": {
209
- let result = {};
210
- let open = false;
211
- for (let i = 0, len = exp.product.length; i < len; i++) {
212
- const { label, exp: e } = exp.product[i];
213
- const r = run(e, value);
214
- if (r === undefined) return;
215
- if (open) {
216
- if (isOpen(r)) {
217
- let newResult = [];
218
- newResult.open = true;
219
- for (const v of r) {
220
- for (const x of result) {
221
- newResult.push({...x, [label]: v});
222
- }
223
- }
224
- result = newResult;
225
- } else {
226
- let newResult = [];
227
- newResult.open = true;
228
- for (const x of result) {
229
- newResult.push({...x, [label]: r});
230
- }
231
- result = newResult;
232
- }
233
- } else {
234
- if (isOpen(r)) {
235
- open = true;
236
- let newResult = [];
237
- newResult.open = true;
238
- for (const v of r.values()) {
239
- newResult.push({...result, [label]: v});
240
- }
241
- result = newResult;
242
- } else {
243
- result[label] = r;
244
- }
245
- }
246
- }
247
- return result
248
- }
249
- case "caret": {
250
- const result = run(exp.caret, value);
251
- // assert(isOpen(result), "CARET (^): Only an 'open' vector can be closed.");
252
- if (! isOpen(result))
253
- throw new Error(`Type Error (line: ${exp.end?.line}:${exp.end?.column}): CARET (^): Only 'unboxed' values can be 'boxed'.`)
254
- return [...result];
255
- }
256
- case "filter": {
257
- return value;
258
- }
259
- default:
260
- assert(false,`Unknown operation: '${exp.op}'`);
261
-
262
- }
263
- };
295
+ function run(findCode, exp, value, typePatternGraph) {
296
+ return compiledExp(findCode, exp, typePatternGraph || null)(value);
264
297
  }
265
298
 
266
299
  run.builtin = builtin;
267
300
 
268
301
  export default run;
269
- export { run , closeVector };
302
+ export { run };
package/symbol-table.mjs CHANGED
@@ -9,19 +9,9 @@ function is_identity_rel(rel) {
9
9
  }
10
10
 
11
11
  function is_constant_rel(rel) {
12
- switch (rel.op) {
13
- case "int":
14
- case "str":
15
- return true;
16
- case "vector":
17
- return Object.values(rel[rel.op]).every(is_constant_rel);
18
- case "product":
19
- return Object.values(rel[rel.op]).every(({ exp }) =>
20
- is_constant_rel(exp)
21
- );
22
- default:
23
- return false;
24
- }
12
+ if (rel.op == "product")
13
+ return Object.values(rel[rel.op]).every(({ exp }) => is_constant_rel(exp));
14
+ return false;
25
15
  }
26
16
 
27
17
  function is_empty_rel(rel) {
@@ -31,14 +21,10 @@ function is_empty_rel(rel) {
31
21
  function is_full_rel(rel) {
32
22
  if (is_constant_rel(rel)) return true;
33
23
  switch (rel.op) {
34
- case "int":
35
- case "str":
36
24
  case "identity":
37
25
  return true;
38
26
  case "comp":
39
27
  return rel.comp.every(is_full_rel);
40
- case "vector":
41
- return Object.values(rel[rel.op]).every(is_full_rel);
42
28
  case "product":
43
29
  return Object.values(rel[rel.op]).every(({ exp }) =>
44
30
  is_full_rel(exp)
@@ -3,18 +3,18 @@ import { encodeCodeToString, find } from './codes.mjs';
3
3
  import hash from './hash.mjs';
4
4
  [
5
5
  `
6
+ $bits = < bits 0, bits 1, {} _ >;
6
7
  $nat = < {} zero, nat succ>;
7
8
  $pair = {nat x, nat y};
8
- $b = {@int"x", @bool y};
9
- $vector = [@int];
10
- $tree = <{nat value, tree left, tree right} binary, nat leaf, {nat value, tree tree} unary, [tree] list_of_trees>;
9
+ $b = { bits"x", bits y};
10
+ $tree = < {nat value, tree left, tree right} binary, nat leaf, {nat value, tree tree} unary >;
11
11
 
12
- succ = { $nat succ} $nat;
12
+ succ = | succ $nat;
13
13
  plus = $pair <
14
- {.x.zero stop, .y result} .result,
15
- {.x.succ x, .y succ y } plus
14
+ {.x/zero stop, .y result} .result,
15
+ {.x/succ x, .y succ y } plus
16
16
  > $nat;
17
- {{} zero} succ succ {() x, () y} plus
17
+ {}|zero succ succ {() x, () y} plus
18
18
  `
19
19
  ].map(function (script) {
20
20
  console.log("test-fingerprint:");