@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
package/codecs/djson.mjs
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dynamic JSON (djson) codec with universal singleton pattern.
|
|
5
|
+
*
|
|
6
|
+
* Translates arbitrary JSON data to/from self-describing enveloped k
|
|
7
|
+
* values using a single recursive AST pattern:
|
|
8
|
+
*
|
|
9
|
+
* JSON = <
|
|
10
|
+
* float64 number,
|
|
11
|
+
* str string,
|
|
12
|
+
* <{} true, {} false> bool,
|
|
13
|
+
* {} null,
|
|
14
|
+
* <{} nil, {JSON car, LIST cdr} cons> = LIST list,
|
|
15
|
+
* <{} nil, {{str key, JSON val} car, OBJ cdr} cons> = OBJ object
|
|
16
|
+
* >
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
Value,
|
|
21
|
+
isProduct,
|
|
22
|
+
isVariant,
|
|
23
|
+
withPattern,
|
|
24
|
+
patternFromFilter,
|
|
25
|
+
runCodecCLI
|
|
26
|
+
} from "./runtime/codec-sdk.mjs";
|
|
27
|
+
import { encodeNumberToValue, decodeValueToNumber } from "./ieee.mjs";
|
|
28
|
+
import {
|
|
29
|
+
textToStringValue,
|
|
30
|
+
stringValueToText
|
|
31
|
+
} from "./runtime/unicode-string.mjs";
|
|
32
|
+
|
|
33
|
+
export const doc = `
|
|
34
|
+
Dynamic JSON (djson) codec with universal singleton pattern.
|
|
35
|
+
|
|
36
|
+
Translates any JSON value to/from self-describing enveloped k values
|
|
37
|
+
conforming to the universal recursive JSON AST type:
|
|
38
|
+
JSON = <
|
|
39
|
+
float64 number,
|
|
40
|
+
str string,
|
|
41
|
+
<{} true, {} false> bool,
|
|
42
|
+
{} null,
|
|
43
|
+
<{} nil, {JSON car, LIST cdr} cons> = LIST list,
|
|
44
|
+
<{} nil, {{str key, JSON val} car, OBJ cdr} cons> = OBJ object
|
|
45
|
+
>
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
export const DJSON_PATTERN = patternFromFilter(`
|
|
49
|
+
? <
|
|
50
|
+
{
|
|
51
|
+
< {} "+", {} "-" > sign,
|
|
52
|
+
{
|
|
53
|
+
< {} 0, {} 1 >=Bit 0,
|
|
54
|
+
Bit 1, Bit 2, Bit 3, Bit 4, Bit 5,
|
|
55
|
+
Bit 6, Bit 7, Bit 8, Bit 9, Bit 10
|
|
56
|
+
} exponent,
|
|
57
|
+
{
|
|
58
|
+
Bit 0, Bit 1, Bit 2, Bit 3, Bit 4, Bit 5,
|
|
59
|
+
Bit 6, Bit 7, Bit 8, Bit 9, Bit 10, Bit 11,
|
|
60
|
+
Bit 12, Bit 13, Bit 14, Bit 15, Bit 16, Bit 17,
|
|
61
|
+
Bit 18, Bit 19, Bit 20, Bit 21, Bit 22, Bit 23,
|
|
62
|
+
Bit 24, Bit 25, Bit 26, Bit 27, Bit 28, Bit 29,
|
|
63
|
+
Bit 30, Bit 31, Bit 32, Bit 33, Bit 34, Bit 35,
|
|
64
|
+
Bit 36, Bit 37, Bit 38, Bit 39, Bit 40, Bit 41,
|
|
65
|
+
Bit 42, Bit 43, Bit 44, Bit 45, Bit 46, Bit 47,
|
|
66
|
+
Bit 48, Bit 49, Bit 50, Bit 51
|
|
67
|
+
} fraction
|
|
68
|
+
} number,
|
|
69
|
+
|
|
70
|
+
<
|
|
71
|
+
{} nil,
|
|
72
|
+
{
|
|
73
|
+
<
|
|
74
|
+
{
|
|
75
|
+
< {} 0, {} 1 >=Bit7 0,
|
|
76
|
+
Bit7 1, Bit7 2, Bit7 3, Bit7 4, Bit7 5, Bit7 6
|
|
77
|
+
}=Bits7 ascii,
|
|
78
|
+
{
|
|
79
|
+
<
|
|
80
|
+
{ Bit7 0, Bit7 1, Bit7 2 }=Bits3 h08_0F,
|
|
81
|
+
Bits7 h10_7F,
|
|
82
|
+
Bits7 h80_CF,
|
|
83
|
+
Bits3 hD0_D7,
|
|
84
|
+
{} hF9,
|
|
85
|
+
{ Bit7 0 }=Bits1 hFA_FB,
|
|
86
|
+
Bits1 hFC_FD,
|
|
87
|
+
Bits1 hFE_FF
|
|
88
|
+
> hi,
|
|
89
|
+
{
|
|
90
|
+
Bit7 0, Bit7 1, Bit7 2, Bit7 3,
|
|
91
|
+
Bit7 4, Bit7 5, Bit7 6, Bit7 7
|
|
92
|
+
}=Bits8 lo
|
|
93
|
+
} bmp_common,
|
|
94
|
+
{
|
|
95
|
+
<
|
|
96
|
+
{ Bit7 0, Bit7 1, Bit7 2, Bit7 3 } hE0_EF,
|
|
97
|
+
Bits3 hF0_F7,
|
|
98
|
+
{} hF8
|
|
99
|
+
> hi,
|
|
100
|
+
Bits8 lo
|
|
101
|
+
} bmp_private_use,
|
|
102
|
+
{
|
|
103
|
+
Bit7 0, Bit7 1, Bit7 2, Bit7 3, Bit7 4, Bit7 5,
|
|
104
|
+
Bit7 6, Bit7 7, Bit7 8, Bit7 9, Bit7 10
|
|
105
|
+
} plane0,
|
|
106
|
+
{ Bits8 mid, Bits8 lo } supplementary_plane1,
|
|
107
|
+
{
|
|
108
|
+
<
|
|
109
|
+
Bits1 p02_03,
|
|
110
|
+
{ Bit7 0, Bit7 1 } p04_07,
|
|
111
|
+
Bits3 p08_0F,
|
|
112
|
+
{} p10
|
|
113
|
+
> plane,
|
|
114
|
+
Bits8 mid,
|
|
115
|
+
Bits8 lo
|
|
116
|
+
} supplementary_planes2_16
|
|
117
|
+
> car,
|
|
118
|
+
Str cdr
|
|
119
|
+
} cons
|
|
120
|
+
> = Str string,
|
|
121
|
+
|
|
122
|
+
< {} true, {} false > bool,
|
|
123
|
+
{} null,
|
|
124
|
+
|
|
125
|
+
< {} nil, { JSON car, LIST cdr } cons > = LIST list,
|
|
126
|
+
|
|
127
|
+
< {} nil, { { Str key, JSON val } car, OBJ cdr } cons > = OBJ object
|
|
128
|
+
> = JSON
|
|
129
|
+
`);
|
|
130
|
+
|
|
131
|
+
const UNIT = Value.product({});
|
|
132
|
+
|
|
133
|
+
function requireProduct(value, where) {
|
|
134
|
+
if (!isProduct(value)) {
|
|
135
|
+
throw new Error(`${where}: expected Product`);
|
|
136
|
+
}
|
|
137
|
+
return value.product;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function listToK(items) {
|
|
141
|
+
let result = Value.variant("nil", UNIT);
|
|
142
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
143
|
+
result = Value.variant("cons", Value.product({
|
|
144
|
+
car: items[i],
|
|
145
|
+
cdr: result
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function listFromK(value, where) {
|
|
152
|
+
const result = [];
|
|
153
|
+
let current = value;
|
|
154
|
+
while (true) {
|
|
155
|
+
if (!isVariant(current)) {
|
|
156
|
+
throw new Error(`${where}: expected list variant (nil or cons)`);
|
|
157
|
+
}
|
|
158
|
+
if (current.tag === "nil") {
|
|
159
|
+
requireProduct(current.value, `${where}.nil`);
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
if (current.tag !== "cons") {
|
|
163
|
+
throw new Error(
|
|
164
|
+
`${where}: expected nil or cons, got ${current.tag}`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
const pair = requireProduct(current.value, `${where}.cons`);
|
|
168
|
+
result.push(pair.car);
|
|
169
|
+
current = pair.cdr;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function fromJsonValue(value) {
|
|
174
|
+
if (value === null) {
|
|
175
|
+
return Value.variant("null", UNIT);
|
|
176
|
+
}
|
|
177
|
+
if (typeof value === "boolean") {
|
|
178
|
+
return Value.variant(
|
|
179
|
+
"bool",
|
|
180
|
+
Value.variant(value ? "true" : "false", UNIT)
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
if (typeof value === "number") {
|
|
184
|
+
if (!Number.isFinite(value)) {
|
|
185
|
+
throw new Error("JSON numbers must be finite");
|
|
186
|
+
}
|
|
187
|
+
return Value.variant("number", encodeNumberToValue(value));
|
|
188
|
+
}
|
|
189
|
+
if (typeof value === "string") {
|
|
190
|
+
return Value.variant("string", textToStringValue(value));
|
|
191
|
+
}
|
|
192
|
+
if (Array.isArray(value)) {
|
|
193
|
+
return Value.variant("list", listToK(value.map(fromJsonValue)));
|
|
194
|
+
}
|
|
195
|
+
if (value && typeof value === "object") {
|
|
196
|
+
const keys = Object.keys(value).sort();
|
|
197
|
+
const entries = keys.map((k) =>
|
|
198
|
+
Value.product({
|
|
199
|
+
key: textToStringValue(k),
|
|
200
|
+
val: fromJsonValue(value[k])
|
|
201
|
+
})
|
|
202
|
+
);
|
|
203
|
+
return Value.variant("object", listToK(entries));
|
|
204
|
+
}
|
|
205
|
+
throw new Error(`Unsupported JSON value: ${value}`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function toJsonValue(value) {
|
|
209
|
+
if (!isVariant(value)) {
|
|
210
|
+
throw new Error("djson.value: expected top-level Variant");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (value.tag === "null") {
|
|
214
|
+
requireProduct(value.value, "djson.null");
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (value.tag === "bool") {
|
|
219
|
+
if (!isVariant(value.value)) {
|
|
220
|
+
throw new Error("djson.bool: expected variant");
|
|
221
|
+
}
|
|
222
|
+
if (value.value.tag === "true") {
|
|
223
|
+
requireProduct(value.value.value, "djson.bool.true");
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
if (value.value.tag === "false") {
|
|
227
|
+
requireProduct(value.value.value, "djson.bool.false");
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
throw new Error(`djson.bool: invalid tag ${value.value.tag}`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (value.tag === "number") {
|
|
234
|
+
return decodeValueToNumber(value.value);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (value.tag === "string") {
|
|
238
|
+
return stringValueToText(value.value);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (value.tag === "list") {
|
|
242
|
+
const items = listFromK(value.value, "djson.list");
|
|
243
|
+
return items.map(toJsonValue);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (value.tag === "object") {
|
|
247
|
+
const pairs = listFromK(value.value, "djson.object");
|
|
248
|
+
const result = {};
|
|
249
|
+
for (const pairValue of pairs) {
|
|
250
|
+
const pair = requireProduct(pairValue, "djson.object.pair");
|
|
251
|
+
const key = stringValueToText(pair.key);
|
|
252
|
+
result[key] = toJsonValue(pair.val);
|
|
253
|
+
}
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
throw new Error(`Unsupported djson tag: ${value.tag}`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export function parse(text) {
|
|
261
|
+
const json = JSON.parse(text);
|
|
262
|
+
const value = fromJsonValue(json);
|
|
263
|
+
return withPattern(value, DJSON_PATTERN);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function print(value) {
|
|
267
|
+
return JSON.stringify(toJsonValue(value));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
runCodecCLI(import.meta.url, { parse, print, doc });
|
package/codecs/int.mjs
CHANGED
|
@@ -14,7 +14,8 @@ export const doc = `
|
|
|
14
14
|
Decimal integers and integer lists.
|
|
15
15
|
|
|
16
16
|
Syntax:
|
|
17
|
-
Decimal integer (e.g. 42, -15) or bracketed integer list
|
|
17
|
+
Decimal integer (e.g. 42, -15) or bracketed integer list
|
|
18
|
+
(e.g. [0, 1, 2], []).
|
|
18
19
|
`;
|
|
19
20
|
|
|
20
21
|
// Closed pattern for $ int = < bits '+', bits '-' >
|
package/codecs/json.mjs
CHANGED
|
@@ -4,9 +4,14 @@ import { withPattern, runCodecCLI } from "./runtime/codec-sdk.mjs";
|
|
|
4
4
|
import { fromJsonValue, toJsonValue, patternFromJsonValue } from "./json-codec.mjs";
|
|
5
5
|
|
|
6
6
|
export const doc = `
|
|
7
|
-
JSON codec (RFC 8259).
|
|
7
|
+
Schema-specializing JSON codec (RFC 8259).
|
|
8
8
|
|
|
9
|
-
Translates JSON data to/from self-describing enveloped k values
|
|
9
|
+
Translates JSON data to/from self-describing enveloped k values where
|
|
10
|
+
each JSON document derives a document-specific pattern:
|
|
11
|
+
- objects map to products { field: value, ... }
|
|
12
|
+
- arrays map to indexed products { "0": a0, "1": a1, ... }
|
|
13
|
+
- numbers, strings, booleans, and null map to canonical k values
|
|
14
|
+
(See djson.mjs for the universal singleton-pattern dynamic JSON codec.)
|
|
10
15
|
`;
|
|
11
16
|
|
|
12
17
|
export function parse(text) {
|
package/codecs/k-parse.mjs
CHANGED
|
@@ -82,7 +82,13 @@ async function main() {
|
|
|
82
82
|
return exit(1);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
stdout.on("error", (err) => {
|
|
86
|
+
if (err.code === "EPIPE") exit(0);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const inputBuffer = valueFile
|
|
90
|
+
? fs.readFileSync(valueFile)
|
|
91
|
+
: await readAll(stdin);
|
|
86
92
|
const inputText = inputBuffer.toString("utf8");
|
|
87
93
|
const value = parseValue(inputText, null, null);
|
|
88
94
|
|
package/codecs/k-print.mjs
CHANGED
|
@@ -60,6 +60,10 @@ async function main() {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
stdout.on("error", (err) => {
|
|
64
|
+
if (err.code === "EPIPE") process.exit(0);
|
|
65
|
+
});
|
|
66
|
+
|
|
63
67
|
const input = fileArg ? fs.createReadStream(fileArg) : stdin;
|
|
64
68
|
const buffer = await readAll(input);
|
|
65
69
|
const { pattern, value } = decodeWire(buffer);
|
|
@@ -3,8 +3,17 @@
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { stdin, stdout, stderr, exit } from "node:process";
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
Value,
|
|
8
|
+
isProduct,
|
|
9
|
+
isVariant,
|
|
10
|
+
withPattern
|
|
11
|
+
} from "../../Value.mjs";
|
|
12
|
+
import {
|
|
13
|
+
decodeWire,
|
|
14
|
+
decodeWireLazy,
|
|
15
|
+
encodeToWire
|
|
16
|
+
} from "./prefix-codec.mjs";
|
|
8
17
|
import { isMainEntrypoint } from "./cli-entry.mjs";
|
|
9
18
|
import { patternFromFilter } from "./pattern-k.mjs";
|
|
10
19
|
|
|
@@ -53,6 +62,10 @@ function runCodecCLI(metaUrl, codec) {
|
|
|
53
62
|
|
|
54
63
|
const mode = args[0];
|
|
55
64
|
|
|
65
|
+
stdout.on("error", (err) => {
|
|
66
|
+
if (err.code === "EPIPE") exit(0);
|
|
67
|
+
});
|
|
68
|
+
|
|
56
69
|
(async () => {
|
|
57
70
|
if (mode === "--parse") {
|
|
58
71
|
let parsed;
|
|
@@ -92,6 +105,7 @@ export {
|
|
|
92
105
|
withPattern,
|
|
93
106
|
encodeToWire,
|
|
94
107
|
decodeWire,
|
|
108
|
+
decodeWireLazy,
|
|
95
109
|
isMainEntrypoint,
|
|
96
110
|
runCodecCLI,
|
|
97
111
|
patternFromFilter
|
|
@@ -80,17 +80,96 @@ function propertyListToPattern(propertyList) {
|
|
|
80
80
|
throw new Error("Pattern node 'any' cannot have outgoing edges");
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
const tagIndex = Object.create(null);
|
|
84
|
+
for (let i = 0; i < edges.length; i++) {
|
|
85
|
+
tagIndex[edges[i].label] = i;
|
|
86
|
+
}
|
|
87
|
+
const choiceBits = edges.length <= 1
|
|
88
|
+
? 0
|
|
89
|
+
: Math.ceil(Math.log2(edges.length));
|
|
83
90
|
return {
|
|
84
91
|
kind,
|
|
85
|
-
edges: edges.map((edge) => ({
|
|
92
|
+
edges: edges.map((edge) => ({
|
|
93
|
+
...edge,
|
|
94
|
+
symbolId: symbolIds.get(edge.label)
|
|
95
|
+
})),
|
|
96
|
+
tagIndex,
|
|
97
|
+
choiceBits
|
|
86
98
|
};
|
|
87
99
|
});
|
|
88
100
|
|
|
101
|
+
computePatternBitWidths(nodes);
|
|
102
|
+
|
|
89
103
|
return {
|
|
90
104
|
dictionary,
|
|
91
105
|
nodes
|
|
92
106
|
};
|
|
93
107
|
}
|
|
94
108
|
|
|
109
|
+
function computePatternBitWidths(nodes) {
|
|
110
|
+
let changed = true;
|
|
111
|
+
while (changed) {
|
|
112
|
+
changed = false;
|
|
113
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
114
|
+
const node = nodes[i];
|
|
115
|
+
if (node.fixedBitWidth !== undefined) continue;
|
|
116
|
+
|
|
117
|
+
if (node.kind === NAME_TO_NODE_KIND["closed-product"]) {
|
|
118
|
+
if (node.edges.length === 0) {
|
|
119
|
+
node.fixedBitWidth = 0;
|
|
120
|
+
node.staticOffsets = [];
|
|
121
|
+
changed = true;
|
|
122
|
+
} else {
|
|
123
|
+
let allKnown = true;
|
|
124
|
+
let sum = 0;
|
|
125
|
+
const offsets = new Array(node.edges.length);
|
|
126
|
+
for (let j = 0; j < node.edges.length; j++) {
|
|
127
|
+
const target = nodes[node.edges[j].target];
|
|
128
|
+
if (target.fixedBitWidth === undefined) {
|
|
129
|
+
allKnown = false;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
offsets[j] = sum;
|
|
133
|
+
sum += target.fixedBitWidth;
|
|
134
|
+
}
|
|
135
|
+
if (allKnown) {
|
|
136
|
+
node.fixedBitWidth = sum;
|
|
137
|
+
node.staticOffsets = offsets;
|
|
138
|
+
changed = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} else if (node.kind === NAME_TO_NODE_KIND["closed-union"]) {
|
|
142
|
+
if (node.edges.length > 0) {
|
|
143
|
+
const firstTarget = nodes[node.edges[0].target];
|
|
144
|
+
const w = firstTarget.fixedBitWidth;
|
|
145
|
+
if (w !== undefined) {
|
|
146
|
+
let allSame = true;
|
|
147
|
+
for (let j = 1; j < node.edges.length; j++) {
|
|
148
|
+
if (nodes[node.edges[j].target].fixedBitWidth !== w) {
|
|
149
|
+
allSame = false;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (allSame) {
|
|
154
|
+
node.fixedBitWidth = node.choiceBits + w;
|
|
155
|
+
changed = true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
164
|
+
const edges = nodes[i].edges;
|
|
165
|
+
for (let j = 0; j < edges.length; j++) {
|
|
166
|
+
const target = nodes[edges[j].target];
|
|
167
|
+
if (target.fixedBitWidth !== undefined) {
|
|
168
|
+
edges[j].fixedTargetBitWidth = target.fixedBitWidth;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
95
174
|
export { patternToPropertyList, propertyListToPattern, NODE_KIND_TO_NAME, NAME_TO_NODE_KIND };
|
|
96
175
|
export default { patternToPropertyList, propertyListToPattern, NODE_KIND_TO_NAME, NAME_TO_NODE_KIND };
|