@fraczak/k 7.1.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 +99 -0
- package/DOCS/BIG_PICTURE.md +54 -7
- package/DOCS/CODECS.md +47 -2
- package/DOCS/CODEC_ARCHITECTURE.md +14 -5
- 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 +24 -5
- 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 -15
- package/Value.mjs +28 -3
- package/backend-api.mjs +5 -1
- package/browser/repl-browser.mjs +6 -0
- package/browser/tree-view.mjs +82 -24
- package/browser/vfs-data.mjs +21 -12
- package/codecs/README.md +3 -0
- package/codecs/djson-btrie.mjs +560 -0
- package/codecs/djson-ptrie.mjs +587 -0
- package/codecs/djson.mjs +270 -0
- package/codecs/int.mjs +2 -1
- package/codecs/json.mjs +7 -2
- package/codecs/k-parse.mjs +7 -1
- package/codecs/k-print.mjs +4 -0
- package/codecs/runtime/codec-sdk.mjs +16 -2
- package/codecs/runtime/pattern-json.mjs +80 -1
- package/codecs/runtime/prefix-codec.mjs +629 -67
- package/codecs/runtime/show-value.mjs +93 -51
- package/codecs/runtime/unicode-string.mjs +29 -6
- package/codecs/show.mjs +4 -0
- package/codecs/utf16.mjs +2 -1
- package/core.k +79 -115
- package/index.mjs +3 -0
- package/named-patterns.mjs +267 -0
- package/object.mjs +31 -3
- package/package.json +5 -1
- package/parser.jison +68 -5
- package/parser.mjs +111 -60
- package/pretty.mjs +5 -0
- package/repl.mjs +245 -28
- package/scripts/build-repl-html.mjs +76 -5
- 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 +211 -0
- package/tests/test-named-patterns.mjs +189 -0
- package/tests/test-repl-html.mjs +52 -4
- package/tests/test-repl.mjs +223 -0
|
@@ -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",
|
|
@@ -58,6 +59,9 @@
|
|
|
58
59
|
"k-wasm": "backends/wasm/bin/k-wasm.mjs",
|
|
59
60
|
"k-wasm-compile": "backends/wasm/bin/k-wasm-compile.mjs",
|
|
60
61
|
"k-wasm-run": "backends/wasm/bin/k-wasm-run.mjs",
|
|
62
|
+
"k-djson": "codecs/djson.mjs",
|
|
63
|
+
"k-djson-btrie": "codecs/djson-btrie.mjs",
|
|
64
|
+
"k-djson-ptrie": "codecs/djson-ptrie.mjs",
|
|
61
65
|
"k-ieee": "codecs/ieee.mjs",
|
|
62
66
|
"k-int": "codecs/int.mjs",
|
|
63
67
|
"k-json": "codecs/json.mjs",
|
package/parser.jison
CHANGED
|
@@ -49,9 +49,11 @@ function fromEscString(escString) {
|
|
|
49
49
|
"<" return 'LA';
|
|
50
50
|
"{" return 'LC';
|
|
51
51
|
"(" return 'LP';
|
|
52
|
+
"[" return 'LB';
|
|
52
53
|
">" return 'RA';
|
|
53
54
|
"}" return 'RC';
|
|
54
55
|
")" return 'RP';
|
|
56
|
+
"]" return 'RB';
|
|
55
57
|
"=" return 'EQ';
|
|
56
58
|
"..." return 'DOTS';
|
|
57
59
|
"." return 'DOT';
|
|
@@ -71,7 +73,7 @@ function fromEscString(escString) {
|
|
|
71
73
|
/lex
|
|
72
74
|
|
|
73
75
|
%token NAME STRING
|
|
74
|
-
%token LA LC LP RA RP
|
|
76
|
+
%token LA LC LP LB RA RC RP RB EQ DOT COMMA SC COL AT QMARK DOTS DIV VID
|
|
75
77
|
%token INCREMENTAL
|
|
76
78
|
%token EOF
|
|
77
79
|
|
|
@@ -85,9 +87,11 @@ at: AT { $$ = getToken(yytext,yy,_$); };
|
|
|
85
87
|
la: LA { $$ = getToken(yytext,yy,_$); };
|
|
86
88
|
lc: LC { $$ = getToken(yytext,yy,_$); };
|
|
87
89
|
lp: LP { $$ = getToken(yytext,yy,_$); };
|
|
90
|
+
lb: LB { $$ = getToken(yytext,yy,_$); };
|
|
88
91
|
ra: RA { $$ = getToken(yytext,yy,_$); };
|
|
89
92
|
rc: RC { $$ = getToken(yytext,yy,_$); };
|
|
90
93
|
rp: RP { $$ = getToken(yytext,yy,_$); };
|
|
94
|
+
rb: RB { $$ = getToken(yytext,yy,_$); };
|
|
91
95
|
eq: EQ { $$ = getToken(yytext,yy,_$); };
|
|
92
96
|
dots: DOTS { $$ = getToken(yytext,yy,_$); };
|
|
93
97
|
dot: DOT { $$ = getToken(yytext,yy,_$); };
|
|
@@ -100,9 +104,14 @@ qmark: QMARK { $$ = getToken(yytext,yy,_$); };
|
|
|
100
104
|
incremental: INCREMENTAL { $$ = getToken(yytext,yy,_$); };
|
|
101
105
|
|
|
102
106
|
input_with_eof: initialize_symbol_table defs comp EOF {
|
|
103
|
-
const result = {
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
const result = {
|
|
108
|
+
defs: {
|
|
109
|
+
rels: s.rels,
|
|
110
|
+
codes: s.codes,
|
|
111
|
+
patterns: s.patterns
|
|
112
|
+
},
|
|
113
|
+
exp: $3
|
|
114
|
+
};
|
|
106
115
|
return result;
|
|
107
116
|
};
|
|
108
117
|
|
|
@@ -113,17 +122,71 @@ initialize_symbol_table
|
|
|
113
122
|
|
|
114
123
|
defs: { }
|
|
115
124
|
| defs name eq comp sc { s.add_rel($2.value,$4); }
|
|
125
|
+
| defs name lb pattern_params rb eq filter sc
|
|
126
|
+
{
|
|
127
|
+
const seen = new Set();
|
|
128
|
+
for (const p of $4) {
|
|
129
|
+
if (seen.has(p)) {
|
|
130
|
+
const msg =
|
|
131
|
+
`Duplicate parameter '${p}' ` +
|
|
132
|
+
`in pattern '${$2.value}'.`;
|
|
133
|
+
anError(@4, msg);
|
|
134
|
+
}
|
|
135
|
+
seen.add(p);
|
|
136
|
+
}
|
|
137
|
+
s.add_pattern($2.value, $4, $7);
|
|
138
|
+
}
|
|
139
|
+
;
|
|
140
|
+
|
|
141
|
+
pattern_params
|
|
142
|
+
: /* empty */ { $$ = []; }
|
|
143
|
+
| non_empty_pattern_params { $$ = $1; }
|
|
144
|
+
;
|
|
145
|
+
|
|
146
|
+
non_empty_pattern_params
|
|
147
|
+
: name { $$ = [$1.value]; }
|
|
148
|
+
| non_empty_pattern_params comma name
|
|
149
|
+
{ $$ = [].concat($1, $3.value); }
|
|
116
150
|
;
|
|
117
151
|
|
|
118
152
|
filter_
|
|
119
153
|
: lp dots rp { $$ = { type: null, open: true, fields: {}, start: $1.start, end: $3.end}; }
|
|
120
154
|
| la labelled_filters ra { $$ = { type: "union", open: $2.open, fields: $2.fields, start: $1.start, end: $3.end}; }
|
|
121
155
|
| lc labelled_filters rc { $$ = { type: "product", open: $2.open, fields: $2.fields, start: $1.start, end: $3.end}; }
|
|
156
|
+
| name lb pattern_args rb
|
|
157
|
+
{
|
|
158
|
+
$$ = {
|
|
159
|
+
type: "pattern_apply",
|
|
160
|
+
pattern: $1.value,
|
|
161
|
+
args: $3,
|
|
162
|
+
start: $1.start,
|
|
163
|
+
end: $4.end
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
;
|
|
167
|
+
|
|
168
|
+
pattern_args
|
|
169
|
+
: /* empty */ { $$ = []; }
|
|
170
|
+
| non_empty_pattern_args { $$ = $1; }
|
|
171
|
+
;
|
|
172
|
+
|
|
173
|
+
non_empty_pattern_args
|
|
174
|
+
: filter { $$ = [$1]; }
|
|
175
|
+
| non_empty_pattern_args comma filter
|
|
176
|
+
{ $$ = [].concat($1, $3); }
|
|
122
177
|
;
|
|
123
178
|
|
|
124
179
|
filter
|
|
125
180
|
: filter_ { $$ = $1; }
|
|
126
|
-
| filter_ EQ name
|
|
181
|
+
| filter_ EQ name
|
|
182
|
+
{
|
|
183
|
+
$$ = {
|
|
184
|
+
...$1,
|
|
185
|
+
name: $3.value,
|
|
186
|
+
start: $1.start,
|
|
187
|
+
end: $3.end
|
|
188
|
+
};
|
|
189
|
+
}
|
|
127
190
|
| name { $$ = { type: 'name', name: $1.value, open: true, start: $1.start, end: $1.end}; }
|
|
128
191
|
;
|
|
129
192
|
labelled_filters
|