@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.
- package/Code-derivation-tests/blowup.mjs +3 -3
- package/Code-derivation-tests/bnat.mjs +2 -2
- package/Code-derivation-tests/codec-witness-pattern.mjs +50 -0
- package/Code-derivation-tests/convergence-strategy.mjs +24 -0
- package/Code-derivation-tests/dot.mjs +12 -9
- package/Code-derivation-tests/filter-syntax.mjs +21 -0
- package/Code-derivation-tests/loop.mjs +8 -2
- package/Code-derivation-tests/nat.mjs +1 -1
- package/Code-derivation-tests/not-not.mjs +3 -3
- package/Code-derivation-tests/pattern-envelope.mjs +68 -0
- package/Code-derivation-tests/rlz.mjs +2 -2
- package/{BIG_PICTURE.md → DOCS/BIG_PICTURE.md} +103 -50
- package/DOCS/REPL.md +191 -0
- package/DOCS/book/01-introduction.md +51 -0
- package/DOCS/book/02-syntax-and-values.md +111 -0
- package/DOCS/book/03-types-as-finite-automata.md +156 -0
- package/DOCS/book/04-partial-functions-and-composition.md +146 -0
- package/DOCS/book/05-typing-filters-and-normalization.md +111 -0
- package/DOCS/book.md +54 -0
- package/README.md +204 -508
- package/TypeGraph.mjs +43 -0
- package/TypePatternGraph.mjs +251 -0
- package/Value.mjs +192 -0
- package/augmentation.mjs +198 -0
- package/codecs/BINARY_FORMAT.md +53 -0
- package/codecs/POLYMORPHIC_BINARY_FORMAT.md +303 -0
- package/codecs/README.md +215 -0
- package/codecs/example-pipeline.mjs +149 -0
- package/codecs/ieee.mjs +140 -0
- package/codecs/int.mjs +104 -0
- package/codecs/json-codec.mjs +215 -0
- package/codecs/json.mjs +40 -0
- package/codecs/k-parse.mjs +90 -0
- package/codecs/k-pattern.mjs +75 -0
- package/codecs/k-print.mjs +46 -0
- package/codecs/runtime/codec.mjs +768 -0
- package/codecs/runtime/ieee-pattern.mjs +30 -0
- package/codecs/runtime/pattern-json.mjs +96 -0
- package/codecs/runtime/prefix-codec.mjs +425 -0
- package/codecs/runtime/show-value.mjs +68 -0
- package/codecs/runtime/typeFromValue.mjs +34 -0
- package/codecs/runtime/unicode-string.mjs +220 -0
- package/codecs/show.mjs +41 -0
- package/codecs/string-codec.mjs +80 -0
- package/codecs/unit.mjs +51 -0
- package/codecs/utf16.mjs +66 -0
- package/codecs/utf8.mjs +37 -0
- package/codes.mjs +146 -44
- package/compiler.mjs +111 -0
- package/convergence.mjs +197 -0
- package/core.k +197 -0
- package/export.mjs +22 -32
- package/hash.mjs +29 -31
- package/index.mjs +41 -15
- package/k-vscode/.vscode/launch.json +14 -0
- package/k-vscode/README.md +65 -0
- package/k-vscode/language-configuration.json +42 -0
- package/k-vscode/package.json +57 -0
- package/k-vscode/snippets/k.json +92 -0
- package/k-vscode/syntaxes/k.tmLanguage.json +243 -0
- package/k.mjs +56 -54
- package/object.mjs +517 -0
- package/objects/README.md +38 -0
- package/objects/compile-lib.mjs +42 -0
- package/objects/compile.mjs +42 -0
- package/objects/decompile.mjs +32 -0
- package/package.json +18 -8
- package/parser.jison +27 -46
- package/parser.mjs +68 -100
- package/pretty.mjs +21 -40
- package/repl2.mjs +652 -0
- package/run.mjs +264 -231
- package/symbol-table.mjs +3 -17
- package/test-fingerprint.mjs +7 -7
- package/test-hash-fuzz.mjs +107 -0
- package/test-hash-normalization.mjs +134 -0
- package/test-k-object.mjs +74 -0
- package/test-repl2.mjs +95 -0
- package/test.mjs +45 -70
- package/tests.sh +10 -1
- package/typing.mjs +129 -676
- package/unification.mjs +157 -0
- package/valueIO.mjs +54 -0
- package/valueParser.jison +143 -0
- package/valueParser.mjs +713 -0
- package/Code-derivation-tests/built-in.mjs +0 -19
- package/Code-derivation-tests/vector.mjs +0 -19
- package/Filters/bug.k +0 -3
- package/Filters/composing.k +0 -15
- package/Filters/filter.k +0 -9
- package/TODO.md +0 -53
- package/TYPING.md +0 -365
- package/k-repl.cast +0 -1913
- package/k.cast +0 -618
- package/my-objects.json +0 -6
- package/patterns.mjs +0 -543
- package/repl.mjs +0 -213
- package/test-filters.mjs +0 -45
- package/typing-test.mjs +0 -40
package/run.mjs
CHANGED
|
@@ -1,269 +1,302 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
|
-
import {
|
|
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
|
|
5
|
-
|
|
6
|
+
const builtin = {
|
|
7
|
+
"_log!": (arg) => {
|
|
8
|
+
console.error(`_log!: ${arg}`);
|
|
9
|
+
|
|
10
|
+
return arg;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
12
|
-
|
|
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
|
-
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
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 =
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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)
|
package/test-fingerprint.mjs
CHANGED
|
@@ -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 = {
|
|
9
|
-
$
|
|
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 =
|
|
12
|
+
succ = | succ $nat;
|
|
13
13
|
plus = $pair <
|
|
14
|
-
{.x
|
|
15
|
-
{.x
|
|
14
|
+
{.x/zero stop, .y result} .result,
|
|
15
|
+
{.x/succ x, .y succ y } plus
|
|
16
16
|
> $nat;
|
|
17
|
-
{
|
|
17
|
+
{}|zero succ succ {() x, () y} plus
|
|
18
18
|
`
|
|
19
19
|
].map(function (script) {
|
|
20
20
|
console.log("test-fingerprint:");
|