@fraczak/k 7.2.0 → 8.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/CHANGELOG.md +66 -0
- package/DOCS/BIG_PICTURE.md +54 -7
- package/DOCS/CODECS.md +21 -11
- package/DOCS/CODEC_ARCHITECTURE.md +5 -3
- package/DOCS/DICTIONARY.md +13 -4
- package/DOCS/FILE_FORMATS.md +3 -2
- package/DOCS/JSON_APPROACHES_COMPARISON.md +306 -0
- package/DOCS/NAMED_PATTERNS.md +317 -0
- package/DOCS/PATTERNS.md +59 -11
- package/DOCS/REPL.md +13 -2
- package/DOCS/WEB_REPL_REQUIREMENTS.md +4 -2
- package/Examples/arithmetics.k +22 -17
- package/Examples/bnat.k +21 -11
- package/Examples/buda.k +37 -20
- package/Examples/byte.k +3 -1
- package/Examples/code.k +38 -39
- package/Examples/djson-btrie.k +414 -0
- package/Examples/djson-ptrie.k +663 -0
- package/Examples/djson.k +323 -0
- package/Examples/esc.k +1 -1
- package/Examples/karatsuba-mult.k +16 -13
- package/Examples/list.k +8 -4
- package/Examples/nat.k +17 -11
- package/Examples/poly.k +11 -3
- package/Examples/vhdl_to_k.k +43 -31
- package/README.md +42 -16
- package/browser/repl-browser.mjs +6 -0
- package/browser/tree-view.mjs +35 -16
- package/browser/vfs-data.mjs +15 -7
- package/codecs/README.md +2 -0
- package/codecs/djson-btrie.mjs +560 -0
- package/codecs/djson-ptrie.mjs +587 -0
- package/core.k +79 -115
- package/index.mjs +3 -0
- package/named-patterns.mjs +267 -0
- package/object.mjs +31 -3
- package/package.json +4 -1
- package/parser.jison +68 -5
- package/parser.mjs +111 -60
- package/pretty.mjs +5 -0
- package/repl.mjs +188 -22
- package/scripts/build-repl-html.mjs +68 -4
- package/scripts/perf-djson.mjs +1142 -0
- package/scripts/run-tests.mjs +5 -0
- package/symbol-table.mjs +20 -2
- package/tests/bench-djson-tries.mjs +340 -0
- package/tests/test-codecs.mjs +59 -16
- package/tests/test-named-patterns.mjs +189 -0
- package/tests/test-repl-html.mjs +51 -4
- package/tests/test-repl.mjs +190 -0
package/core.k
CHANGED
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
-- §1. Bits
|
|
10
10
|
---------------------------------------------------------------
|
|
11
11
|
|
|
12
|
-
bit
|
|
12
|
+
bit[] = < {} 0, {} 1 >;
|
|
13
|
+
bits[] = < {} _, B 0, B 1 > = B;
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
bit? = ? bit[];
|
|
16
|
+
bits? = ? bits[];
|
|
15
17
|
|
|
16
18
|
_ = {}|_;
|
|
17
19
|
|
|
@@ -22,52 +24,66 @@ _ = {}|_;
|
|
|
22
24
|
-- §2. Unicode and String
|
|
23
25
|
---------------------------------------------------------------
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
27
|
+
-- 8-bit octet used as a building block for UTF-8 payload pieces.
|
|
28
|
+
byte[] = {
|
|
29
|
+
bit[] 0, bit[] 1, bit[] 2, bit[] 3,
|
|
30
|
+
bit[] 4, bit[] 5, bit[] 6, bit[] 7
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
-- 7-bit ASCII code point payload (U+0000..U+007F).
|
|
34
|
+
ascii[] = {
|
|
35
|
+
bit[] 0, bit[] 1, bit[] 2, bit[] 3,
|
|
36
|
+
bit[] 4, bit[] 5, bit[] 6
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
-- High-byte classes for common BMP ranges, excluding surrogate
|
|
40
|
+
-- and private-use partitions.
|
|
41
|
+
bmp_hi_common[] = <
|
|
42
|
+
{ bit[] 0, bit[] 1, bit[] 2 } h08_0F,
|
|
43
|
+
ascii[] h10_7F,
|
|
44
|
+
ascii[] h80_CF,
|
|
45
|
+
{ bit[] 0, bit[] 1, bit[] 2 } hD0_D7,
|
|
46
|
+
{} hF9,
|
|
47
|
+
{ bit[] 0 } hFA_FB,
|
|
48
|
+
{ bit[] 0 } hFC_FD,
|
|
49
|
+
{ bit[] 0 } hFE_FF
|
|
50
|
+
>;
|
|
51
|
+
|
|
52
|
+
-- High-byte classes for BMP private-use/high-reserved slices.
|
|
53
|
+
bmp_hi_private_use[] = <
|
|
54
|
+
{ bit[] 0, bit[] 1, bit[] 2, bit[] 3 } hE0_EF,
|
|
55
|
+
{ bit[] 0, bit[] 1, bit[] 2 } hF0_F7,
|
|
56
|
+
{} hF8
|
|
57
|
+
>;
|
|
58
|
+
|
|
59
|
+
-- 11-bit payload used for Plane 0 code points U+0080..U+07FF.
|
|
60
|
+
plane0[] = {
|
|
61
|
+
bit[] 0, bit[] 1, bit[] 2, bit[] 3, bit[] 4,
|
|
62
|
+
bit[] 5, bit[] 6, bit[] 7, bit[] 8, bit[] 9, bit[] 10
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
-- Plane selector for supplementary code points in Planes 2..16.
|
|
66
|
+
plane_02_10[] = <
|
|
67
|
+
{ bit[] 0 } p02_03,
|
|
68
|
+
{ bit[] 0, bit[] 1 } p04_07,
|
|
69
|
+
{ bit[] 0, bit[] 1, bit[] 2 } p08_0F,
|
|
70
|
+
{} p10
|
|
71
|
+
>;
|
|
72
|
+
|
|
73
|
+
-- Canonical Unicode scalar-value partition used by string encoding.
|
|
74
|
+
unicode[] = <
|
|
75
|
+
ascii[] ascii,
|
|
76
|
+
{ bmp_hi_common[] hi, byte[] lo } bmp_common,
|
|
77
|
+
{ bmp_hi_private_use[] hi, byte[] lo } bmp_private_use,
|
|
78
|
+
plane0[] plane0,
|
|
79
|
+
{ byte[] mid, byte[] lo } supplementary_plane1,
|
|
80
|
+
{ plane_02_10[] plane, byte[] mid, byte[] lo } supplementary_planes2_16
|
|
81
|
+
>;
|
|
82
|
+
|
|
83
|
+
-- Linked-list string: nil or (unicode car, string cdr).
|
|
84
|
+
string[] = < {} nil, { unicode[] car, S cdr } cons > = S;
|
|
85
|
+
|
|
86
|
+
string? = ? string[];
|
|
71
87
|
|
|
72
88
|
---------------------------------------------------------------
|
|
73
89
|
-- §3. Pattern
|
|
@@ -82,72 +98,20 @@ string? = ? <
|
|
|
82
98
|
-- to decode any value, first decode a pattern under that constant,
|
|
83
99
|
-- then decode the value under the pattern just obtained.
|
|
84
100
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}=Bits7 ascii,
|
|
101
|
-
{
|
|
102
|
-
<
|
|
103
|
-
{ Bit 0, Bit 1, Bit 2 }=Bits3 h08_0F,
|
|
104
|
-
Bits7 h10_7F,
|
|
105
|
-
Bits7 h80_CF,
|
|
106
|
-
Bits3 hD0_D7,
|
|
107
|
-
{} hF9,
|
|
108
|
-
{ Bit 0 }=Bits1 hFA_FB,
|
|
109
|
-
Bits1 hFC_FD,
|
|
110
|
-
Bits1 hFE_FF
|
|
111
|
-
> hi,
|
|
112
|
-
{ Bit 0, Bit 1, Bit 2, Bit 3, Bit 4, Bit 5, Bit 6, Bit 7 }=Bits8 lo
|
|
113
|
-
} bmp_common,
|
|
114
|
-
{
|
|
115
|
-
<
|
|
116
|
-
{ Bit 0, Bit 1, Bit 2, Bit 3 } hE0_EF,
|
|
117
|
-
Bits3 hF0_F7,
|
|
118
|
-
{} hF8
|
|
119
|
-
> hi,
|
|
120
|
-
Bits8 lo
|
|
121
|
-
} bmp_private_use,
|
|
122
|
-
{
|
|
123
|
-
Bit 0, Bit 1, Bit 2, Bit 3, Bit 4, Bit 5, Bit 6, Bit 7, Bit 8, Bit 9, Bit 10
|
|
124
|
-
} plane0,
|
|
125
|
-
{ Bits8 mid, Bits8 lo } supplementary_plane1,
|
|
126
|
-
{
|
|
127
|
-
<
|
|
128
|
-
Bits1 p02_03,
|
|
129
|
-
{ Bit 0, Bit 1 } p04_07,
|
|
130
|
-
Bits3 p08_0F,
|
|
131
|
-
{} p10
|
|
132
|
-
> plane,
|
|
133
|
-
Bits8 mid,
|
|
134
|
-
Bits8 lo
|
|
135
|
-
} supplementary_planes2_16
|
|
136
|
-
> car,
|
|
137
|
-
String cdr
|
|
138
|
-
} cons
|
|
139
|
-
> = String label,
|
|
140
|
-
< Bits 0, Bits 1, {} _ > = Bits target
|
|
141
|
-
} car,
|
|
142
|
-
Edges cdr
|
|
143
|
-
} cons
|
|
144
|
-
> = Edges open-product,
|
|
145
|
-
Edges open-union,
|
|
146
|
-
Edges closed-product,
|
|
147
|
-
Edges closed-union
|
|
148
|
-
> car,
|
|
149
|
-
Pattern cdr
|
|
150
|
-
} cons
|
|
151
|
-
> = Pattern;
|
|
101
|
+
edge[] = { string[] label, bits[] target };
|
|
102
|
+
|
|
103
|
+
edges[] = < {} nil, { edge[] car, E cdr } cons > = E;
|
|
104
|
+
|
|
105
|
+
node[] = <
|
|
106
|
+
{} any,
|
|
107
|
+
edges[] open-product,
|
|
108
|
+
edges[] open-union,
|
|
109
|
+
edges[] closed-product,
|
|
110
|
+
edges[] closed-union
|
|
111
|
+
>;
|
|
112
|
+
|
|
113
|
+
pattern[] = < {} nil, { node[] car, P cdr } cons > = P;
|
|
114
|
+
|
|
115
|
+
pattern? = ? pattern[];
|
|
152
116
|
|
|
153
117
|
pattern?
|
package/index.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { parse } from "./parser.mjs";
|
|
|
2
2
|
import { fromObject, isValue } from "./Value.mjs";
|
|
3
3
|
import { parseValue } from "./valueIO.mjs";
|
|
4
4
|
import { compileTypes } from "./compiler.mjs";
|
|
5
|
+
import { expandPatternsInRels } from "./named-patterns.mjs";
|
|
5
6
|
import run from "./run.mjs";
|
|
6
7
|
import codes from "./codes.mjs";
|
|
7
8
|
|
|
@@ -37,6 +38,8 @@ function annotate(script, options = {}) {
|
|
|
37
38
|
const representatives = codes.register(defs.codes);
|
|
38
39
|
const rels = {...defs.rels, "__main__": {def: exp}};
|
|
39
40
|
|
|
41
|
+
expandPatternsInRels(rels, defs.patterns || {}, options);
|
|
42
|
+
|
|
40
43
|
// Inject library relations into the rels table so @hash refs resolve
|
|
41
44
|
if (options.libraries) {
|
|
42
45
|
for (const lib of options.libraries) {
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// named-patterns.mjs
|
|
2
|
+
// Expansion of named patterns and parameterized type schemes in k ASTs.
|
|
3
|
+
|
|
4
|
+
function cloneFilter(filter) {
|
|
5
|
+
if (!filter || typeof filter !== "object") return filter;
|
|
6
|
+
const copy = { ...filter };
|
|
7
|
+
if (filter.fields) {
|
|
8
|
+
copy.fields = {};
|
|
9
|
+
for (const [k, v] of Object.entries(filter.fields)) {
|
|
10
|
+
copy.fields[k] = cloneFilter(v);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (filter.args) {
|
|
14
|
+
copy.args = filter.args.map(cloneFilter);
|
|
15
|
+
}
|
|
16
|
+
return copy;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function expandFilter(
|
|
20
|
+
filter,
|
|
21
|
+
patterns = {},
|
|
22
|
+
stack = new Set(),
|
|
23
|
+
uniqueIdRef = { val: 0 }
|
|
24
|
+
) {
|
|
25
|
+
if (!filter || typeof filter !== "object") return filter;
|
|
26
|
+
|
|
27
|
+
if (filter.type === "pattern_apply") {
|
|
28
|
+
const patternName = filter.pattern;
|
|
29
|
+
const template = patterns[patternName];
|
|
30
|
+
if (!template) {
|
|
31
|
+
const pos = filter.start
|
|
32
|
+
? ` (lines ${filter.start.line}:${filter.start.column})`
|
|
33
|
+
: "";
|
|
34
|
+
throw new Error(
|
|
35
|
+
`Unknown pattern template '${patternName}[]'${pos}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (stack.has(patternName)) {
|
|
40
|
+
const cycle = [...stack, patternName].join(" -> ");
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Cyclic pattern template dependency detected: ${cycle}`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const expectedArity = template.params.length;
|
|
47
|
+
const actualArity = (filter.args || []).length;
|
|
48
|
+
if (expectedArity !== actualArity) {
|
|
49
|
+
const pos = filter.start
|
|
50
|
+
? ` (lines ${filter.start.line}:${filter.start.column})`
|
|
51
|
+
: "";
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Pattern '${patternName}' expects ${expectedArity} ` +
|
|
54
|
+
`argument${expectedArity === 1 ? "" : "s"}, ` +
|
|
55
|
+
`got ${actualArity}${pos}`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Expand arguments in caller scope first
|
|
60
|
+
const expandedArgs = (filter.args || []).map((arg) =>
|
|
61
|
+
expandFilter(arg, patterns, stack, uniqueIdRef)
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Map internal variables and knots to unique fresh names
|
|
65
|
+
const varSubst = {};
|
|
66
|
+
const rootKnot = template.filter?.name;
|
|
67
|
+
if (rootKnot && !template.params.includes(rootKnot)) {
|
|
68
|
+
varSubst[rootKnot] =
|
|
69
|
+
filter.name || `_${rootKnot}_np${++uniqueIdRef.val}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function collectInternalVars(node) {
|
|
73
|
+
if (!node || typeof node !== "object") return;
|
|
74
|
+
if (node.name && !template.params.includes(node.name)) {
|
|
75
|
+
if (!varSubst[node.name]) {
|
|
76
|
+
varSubst[node.name] = `_${node.name}_np${++uniqueIdRef.val}`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (node.fields) {
|
|
80
|
+
for (const f of Object.values(node.fields)) {
|
|
81
|
+
collectInternalVars(f);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (node.args) {
|
|
85
|
+
for (const a of node.args) {
|
|
86
|
+
collectInternalVars(a);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
collectInternalVars(template.filter);
|
|
91
|
+
|
|
92
|
+
const nextStack = new Set(stack);
|
|
93
|
+
nextStack.add(patternName);
|
|
94
|
+
|
|
95
|
+
function substitute(node) {
|
|
96
|
+
if (!node || typeof node !== "object") return node;
|
|
97
|
+
|
|
98
|
+
if (node.type === "name") {
|
|
99
|
+
const paramIdx = template.params.indexOf(node.name);
|
|
100
|
+
if (paramIdx !== -1) {
|
|
101
|
+
const clonedArg = cloneFilter(expandedArgs[paramIdx]);
|
|
102
|
+
if (node.name && node.name !== template.params[paramIdx]) {
|
|
103
|
+
clonedArg.name = varSubst[node.name] || node.name;
|
|
104
|
+
}
|
|
105
|
+
return clonedArg;
|
|
106
|
+
} else {
|
|
107
|
+
const renamed = varSubst[node.name] || node.name;
|
|
108
|
+
return { ...node, name: renamed };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let knotName = undefined;
|
|
113
|
+
if (node.name) {
|
|
114
|
+
const paramIdx = template.params.indexOf(node.name);
|
|
115
|
+
if (paramIdx === -1) {
|
|
116
|
+
knotName = varSubst[node.name] || node.name;
|
|
117
|
+
} else {
|
|
118
|
+
knotName = node.name;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (node.type === "union" || node.type === "product") {
|
|
123
|
+
const newFields = {};
|
|
124
|
+
for (const [key, fieldFilter] of Object.entries(
|
|
125
|
+
node.fields || {}
|
|
126
|
+
)) {
|
|
127
|
+
newFields[key] = substitute(fieldFilter);
|
|
128
|
+
}
|
|
129
|
+
const res = { ...node, fields: newFields };
|
|
130
|
+
if (knotName !== undefined) res.name = knotName;
|
|
131
|
+
else delete res.name;
|
|
132
|
+
return res;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (node.type === "pattern_apply") {
|
|
136
|
+
const newArgs = (node.args || []).map(substitute);
|
|
137
|
+
const nestedApply = {
|
|
138
|
+
...node,
|
|
139
|
+
args: newArgs,
|
|
140
|
+
};
|
|
141
|
+
if (knotName !== undefined) nestedApply.name = knotName;
|
|
142
|
+
else delete nestedApply.name;
|
|
143
|
+
return expandFilter(
|
|
144
|
+
nestedApply,
|
|
145
|
+
patterns,
|
|
146
|
+
nextStack,
|
|
147
|
+
uniqueIdRef
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const res = { ...node };
|
|
152
|
+
if (knotName !== undefined) res.name = knotName;
|
|
153
|
+
else delete res.name;
|
|
154
|
+
return res;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const instantiated = substitute(template.filter);
|
|
158
|
+
if (filter.name) {
|
|
159
|
+
instantiated.name = filter.name;
|
|
160
|
+
}
|
|
161
|
+
return instantiated;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (filter.type === "union" || filter.type === "product") {
|
|
165
|
+
const newFields = {};
|
|
166
|
+
for (const [key, fieldFilter] of Object.entries(
|
|
167
|
+
filter.fields || {}
|
|
168
|
+
)) {
|
|
169
|
+
newFields[key] = expandFilter(
|
|
170
|
+
fieldFilter,
|
|
171
|
+
patterns,
|
|
172
|
+
stack,
|
|
173
|
+
uniqueIdRef
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
return { ...filter, fields: newFields };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return cloneFilter(filter);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function expandExp(
|
|
183
|
+
exp,
|
|
184
|
+
patterns = {},
|
|
185
|
+
stack = new Set(),
|
|
186
|
+
uniqueIdRef = { val: 0 }
|
|
187
|
+
) {
|
|
188
|
+
if (!exp || typeof exp !== "object") return exp;
|
|
189
|
+
|
|
190
|
+
switch (exp.op) {
|
|
191
|
+
case "filter":
|
|
192
|
+
return {
|
|
193
|
+
...exp,
|
|
194
|
+
filter: expandFilter(exp.filter, patterns, stack, uniqueIdRef),
|
|
195
|
+
};
|
|
196
|
+
case "pattern_apply":
|
|
197
|
+
return {
|
|
198
|
+
op: "filter",
|
|
199
|
+
filter: expandFilter(
|
|
200
|
+
{ type: "pattern_apply", pattern: exp.pattern, args: exp.args },
|
|
201
|
+
patterns,
|
|
202
|
+
stack,
|
|
203
|
+
uniqueIdRef
|
|
204
|
+
),
|
|
205
|
+
start: exp.start,
|
|
206
|
+
end: exp.end,
|
|
207
|
+
};
|
|
208
|
+
case "comp":
|
|
209
|
+
return {
|
|
210
|
+
...exp,
|
|
211
|
+
comp: exp.comp.map((subExp) =>
|
|
212
|
+
expandExp(subExp, patterns, stack, uniqueIdRef)
|
|
213
|
+
),
|
|
214
|
+
};
|
|
215
|
+
case "union":
|
|
216
|
+
return {
|
|
217
|
+
...exp,
|
|
218
|
+
union: exp.union.map((subExp) =>
|
|
219
|
+
expandExp(subExp, patterns, stack, uniqueIdRef)
|
|
220
|
+
),
|
|
221
|
+
};
|
|
222
|
+
case "product":
|
|
223
|
+
return {
|
|
224
|
+
...exp,
|
|
225
|
+
product: exp.product.map(({ label, exp: subExp }) => ({
|
|
226
|
+
label,
|
|
227
|
+
exp: expandExp(subExp, patterns, stack, uniqueIdRef),
|
|
228
|
+
})),
|
|
229
|
+
};
|
|
230
|
+
default:
|
|
231
|
+
return exp;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function expandPatternsInRels(rels, patterns = {}, options = {}) {
|
|
236
|
+
const allPatterns = { ...(options.patterns || {}), ...patterns };
|
|
237
|
+
if (options.libraries) {
|
|
238
|
+
for (const lib of options.libraries) {
|
|
239
|
+
const libPatterns =
|
|
240
|
+
lib.patterns ||
|
|
241
|
+
lib.defs?.patterns ||
|
|
242
|
+
lib.sourceDefs?.patterns ||
|
|
243
|
+
{};
|
|
244
|
+
for (const [name, pat] of Object.entries(libPatterns)) {
|
|
245
|
+
if (!(name in allPatterns)) {
|
|
246
|
+
allPatterns[name] = pat;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const uniqueIdRef = { val: 0 };
|
|
253
|
+
for (const relName of Object.keys(rels)) {
|
|
254
|
+
const rel = rels[relName];
|
|
255
|
+
if (rel?.def) {
|
|
256
|
+
rel.def = expandExp(rel.def, allPatterns, new Set(), uniqueIdRef);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return rels;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export default {
|
|
264
|
+
expandFilter,
|
|
265
|
+
expandExp,
|
|
266
|
+
expandPatternsInRels,
|
|
267
|
+
};
|
package/object.mjs
CHANGED
|
@@ -489,6 +489,24 @@ function compileLibrary(script, options = {}) {
|
|
|
489
489
|
Object.entries(meta).filter(([hash]) => libraryMetaHashes.has(hash))
|
|
490
490
|
);
|
|
491
491
|
|
|
492
|
+
const libPatterns = {};
|
|
493
|
+
if (options.libraries) {
|
|
494
|
+
for (const lib of options.libraries) {
|
|
495
|
+
const lp =
|
|
496
|
+
lib.patterns ||
|
|
497
|
+
lib.defs?.patterns ||
|
|
498
|
+
lib.sourceDefs?.patterns ||
|
|
499
|
+
{};
|
|
500
|
+
Object.assign(libPatterns, lp);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (options.patterns) {
|
|
504
|
+
Object.assign(libPatterns, options.patterns);
|
|
505
|
+
}
|
|
506
|
+
if (annotated.sourceDefs?.patterns) {
|
|
507
|
+
Object.assign(libPatterns, annotated.sourceDefs.patterns);
|
|
508
|
+
}
|
|
509
|
+
|
|
492
510
|
return {
|
|
493
511
|
format: "k-object",
|
|
494
512
|
codes: allCodes,
|
|
@@ -496,6 +514,7 @@ function compileLibrary(script, options = {}) {
|
|
|
496
514
|
relAlias: serialized.relAlias,
|
|
497
515
|
compileStats: serialized.compileStats,
|
|
498
516
|
meta: libMeta,
|
|
517
|
+
patterns: libPatterns,
|
|
499
518
|
main: null
|
|
500
519
|
};
|
|
501
520
|
}
|
|
@@ -506,13 +525,22 @@ function hydrateObject(object) {
|
|
|
506
525
|
}
|
|
507
526
|
codes.load(object.codes);
|
|
508
527
|
const hydratedRels = Object.fromEntries(
|
|
509
|
-
Object.entries(object.rels).map(([name, rel]) => [
|
|
528
|
+
Object.entries(object.rels).map(([name, rel]) => [
|
|
529
|
+
name,
|
|
530
|
+
hydrateRelation(rel)
|
|
531
|
+
])
|
|
510
532
|
);
|
|
511
|
-
return {
|
|
533
|
+
return {
|
|
534
|
+
...object,
|
|
535
|
+
rels: hydratedRels,
|
|
536
|
+
patterns: object.patterns || {}
|
|
537
|
+
};
|
|
512
538
|
}
|
|
513
539
|
|
|
514
540
|
function loadLibrary(object) {
|
|
515
|
-
const hydrated = isHydratedObject(object)
|
|
541
|
+
const hydrated = isHydratedObject(object)
|
|
542
|
+
? object
|
|
543
|
+
: hydrateObject(object);
|
|
516
544
|
if (hydrated.main != null) {
|
|
517
545
|
throw new Error("Expected a library (main: null), got an executable");
|
|
518
546
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fraczak/k",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "k — a language for content-addressable schemas and data transformations over algebraic data types (products and tagged unions); includes runtime, contract derivation, REPL, and codec toolchain",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"perf:poly:pkir": "BACKENDS=pkir node scripts/perf-poly.mjs",
|
|
34
34
|
"perf:poly:llvm-pkir": "BACKENDS=llvm-pkir node scripts/perf-poly.mjs",
|
|
35
35
|
"perf:poly:trace": "node scripts/perf-poly.mjs --trace",
|
|
36
|
+
"perf:djson": "node scripts/perf-djson.mjs",
|
|
36
37
|
"perf:idempotency": "node scripts/benchmark-idempotency.mjs",
|
|
37
38
|
"deps:graph": "node scripts/generate-dependency-graph.mjs",
|
|
38
39
|
"compare": "node harness/cli.mjs",
|
|
@@ -59,6 +60,8 @@
|
|
|
59
60
|
"k-wasm-compile": "backends/wasm/bin/k-wasm-compile.mjs",
|
|
60
61
|
"k-wasm-run": "backends/wasm/bin/k-wasm-run.mjs",
|
|
61
62
|
"k-djson": "codecs/djson.mjs",
|
|
63
|
+
"k-djson-btrie": "codecs/djson-btrie.mjs",
|
|
64
|
+
"k-djson-ptrie": "codecs/djson-ptrie.mjs",
|
|
62
65
|
"k-ieee": "codecs/ieee.mjs",
|
|
63
66
|
"k-int": "codecs/int.mjs",
|
|
64
67
|
"k-json": "codecs/json.mjs",
|