@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.
Files changed (64) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/DOCS/BIG_PICTURE.md +54 -7
  3. package/DOCS/CODECS.md +47 -2
  4. package/DOCS/CODEC_ARCHITECTURE.md +14 -5
  5. package/DOCS/DICTIONARY.md +13 -4
  6. package/DOCS/FILE_FORMATS.md +3 -2
  7. package/DOCS/JSON_APPROACHES_COMPARISON.md +306 -0
  8. package/DOCS/NAMED_PATTERNS.md +317 -0
  9. package/DOCS/PATTERNS.md +59 -11
  10. package/DOCS/REPL.md +24 -5
  11. package/DOCS/WEB_REPL_REQUIREMENTS.md +4 -2
  12. package/Examples/arithmetics.k +22 -17
  13. package/Examples/bnat.k +21 -11
  14. package/Examples/buda.k +37 -20
  15. package/Examples/byte.k +3 -1
  16. package/Examples/code.k +38 -39
  17. package/Examples/djson-btrie.k +414 -0
  18. package/Examples/djson-ptrie.k +663 -0
  19. package/Examples/djson.k +323 -0
  20. package/Examples/esc.k +1 -1
  21. package/Examples/karatsuba-mult.k +16 -13
  22. package/Examples/list.k +8 -4
  23. package/Examples/nat.k +17 -11
  24. package/Examples/poly.k +11 -3
  25. package/Examples/vhdl_to_k.k +43 -31
  26. package/README.md +42 -15
  27. package/Value.mjs +28 -3
  28. package/backend-api.mjs +5 -1
  29. package/browser/repl-browser.mjs +6 -0
  30. package/browser/tree-view.mjs +82 -24
  31. package/browser/vfs-data.mjs +21 -12
  32. package/codecs/README.md +3 -0
  33. package/codecs/djson-btrie.mjs +560 -0
  34. package/codecs/djson-ptrie.mjs +587 -0
  35. package/codecs/djson.mjs +270 -0
  36. package/codecs/int.mjs +2 -1
  37. package/codecs/json.mjs +7 -2
  38. package/codecs/k-parse.mjs +7 -1
  39. package/codecs/k-print.mjs +4 -0
  40. package/codecs/runtime/codec-sdk.mjs +16 -2
  41. package/codecs/runtime/pattern-json.mjs +80 -1
  42. package/codecs/runtime/prefix-codec.mjs +629 -67
  43. package/codecs/runtime/show-value.mjs +93 -51
  44. package/codecs/runtime/unicode-string.mjs +29 -6
  45. package/codecs/show.mjs +4 -0
  46. package/codecs/utf16.mjs +2 -1
  47. package/core.k +79 -115
  48. package/index.mjs +3 -0
  49. package/named-patterns.mjs +267 -0
  50. package/object.mjs +31 -3
  51. package/package.json +5 -1
  52. package/parser.jison +68 -5
  53. package/parser.mjs +111 -60
  54. package/pretty.mjs +5 -0
  55. package/repl.mjs +245 -28
  56. package/scripts/build-repl-html.mjs +76 -5
  57. package/scripts/perf-djson.mjs +1142 -0
  58. package/scripts/run-tests.mjs +5 -0
  59. package/symbol-table.mjs +20 -2
  60. package/tests/bench-djson-tries.mjs +340 -0
  61. package/tests/test-codecs.mjs +211 -0
  62. package/tests/test-named-patterns.mjs +189 -0
  63. package/tests/test-repl-html.mjs +52 -4
  64. package/tests/test-repl.mjs +223 -0
@@ -0,0 +1,663 @@
1
+ -- Examples/djson-ptrie.k: Patricia/Radix Trie JSON schema & helpers
2
+ -- Works with codecs/djson-ptrie.mjs (trie-array style).
3
+
4
+ ---------------------------------------------------------------
5
+ -- §1. Named Pattern Definitions & Component Schemas
6
+ ---------------------------------------------------------------
7
+
8
+ bit[] = < {} 0, {} 1 >;
9
+
10
+ bits[] = < {} _, B 0, B 1 > = B;
11
+
12
+ sign[] = < {} "+", {} "-" >;
13
+
14
+ exponent[] = {
15
+ bit[] 0, bit[] 1, bit[] 2, bit[] 3, bit[] 4,
16
+ bit[] 5, bit[] 6, bit[] 7, bit[] 8, bit[] 9, bit[] 10
17
+ };
18
+
19
+ fraction[] = {
20
+ bit[] 0, bit[] 1, bit[] 2, bit[] 3, bit[] 4, bit[] 5,
21
+ bit[] 6, bit[] 7, bit[] 8, bit[] 9, bit[] 10, bit[] 11,
22
+ bit[] 12, bit[] 13, bit[] 14, bit[] 15, bit[] 16, bit[] 17,
23
+ bit[] 18, bit[] 19, bit[] 20, bit[] 21, bit[] 22, bit[] 23,
24
+ bit[] 24, bit[] 25, bit[] 26, bit[] 27, bit[] 28, bit[] 29,
25
+ bit[] 30, bit[] 31, bit[] 32, bit[] 33, bit[] 34, bit[] 35,
26
+ bit[] 36, bit[] 37, bit[] 38, bit[] 39, bit[] 40, bit[] 41,
27
+ bit[] 42, bit[] 43, bit[] 44, bit[] 45, bit[] 46, bit[] 47,
28
+ bit[] 48, bit[] 49, bit[] 50, bit[] 51
29
+ };
30
+
31
+ number[] = {
32
+ sign[] sign,
33
+ exponent[] exponent,
34
+ fraction[] fraction
35
+ };
36
+
37
+ byte[] = {
38
+ bit[] 0, bit[] 1, bit[] 2, bit[] 3,
39
+ bit[] 4, bit[] 5, bit[] 6, bit[] 7
40
+ };
41
+
42
+ ascii[] = {
43
+ bit[] 0, bit[] 1, bit[] 2, bit[] 3,
44
+ bit[] 4, bit[] 5, bit[] 6
45
+ };
46
+
47
+ bmp_hi_common[] = <
48
+ { bit[] 0, bit[] 1, bit[] 2 } h08_0F,
49
+ ascii[] h10_7F,
50
+ ascii[] h80_CF,
51
+ { bit[] 0, bit[] 1, bit[] 2 } hD0_D7,
52
+ {} hF9,
53
+ { bit[] 0 } hFA_FB,
54
+ { bit[] 0 } hFC_FD,
55
+ { bit[] 0 } hFE_FF
56
+ >;
57
+
58
+ bmp_hi_private_use[] = <
59
+ { bit[] 0, bit[] 1, bit[] 2, bit[] 3 } hE0_EF,
60
+ { bit[] 0, bit[] 1, bit[] 2 } hF0_F7,
61
+ {} hF8
62
+ >;
63
+
64
+ plane0[] = {
65
+ bit[] 0, bit[] 1, bit[] 2, bit[] 3, bit[] 4,
66
+ bit[] 5, bit[] 6, bit[] 7, bit[] 8, bit[] 9, bit[] 10
67
+ };
68
+
69
+ plane_02_10[] = <
70
+ { bit[] 0 } p02_03,
71
+ { bit[] 0, bit[] 1 } p04_07,
72
+ { bit[] 0, bit[] 1, bit[] 2 } p08_0F,
73
+ {} p10
74
+ >;
75
+
76
+ unicode[] = <
77
+ ascii[] ascii,
78
+ { bmp_hi_common[] hi, byte[] lo } bmp_common,
79
+ { bmp_hi_private_use[] hi, byte[] lo } bmp_private_use,
80
+ plane0[] plane0,
81
+ { byte[] mid, byte[] lo } supplementary_plane1,
82
+ { plane_02_10[] plane, byte[] mid, byte[] lo } supplementary_planes2_16
83
+ >;
84
+
85
+ string[] = < {} nil, { unicode[] car, S cdr } cons > = S;
86
+
87
+ bool[] = < {} true, {} false >;
88
+
89
+ opt[V] = < {} nil, V val >;
90
+
91
+ ptrie_list[V] = <
92
+ {} nil,
93
+ {
94
+ bits[] prefix,
95
+ bits[] size,
96
+ opt[V] val,
97
+ L 0,
98
+ L 1
99
+ } trie
100
+ > = L;
101
+
102
+ pair[A, B] = { A char, B trie };
103
+ list[X] = < {} nil, { X car, D cdr } cons > = D;
104
+
105
+ ptrie_obj[V] = <
106
+ {} nil,
107
+ {
108
+ string[] prefix,
109
+ bits[] size,
110
+ opt[V] val,
111
+ list[pair[unicode[], O]] dict
112
+ } trie
113
+ > = O;
114
+
115
+ djson_ptrie[] = <
116
+ number[] number,
117
+ string[] string,
118
+ bool[] bool,
119
+ {} null,
120
+ ptrie_list[J] list,
121
+ ptrie_obj[J] object
122
+ > = J;
123
+
124
+ json? = ? djson_ptrie[];
125
+
126
+ -----------------------------------------------------------------
127
+ -- §2. Unicode Character Equality (eq_char?)
128
+ ---------------------------------------------------------------
129
+
130
+ eq_bit? = ?{ <{} 0, {} 1>=B x, B y }
131
+ < {.x /0 x, .y /0 y}, {.x /1 x, .y /1 y} > {};
132
+
133
+ eq_bits1? = { {.x .0 x, .y .0 y} eq_bit? 0 } {};
134
+ eq_bits2? = { {.x x, .y y} eq_bits1? a, {.x .1 x, .y .1 y} eq_bit? 1 } {};
135
+ eq_bits3? = { {.x x, .y y} eq_bits2? a, {.x .2 x, .y .2 y} eq_bit? 2 } {};
136
+ eq_bits4? = { {.x x, .y y} eq_bits3? a, {.x .3 x, .y .3 y} eq_bit? 3 } {};
137
+ eq_bits7? = {
138
+ {.x x, .y y} eq_bits4? a,
139
+ {.x .4 x, .y .4 y} eq_bit? 4,
140
+ {.x .5 x, .y .5 y} eq_bit? 5,
141
+ {.x .6 x, .y .6 y} eq_bit? 6
142
+ } {};
143
+ eq_bits8? = { {.x x, .y y} eq_bits7? a, {.x .7 x, .y .7 y} eq_bit? 7 } {};
144
+ eq_bits11? = {
145
+ {.x x, .y y} eq_bits8? a,
146
+ {.x .8 x, .y .8 y} eq_bit? 8,
147
+ {.x .9 x, .y .9 y} eq_bit? 9,
148
+ {.x .10 x, .y .10 y} eq_bit? 10
149
+ } {};
150
+
151
+ eq_bmp_common_hi? = <
152
+ {.x /h08_0F x, .y /h08_0F y} eq_bits3?,
153
+ {.x /h10_7F x, .y /h10_7F y} eq_bits7?,
154
+ {.x /h80_CF x, .y /h80_CF y} eq_bits7?,
155
+ {.x /hD0_D7 x, .y /hD0_D7 y} eq_bits3?,
156
+ {.x /hF9 x, .y /hF9 y} {},
157
+ {.x /hFA_FB x, .y /hFA_FB y} eq_bits1?,
158
+ {.x /hFC_FD x, .y /hFC_FD y} eq_bits1?,
159
+ {.x /hFE_FF x, .y /hFE_FF y} eq_bits1?
160
+ >;
161
+
162
+ eq_bmp_private_use_hi? = <
163
+ {.x /hE0_EF x, .y /hE0_EF y} eq_bits4?,
164
+ {.x /hF0_F7 x, .y /hF0_F7 y} eq_bits3?,
165
+ {.x /hF8 x, .y /hF8 y} {}
166
+ >;
167
+
168
+ eq_plane2_16? = <
169
+ {.x /p02_03 x, .y /p02_03 y} eq_bits1?,
170
+ {.x /p04_07 x, .y /p04_07 y} eq_bits2?,
171
+ {.x /p08_0F x, .y /p08_0F y} eq_bits3?,
172
+ {.x /p10 x, .y /p10 y} {}
173
+ >;
174
+
175
+ eq_char? = <
176
+ {.x /ascii x, .y /ascii y} eq_bits7?,
177
+ {
178
+ {.x /bmp_common .hi x, .y /bmp_common .hi y} eq_bmp_common_hi? hi,
179
+ {.x /bmp_common .lo x, .y /bmp_common .lo y} eq_bits8? lo
180
+ } {},
181
+ {
182
+ {
183
+ .x /bmp_private_use .hi x,
184
+ .y /bmp_private_use .hi y
185
+ } eq_bmp_private_use_hi? hi,
186
+ {.x /bmp_private_use .lo x, .y /bmp_private_use .lo y} eq_bits8? lo
187
+ } {},
188
+ {.x /plane0 x, .y /plane0 y} eq_bits11?,
189
+ {
190
+ {
191
+ .x /supplementary_plane1 .mid x,
192
+ .y /supplementary_plane1 .mid y
193
+ } eq_bits8? mid,
194
+ {
195
+ .x /supplementary_plane1 .lo x,
196
+ .y /supplementary_plane1 .lo y
197
+ } eq_bits8? lo
198
+ } {},
199
+ {
200
+ {
201
+ .x /supplementary_planes2_16 .plane x,
202
+ .y /supplementary_planes2_16 .plane y
203
+ } eq_plane2_16? plane,
204
+ {
205
+ .x /supplementary_planes2_16 .mid x,
206
+ .y /supplementary_planes2_16 .mid y
207
+ } eq_bits8? mid,
208
+ {
209
+ .x /supplementary_planes2_16 .lo x,
210
+ .y /supplementary_planes2_16 .lo y
211
+ } eq_bits8? lo
212
+ } {}
213
+ >;
214
+
215
+ ---------------------------------------------------------------
216
+ -- §3. Patricia/Radix Trie Lookup Relations (dot, nth, has_key?)
217
+ ---------------------------------------------------------------
218
+
219
+ bits? = ?< {} _, bits? 0, bits? 1 > = bits?;
220
+ 0b = {} | _;
221
+ 0 = 0b | 0;
222
+ 1 = 0b | 1;
223
+ str_list? = ?< {} nil, { C car, S cdr } cons > = S;
224
+ ptrie_list? = ?<
225
+ {} nil,
226
+ { B1 prefix, B2 size, < {} nil, V val > val, T 0, T 1 } trie
227
+ > = T;
228
+ ptrie_obj? = ?<
229
+ {} nil,
230
+ {
231
+ S prefix,
232
+ B size,
233
+ < {} nil, V val > val,
234
+ < {} nil, { { C char, T trie } car, D cdr } cons >=D dict
235
+ } trie
236
+ > = T;
237
+ ptrie_dict? = ?<
238
+ {} nil,
239
+ { { C char, T trie } car, D cdr } cons
240
+ > = D;
241
+
242
+ nil = {} | nil;
243
+ null = {} | null json?;
244
+ true = {} | true | bool json?;
245
+ false = {} | false | bool json?;
246
+ number = | number json?;
247
+ string = | string json?;
248
+ bool = | bool json?;
249
+ list = | list json?;
250
+ object = | object json?;
251
+
252
+ -- O(1) subtree size queries (number of elements in list or object)
253
+ list_size = ptrie_list? < /nil 0, /trie .size >;
254
+ obj_size = ptrie_obj? < /nil 0, /trie .size >;
255
+
256
+ match_str_prefix = ?{ P prefix, K key } {
257
+ .prefix str_list? prefix,
258
+ .key str_list? key
259
+ } <
260
+ { .prefix /nil if, .key then } .then,
261
+ {
262
+ { .prefix /cons .car x, .key /cons .car y } eq_char? if,
263
+ { .prefix /cons .cdr prefix, .key /cons .cdr key }
264
+ match_str_prefix then
265
+ } .then
266
+ >;
267
+
268
+ find_in_dict = ?{ C char, D dict } {
269
+ .char char,
270
+ .dict ptrie_dict? dict
271
+ } <
272
+ {
273
+ { .char x, .dict /cons .car .char y } eq_char? if,
274
+ .dict /cons .car .trie then
275
+ } .then,
276
+ { .char char, .dict /cons .cdr dict } find_in_dict
277
+ >;
278
+
279
+ -- Lookup string key in radix object trie: { key, object } -> val
280
+ dot = ?{ K key, T object } {
281
+ { .object ptrie_obj? /trie .prefix prefix, .key str_list? key }
282
+ match_str_prefix rem,
283
+ .object ptrie_obj? /trie t
284
+ } <
285
+ { .rem /nil if, .t .val /val then } .then,
286
+ {
287
+ .rem /cons .cdr key,
288
+ { .rem /cons .car char, .t .dict dict } find_in_dict object
289
+ } dot
290
+ >;
291
+
292
+ has_key? = ?{ K key, O object } { dot if, () then } .then;
293
+
294
+ -- Lookup bits? index in Patricia bit-trie list: { index, list } -> val
295
+ match_bit_prefix = ?{ P prefix, K key } {
296
+ .prefix bits? prefix,
297
+ .key bits? key
298
+ } <
299
+ { .prefix /_ if, .key then } .then,
300
+ { .prefix /0 prefix, .key /0 key } match_bit_prefix,
301
+ { .prefix /1 prefix, .key /1 key } match_bit_prefix
302
+ >;
303
+
304
+ nth = ?{ K index, T list } {
305
+ { .list ptrie_list? /trie .prefix prefix, .index bits? key }
306
+ match_bit_prefix rem,
307
+ .list ptrie_list? /trie t
308
+ } <
309
+ { .rem /_ if, .t .val /val then } .then,
310
+ { .rem /0 index, .t .0 list } nth,
311
+ { .rem /1 index, .t .1 list } nth
312
+ >;
313
+
314
+ -- Binary natural number helpers for size maintenance
315
+ _inv = ?{ < {} _, B 0, B 1 >=B x, B r } <
316
+ { .x /_ if, .r then } .then,
317
+ { .x /0 x, .r |0 r } _inv,
318
+ { .x /1 x, .r |1 r } _inv
319
+ > bits?;
320
+ _dec = ?{ < {} _, B 0, B 1 >=B x, B y } <
321
+ { .x /1 x, .y |0 r } _inv,
322
+ { .x /0 x, .y |1 y } _dec
323
+ > bits?;
324
+ _inc = ?{ < {} _, B 0, B 1 >=B x, B y } <
325
+ { .x /_ if, .y |1 then } .then,
326
+ { .x /0 x, .y |1 r } _inv,
327
+ { .x /1 x, .y |0 y } _inc
328
+ > bits?;
329
+ _trim0 = bits? < /0 _trim0, /_ 0, () >;
330
+ dec_nat = { { () x, 0b r } _inv x, 0b y } _dec _trim0;
331
+ inc_nat = { { () x, 0b r } _inv x, 0b y } _inc;
332
+
333
+ -- Remove key from radix object trie: { key, object } -> object
334
+ _remove_step = ?<
335
+ {
336
+ < {} nil, { C car, S cdr } cons >=S key,
337
+ <
338
+ {} nil,
339
+ {
340
+ S prefix,
341
+ < {} _, B 0, B 1 >=B size,
342
+ < {} nil, V val > val,
343
+ < {} nil, { { C char, T trie } car, D cdr } cons >=D dict
344
+ } trie
345
+ >=T object
346
+ } node,
347
+ { C char, S key, D dict } dict
348
+ > <
349
+ /node {
350
+ { .object /trie .prefix prefix, .key key } match_str_prefix rem,
351
+ .object /trie t
352
+ } <
353
+ {
354
+ .rem /nil if,
355
+ {
356
+ .t .prefix prefix,
357
+ .t .size dec_nat size,
358
+ nil val,
359
+ .t .dict dict
360
+ } |trie then
361
+ } .then,
362
+ {
363
+ .t .prefix prefix,
364
+ .t .size dec_nat size,
365
+ .t .val val,
366
+ {
367
+ .rem /cons .car char,
368
+ .rem /cons .cdr key,
369
+ .t .dict dict
370
+ } |dict _remove_step /dict dict
371
+ } |trie
372
+ > |node,
373
+ /dict <
374
+ {
375
+ { .char x, .dict /cons .car .char y } eq_char? if,
376
+ {
377
+ {
378
+ .char char,
379
+ {
380
+ .key key,
381
+ .dict /cons .car .trie object
382
+ } |node _remove_step /node trie
383
+ } car,
384
+ .dict /cons .cdr cdr
385
+ } |cons then
386
+ } .then,
387
+ {
388
+ .dict /cons .car car,
389
+ {
390
+ .char char,
391
+ .key key,
392
+ .dict /cons .cdr dict
393
+ } |dict _remove_step /dict cdr
394
+ } |cons
395
+ > |dict
396
+ >;
397
+
398
+ remove = ?{ K key, O object } {
399
+ .key str_list? key,
400
+ .object ptrie_obj? object
401
+ } <
402
+ {
403
+ { .key key, .object object } has_key? if,
404
+ { .key key, .object object } |node _remove_step /node then
405
+ } .then,
406
+ .object
407
+ > ptrie_obj?;
408
+
409
+ -- Split two strings into { common, rem_prefix, rem_key }
410
+ split_str_prefix = ?{
411
+ < {} nil, { C car, S cdr } cons >=S prefix,
412
+ S key
413
+ } <
414
+ {
415
+ .prefix /nil if,
416
+ { nil common, nil rem_prefix, .key rem_key } then
417
+ } .then,
418
+ {
419
+ .key /nil if,
420
+ { nil common, .prefix rem_prefix, nil rem_key } then
421
+ } .then,
422
+ {
423
+ { .prefix /cons .car x, .key /cons .car y } eq_char? if,
424
+ {
425
+ .prefix /cons .car c,
426
+ {
427
+ .prefix /cons .cdr prefix,
428
+ .key /cons .cdr key
429
+ } split_str_prefix sub
430
+ } {
431
+ { .c car, .sub .common cdr } |cons common,
432
+ .sub .rem_prefix rem_prefix,
433
+ .sub .rem_key rem_key
434
+ } then
435
+ } .then,
436
+ { nil common, .prefix rem_prefix, .key rem_key }
437
+ > ?{ S1 common, S2 rem_prefix, S3 rem_key } {
438
+ .common str_list? common,
439
+ .rem_prefix str_list? rem_prefix,
440
+ .rem_key str_list? rem_key
441
+ };
442
+
443
+ -- Replace value of an existing key in radix object trie
444
+ _put_replace = ?<
445
+ {
446
+ < {} nil, { C car, S cdr } cons >=S key,
447
+ V val,
448
+ <
449
+ {} nil,
450
+ {
451
+ S prefix,
452
+ < {} _, B 0, B 1 >=B size,
453
+ < {} nil, V val > val,
454
+ < {} nil, { { C char, T trie } car, D cdr } cons >=D dict
455
+ } trie
456
+ >=T object
457
+ } node,
458
+ { C char, S key, V val, D dict } dict
459
+ > <
460
+ /node {
461
+ { .object /trie .prefix prefix, .key key } match_str_prefix rem,
462
+ .val val,
463
+ .object /trie t
464
+ } <
465
+ {
466
+ .rem /nil if,
467
+ {
468
+ .t .prefix prefix,
469
+ .t .size size,
470
+ .val |val val,
471
+ .t .dict dict
472
+ } |trie then
473
+ } .then,
474
+ {
475
+ .t .prefix prefix,
476
+ .t .size size,
477
+ .t .val val,
478
+ {
479
+ .rem /cons .car char,
480
+ .rem /cons .cdr key,
481
+ .val val,
482
+ .t .dict dict
483
+ } |dict _put_replace /dict dict
484
+ } |trie
485
+ > |node,
486
+ /dict <
487
+ {
488
+ { .char x, .dict /cons .car .char y } eq_char? if,
489
+ {
490
+ {
491
+ .char char,
492
+ {
493
+ .key key,
494
+ .val val,
495
+ .dict /cons .car .trie object
496
+ } |node _put_replace /node trie
497
+ } car,
498
+ .dict /cons .cdr cdr
499
+ } |cons then
500
+ } .then,
501
+ {
502
+ .dict /cons .car car,
503
+ {
504
+ .char char,
505
+ .key key,
506
+ .val val,
507
+ .dict /cons .cdr dict
508
+ } |dict _put_replace /dict cdr
509
+ } |cons
510
+ > |dict
511
+ >;
512
+
513
+ -- Insert a new key into radix object trie (splitting prefixes as needed)
514
+ _put_insert = ?<
515
+ {
516
+ < {} nil, { C car, S cdr } cons >=S key,
517
+ V val,
518
+ <
519
+ {} nil,
520
+ {
521
+ S prefix,
522
+ < {} _, B 0, B 1 >=B size,
523
+ < {} nil, V val > val,
524
+ < {} nil, { { C char, T trie } car, D cdr } cons >=D dict
525
+ } trie
526
+ >=T object
527
+ } node,
528
+ { C char, S key, V val, D dict } dict
529
+ > <
530
+ /node <
531
+ {
532
+ .object /nil if,
533
+ { .key prefix, 1 size, .val |val val, nil dict } |trie then
534
+ } .then,
535
+ {
536
+ { .object /trie .prefix prefix, .key key } split_str_prefix sp,
537
+ .val val,
538
+ .object /trie t
539
+ } <
540
+ {
541
+ { .sp .rem_prefix /nil p, .sp .rem_key /nil k } if,
542
+ {
543
+ .t .prefix prefix,
544
+ .t .size inc_nat size,
545
+ .val |val val,
546
+ .t .dict dict
547
+ } |trie then
548
+ } .then,
549
+ {
550
+ { .sp .rem_prefix /nil p, .sp .rem_key /cons k } if,
551
+ {
552
+ .t .prefix prefix,
553
+ .t .size inc_nat size,
554
+ .t .val val,
555
+ {
556
+ .sp .rem_key /cons .car char,
557
+ .sp .rem_key /cons .cdr key,
558
+ .val val,
559
+ .t .dict dict
560
+ } |dict _put_insert /dict dict
561
+ } |trie then
562
+ } .then,
563
+ {
564
+ { .sp .rem_prefix /cons p, .sp .rem_key /nil k } if,
565
+ {
566
+ .sp .common prefix,
567
+ .t .size inc_nat size,
568
+ .val |val val,
569
+ {
570
+ {
571
+ .sp .rem_prefix /cons .car char,
572
+ {
573
+ .sp .rem_prefix /cons .cdr prefix,
574
+ .t .size size,
575
+ .t .val val,
576
+ .t .dict dict
577
+ } |trie trie
578
+ } car,
579
+ nil cdr
580
+ } |cons dict
581
+ } |trie then
582
+ } .then,
583
+ {
584
+ .sp .common prefix,
585
+ .t .size inc_nat size,
586
+ nil val,
587
+ {
588
+ {
589
+ .sp .rem_prefix /cons .car char,
590
+ {
591
+ .sp .rem_prefix /cons .cdr prefix,
592
+ .t .size size,
593
+ .t .val val,
594
+ .t .dict dict
595
+ } |trie trie
596
+ } car,
597
+ {
598
+ {
599
+ .sp .rem_key /cons .car char,
600
+ {
601
+ .sp .rem_key /cons .cdr prefix,
602
+ 1 size,
603
+ .val |val val,
604
+ nil dict
605
+ } |trie trie
606
+ } car,
607
+ nil cdr
608
+ } |cons cdr
609
+ } |cons dict
610
+ } |trie
611
+ >
612
+ > |node,
613
+ /dict <
614
+ {
615
+ .dict /nil if,
616
+ {
617
+ {
618
+ .char char,
619
+ { .key prefix, 1 size, .val |val val, nil dict } |trie trie
620
+ } car,
621
+ nil cdr
622
+ } |cons then
623
+ } .then,
624
+ {
625
+ { .char x, .dict /cons .car .char y } eq_char? if,
626
+ {
627
+ {
628
+ .char char,
629
+ {
630
+ .key key,
631
+ .val val,
632
+ .dict /cons .car .trie object
633
+ } |node _put_insert /node trie
634
+ } car,
635
+ .dict /cons .cdr cdr
636
+ } |cons then
637
+ } .then,
638
+ {
639
+ .dict /cons .car car,
640
+ {
641
+ .char char,
642
+ .key key,
643
+ .val val,
644
+ .dict /cons .cdr dict
645
+ } |dict _put_insert /dict cdr
646
+ } |cons
647
+ > |dict
648
+ >;
649
+
650
+ -- Insert or replace { key, val, object } -> object
651
+ put = ?{ K key, V val, O object } {
652
+ .key str_list? key,
653
+ .val json? val,
654
+ .object ptrie_obj? object
655
+ } <
656
+ {
657
+ { .key key, .object object } has_key? if,
658
+ { .key key, .val val, .object object } |node _put_replace /node then
659
+ } .then,
660
+ { .key key, .val val, .object object } |node _put_insert /node
661
+ > ptrie_obj?;
662
+
663
+