functionalscript 0.45.0 → 0.46.1
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/README.md +5 -3
- package/fjs/asn.1/module.f.mjs +8 -1
- package/fjs/asn.1/proof.f.d.mts +10 -0
- package/fjs/asn.1/proof.f.mjs +16 -0
- package/fjs/basen/base128/module.f.mjs +22 -5
- package/fjs/bnf/data/module.f.d.mts +32 -6
- package/fjs/bnf/data/module.f.mjs +112 -7
- package/fjs/bnf/data/proof.f.d.mts +2 -0
- package/fjs/bnf/data/proof.f.mjs +74 -3
- package/fjs/bnf/data/types.d.ts +20 -2
- package/fjs/bnf/descent/module.f.d.mts +28 -14
- package/fjs/bnf/descent/module.f.mjs +122 -77
- package/fjs/bnf/descent/proof.f.d.mts +2 -0
- package/fjs/bnf/descent/proof.f.mjs +117 -31
- package/fjs/bnf/descent/types.d.ts +12 -14
- package/fjs/bnf/ll1/module.f.d.mts +64 -22
- package/fjs/bnf/ll1/module.f.mjs +214 -154
- package/fjs/bnf/ll1/proof.f.d.mts +15 -2
- package/fjs/bnf/ll1/proof.f.mjs +323 -149
- package/fjs/bnf/ll1/types.d.ts +16 -24
- package/fjs/bnf/matcher/module.f.d.mts +66 -0
- package/fjs/bnf/matcher/module.f.mjs +81 -0
- package/fjs/bnf/matcher/proof.f.d.mts +10 -0
- package/fjs/bnf/matcher/proof.f.mjs +79 -0
- package/fjs/bnf/matcher/types.d.ts +54 -0
- package/fjs/bnf/testlib.f.d.mts +31 -0
- package/fjs/bnf/testlib.f.mjs +80 -0
- package/fjs/cas/cli/module.f.d.mts +1 -1
- package/fjs/cas/cli/module.f.mjs +14 -20
- package/fjs/cas/cli/proof.f.d.mts +1 -3
- package/fjs/cas/cli/proof.f.mjs +44 -33
- package/fjs/cas/evo/module.f.d.mts +64 -18
- package/fjs/cas/evo/module.f.mjs +148 -70
- package/fjs/cas/evo/proof.f.d.mts +10 -1
- package/fjs/cas/evo/proof.f.mjs +305 -223
- package/fjs/cas/evo/types.d.ts +45 -9
- package/fjs/cas/module.f.d.mts +18 -32
- package/fjs/cas/module.f.mjs +129 -128
- package/fjs/cas/proof.f.d.mts +11 -8
- package/fjs/cas/proof.f.mjs +259 -147
- package/fjs/cas/types.d.ts +24 -10
- package/fjs/ci/config/module.f.d.mts +2 -2
- package/fjs/ci/config/module.f.mjs +2 -2
- package/fjs/ci/module.f.d.mts +5 -5
- package/fjs/ci/module.f.mjs +8 -7
- package/fjs/ci/nix/module.f.d.mts +7 -5
- package/fjs/ci/nix/module.f.mjs +13 -12
- package/fjs/ci/nix/proof.f.mjs +2 -2
- package/fjs/ci/proof.f.mjs +9 -5
- package/fjs/cli/module.f.d.mts +4 -6
- package/fjs/cli/module.f.mjs +4 -8
- package/fjs/cli/proof.f.mjs +17 -16
- package/fjs/cli/types.d.ts +2 -3
- package/fjs/common/monoid/types.d.ts +1 -1
- package/fjs/crypto/hmac/module.f.mjs +2 -2
- package/fjs/crypto/sha2/module.f.mjs +3 -1
- package/fjs/crypto/sha2/proof.f.d.mts +1 -0
- package/fjs/crypto/sha2/proof.f.mjs +24 -0
- package/fjs/crypto/sha2/types.d.ts +11 -0
- package/fjs/crypto/sign/module.f.mjs +2 -2
- package/fjs/dev/module.f.d.mts +13 -4
- package/fjs/dev/module.f.mjs +56 -27
- package/fjs/dev/update/module.f.d.mts +9 -4
- package/fjs/dev/update/module.f.mjs +14 -10
- package/fjs/dev/update/proof.f.d.mts +1 -3
- package/fjs/dev/update/proof.f.mjs +10 -5
- package/fjs/djs/module.f.d.mts +13 -5
- package/fjs/djs/module.f.mjs +31 -16
- package/fjs/djs/parser/module.f.d.mts +13 -3
- package/fjs/djs/parser/module.f.mjs +117 -16
- package/fjs/djs/parser/proof.f.d.mts +5 -1
- package/fjs/djs/parser/proof.f.mjs +274 -12
- package/fjs/djs/parser/types.d.ts +7 -1
- package/fjs/djs/proof.f.d.mts +18 -2
- package/fjs/djs/proof.f.mjs +187 -12
- package/fjs/djs/serializer/module.f.d.mts +25 -8
- package/fjs/djs/serializer/module.f.mjs +61 -15
- package/fjs/djs/serializer/proof.f.d.mts +5 -0
- package/fjs/djs/serializer/proof.f.mjs +23 -1
- package/fjs/djs/tokenizer/module.f.d.mts +17 -5
- package/fjs/djs/tokenizer/module.f.mjs +99 -60
- package/fjs/djs/tokenizer/proof.f.d.mts +1 -1
- package/fjs/djs/tokenizer/proof.f.mjs +74 -67
- package/fjs/djs/transpiler/module.f.d.mts +12 -7
- package/fjs/djs/transpiler/module.f.mjs +82 -56
- package/fjs/djs/transpiler/types.d.ts +7 -3
- package/fjs/djs/types.d.ts +7 -1
- package/fjs/effects/list/module.f.d.mts +14 -11
- package/fjs/effects/list/module.f.mjs +13 -11
- package/fjs/effects/list/types.d.ts +27 -7
- package/fjs/effects/memory/module.f.d.mts +2 -1
- package/fjs/effects/memory/module.f.mjs +3 -4
- package/fjs/effects/memory/proof.f.mjs +13 -7
- package/fjs/effects/memory/types.d.ts +4 -3
- package/fjs/effects/mock/module.f.d.mts +20 -4
- package/fjs/effects/mock/module.f.mjs +37 -5
- package/fjs/effects/mock/types.d.ts +10 -1
- package/fjs/effects/module.d.mts +4 -2
- package/fjs/effects/module.f.d.mts +466 -280
- package/fjs/effects/module.f.mjs +537 -299
- package/fjs/effects/module.mjs +2 -1
- package/fjs/effects/node/memory/module.d.mts +4 -2
- package/fjs/effects/node/memory/module.mjs +6 -3
- package/fjs/effects/node/memory/proof.mjs +10 -4
- package/fjs/effects/node/module.d.mts +4 -3
- package/fjs/effects/node/module.f.d.mts +168 -33
- package/fjs/effects/node/module.f.mjs +256 -52
- package/fjs/effects/node/module.mjs +57 -34
- package/fjs/effects/node/proof.f.d.mts +28 -2
- package/fjs/effects/node/proof.f.mjs +161 -42
- package/fjs/effects/node/types.d.ts +106 -18
- package/fjs/effects/node/virtual/module.f.d.mts +18 -4
- package/fjs/effects/node/virtual/module.f.mjs +110 -68
- package/fjs/effects/node/virtual/proof.f.d.mts +28 -2
- package/fjs/effects/node/virtual/proof.f.mjs +190 -9
- package/fjs/effects/proof.f.d.mts +69 -37
- package/fjs/effects/proof.f.mjs +410 -130
- package/fjs/effects/types.d.ts +161 -33
- package/fjs/emergent_testing/module.f.d.mts +19 -12
- package/fjs/emergent_testing/module.f.mjs +93 -33
- package/fjs/emergent_testing/proof.f.d.mts +21 -7
- package/fjs/emergent_testing/proof.f.mjs +166 -32
- package/fjs/emergent_testing/types.d.ts +22 -4
- package/fjs/fsm/module.f.d.mts +14 -4
- package/fjs/fsm/module.f.mjs +54 -37
- package/fjs/fsm/proof.f.d.mts +2 -0
- package/fjs/fsm/proof.f.mjs +83 -114
- package/fjs/js/keywords/module.f.d.mts +52 -0
- package/fjs/js/keywords/module.f.mjs +72 -0
- package/fjs/js/keywords/proof.f.d.mts +3 -0
- package/fjs/js/keywords/proof.f.mjs +13 -0
- package/fjs/js/tokenizer/module.f.d.mts +26 -6
- package/fjs/js/tokenizer/module.f.mjs +145 -159
- package/fjs/js/tokenizer/proof.f.d.mts +1 -0
- package/fjs/js/tokenizer/proof.f.mjs +54 -24
- package/fjs/js/tokenizer/types.d.ts +33 -24
- package/fjs/mcp/cas/module.f.d.mts +1 -6
- package/fjs/mcp/cas/module.f.mjs +55 -51
- package/fjs/mcp/cas/proof.f.d.mts +15 -0
- package/fjs/mcp/cas/proof.f.mjs +174 -0
- package/fjs/mcp/evo/module.f.d.mts +19 -10
- package/fjs/mcp/evo/module.f.mjs +48 -27
- package/fjs/mcp/evo/proof.f.d.mts +6 -1
- package/fjs/mcp/evo/proof.f.mjs +115 -31
- package/fjs/mcp/module.f.d.mts +4 -4
- package/fjs/mcp/module.f.mjs +6 -6
- package/fjs/mcp/proof.f.d.mts +5 -3
- package/fjs/mcp/proof.f.mjs +112 -46
- package/fjs/media/html/module.f.mjs +1 -1
- package/fjs/media/json/extended/module.f.d.mts +82 -0
- package/fjs/media/json/extended/module.f.mjs +153 -0
- package/fjs/media/json/extended/proof.f.d.mts +42 -0
- package/fjs/media/json/extended/proof.f.mjs +127 -0
- package/fjs/media/json/extended/types.d.ts +23 -0
- package/fjs/media/json/module.f.d.mts +8 -2
- package/fjs/media/json/module.f.mjs +43 -41
- package/fjs/media/json/number/module.f.d.mts +59 -0
- package/fjs/media/json/number/module.f.mjs +136 -0
- package/fjs/media/json/number/proof.f.d.mts +24 -0
- package/fjs/media/json/number/proof.f.mjs +86 -0
- package/fjs/media/json/number/types.d.ts +28 -0
- package/fjs/media/json/parser/module.f.d.mts +25 -13
- package/fjs/media/json/parser/module.f.mjs +114 -70
- package/fjs/media/json/parser/proof.f.d.mts +5 -0
- package/fjs/media/json/parser/proof.f.mjs +31 -1
- package/fjs/media/json/parser/types.d.ts +33 -14
- package/fjs/media/json/rtti/module.f.d.mts +1 -1
- package/fjs/media/json/rtti/module.f.mjs +1 -1
- package/fjs/media/json/rtti/proof.f.mjs +9 -9
- package/fjs/media/json/schema/module.f.mjs +3 -13
- package/fjs/media/json/schema/proof.f.d.mts +0 -1
- package/fjs/media/json/schema/proof.f.mjs +1 -2
- package/fjs/media/json/serializer/module.f.d.mts +32 -1
- package/fjs/media/json/serializer/module.f.mjs +64 -2
- package/fjs/media/json/tokenizer/module.f.mjs +7 -3
- package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
- package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
- package/fjs/media/json/types.d.ts +36 -10
- package/fjs/media/lock/module.f.d.mts +100 -0
- package/fjs/media/lock/module.f.mjs +125 -0
- package/fjs/media/lock/proof.f.d.mts +33 -0
- package/fjs/media/lock/proof.f.mjs +196 -0
- package/fjs/media/lock/types.d.ts +15 -0
- package/fjs/media/module.f.d.mts +6 -5
- package/fjs/media/module.f.mjs +8 -7
- package/fjs/media/note/module.f.d.mts +121 -0
- package/fjs/media/note/module.f.mjs +131 -0
- package/fjs/media/note/proof.f.d.mts +29 -0
- package/fjs/media/note/proof.f.mjs +150 -0
- package/fjs/media/note/types.d.ts +10 -0
- package/fjs/media/proof.f.d.mts +4 -1
- package/fjs/media/proof.f.mjs +40 -21
- package/fjs/media/revision/module.f.d.mts +78 -7
- package/fjs/media/revision/module.f.mjs +119 -12
- package/fjs/media/revision/proof.f.d.mts +10 -0
- package/fjs/media/revision/proof.f.mjs +88 -0
- package/fjs/media/revision/types.d.ts +34 -5
- package/fjs/media/type/module.f.d.mts +33 -15
- package/fjs/media/type/module.f.mjs +35 -29
- package/fjs/media/type/proof.f.d.mts +2 -1
- package/fjs/media/type/proof.f.mjs +30 -10
- package/fjs/module.f.mjs +29 -8
- package/fjs/nanvm/proof.f.mjs +3 -3
- package/fjs/nanvm/rust/module.f.mjs +1 -1
- package/fjs/nanvm/update/module.f.d.mts +4 -4
- package/fjs/nanvm/update/module.f.mjs +8 -9
- package/fjs/nanvm/update/proof.f.mjs +4 -3
- package/fjs/proof.f.d.mts +3 -3
- package/fjs/proof.f.mjs +36 -10
- package/fjs/protocol/json_rpc/module.f.d.mts +2 -2
- package/fjs/protocol/json_rpc/module.f.mjs +3 -3
- package/fjs/protocol/json_rpc/proof.f.mjs +4 -4
- package/fjs/protocol/mcp/module.f.d.mts +10 -13
- package/fjs/protocol/mcp/module.f.mjs +74 -58
- package/fjs/protocol/mcp/proof.f.d.mts +13 -4
- package/fjs/protocol/mcp/proof.f.mjs +193 -61
- package/fjs/protocol/mcp/stdio/module.f.d.mts +15 -7
- package/fjs/protocol/mcp/stdio/module.f.mjs +38 -25
- package/fjs/protocol/mcp/stdio/proof.f.d.mts +4 -2
- package/fjs/protocol/mcp/stdio/proof.f.mjs +45 -12
- package/fjs/protocol/mcp/stdio/types.d.ts +1 -1
- package/fjs/protocol/mcp/types.d.ts +17 -6
- package/fjs/sul/id/module.f.d.mts +0 -1
- package/fjs/sul/id/module.f.mjs +2 -3
- package/fjs/sul/level/hash/module.f.mjs +2 -1
- package/fjs/sul/level/hash/proof.f.mjs +2 -2
- package/fjs/sul/module.f.mjs +18 -13
- package/fjs/text/code_point/module.f.d.mts +8 -0
- package/fjs/text/code_point/module.f.mjs +8 -1
- package/fjs/text/code_point/proof.f.d.mts +1 -0
- package/fjs/text/code_point/proof.f.mjs +11 -0
- package/fjs/text/sgr/module.f.d.mts +4 -6
- package/fjs/text/sgr/module.f.mjs +6 -7
- package/fjs/text/utf16/module.f.mjs +7 -2
- package/fjs/text/utf16/proof.f.mjs +3 -3
- package/fjs/text/utf8/module.f.mjs +4 -2
- package/fjs/types/array/module.f.mjs +14 -2
- package/fjs/types/bit_vec/module.f.d.mts +0 -2
- package/fjs/types/bit_vec/module.f.mjs +46 -32
- package/fjs/types/bit_vec/proof.f.mjs +2 -2
- package/fjs/types/btree/remove/module.f.mjs +1 -1
- package/fjs/types/btree/set/module.f.mjs +9 -11
- package/fjs/types/btree/set/proof.f.mjs +12 -0
- package/fjs/types/byte_set/module.f.d.mts +11 -4
- package/fjs/types/byte_set/module.f.mjs +14 -6
- package/fjs/types/byte_set/proof.f.mjs +7 -7
- package/fjs/types/function/compare/module.f.mjs +10 -3
- package/fjs/types/list/module.f.d.mts +1 -1
- package/fjs/types/list/module.f.mjs +1 -1
- package/fjs/types/nullable/module.f.d.mts +18 -4
- package/fjs/types/nullable/module.f.mjs +21 -4
- package/fjs/types/nullable/proof.f.d.mts +4 -0
- package/fjs/types/nullable/proof.f.mjs +15 -0
- package/fjs/types/object/module.f.d.mts +12 -2
- package/fjs/types/object/module.f.mjs +11 -1
- package/fjs/types/patricia_trie/module.f.mjs +26 -11
- package/fjs/types/result/module.f.d.mts +3 -3
- package/fjs/types/result/module.f.mjs +3 -3
- package/fjs/types/rtti/common/module.f.d.mts +25 -28
- package/fjs/types/rtti/common/module.f.mjs +36 -32
- package/fjs/types/rtti/common/proof.f.mjs +5 -5
- package/fjs/types/rtti/data/module.f.d.mts +14 -0
- package/fjs/types/rtti/data/module.f.mjs +25 -2
- package/fjs/types/rtti/data/proof.f.d.mts +1 -0
- package/fjs/types/rtti/data/proof.f.mjs +25 -2
- package/fjs/types/rtti/parse/module.f.d.mts +24 -14
- package/fjs/types/rtti/parse/module.f.mjs +37 -28
- package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
- package/fjs/types/rtti/parse/proof.f.mjs +33 -14
- package/fjs/types/rtti/proof.f.mjs +3 -1
- package/fjs/types/rtti/ts/module.f.mjs +13 -17
- package/fjs/types/rtti/ts/types.d.ts +14 -1
- package/fjs/types/rtti/validate/module.f.d.mts +81 -19
- package/fjs/types/rtti/validate/module.f.mjs +107 -61
- package/fjs/types/rtti/validate/proof.f.d.mts +13 -10
- package/fjs/types/rtti/validate/proof.f.mjs +186 -197
- package/fjs/types/sorted_set/module.f.d.mts +18 -0
- package/fjs/types/sorted_set/module.f.mjs +22 -0
- package/fjs/types/sorted_set/proof.f.d.mts +1 -0
- package/fjs/types/sorted_set/proof.f.mjs +16 -1
- package/fjs/types/uint8array/module.f.d.mts +1 -1
- package/fjs/types/uint8array/module.f.mjs +1 -1
- package/fjs/website/module.f.d.mts +3 -3
- package/fjs/website/module.f.mjs +4 -7
- package/fjs/website/proof.f.mjs +2 -1
- package/package.json +2 -2
- package/fjs/dev/package_json/module.f.d.mts +0 -39
- package/fjs/dev/package_json/module.f.mjs +0 -40
- package/fjs/dev/package_json/proof.f.d.mts +0 -6
- package/fjs/dev/package_json/proof.f.mjs +0 -32
- package/fjs/effects/eff/module.f.d.mts +0 -20
- package/fjs/effects/eff/module.f.mjs +0 -70
- package/fjs/effects/eff/proof.f.d.mts +0 -15
- package/fjs/effects/eff/proof.f.mjs +0 -69
- package/fjs/effects/eff/types.d.ts +0 -71
- package/fjs/types/rtti/validate/types.d.ts +0 -6
|
@@ -172,8 +172,6 @@ const op = norm => op => ap => bp => {
|
|
|
172
172
|
|
|
173
173
|
/**
|
|
174
174
|
* @typedef {{
|
|
175
|
-
* readonly front: (len: bigint) => (v: Vec) => bigint
|
|
176
|
-
* readonly removeFront: (len: bigint) => (v: Vec) => Vec
|
|
177
175
|
* readonly norm: _NormOp
|
|
178
176
|
* readonly uintCmp: (a: bigint) => (b: bigint) => Sign
|
|
179
177
|
* readonly unpackSplit: (len: bigint) => (u: Unpacked) => readonly[bigint, bigint]
|
|
@@ -183,6 +181,15 @@ const op = norm => op => ap => bp => {
|
|
|
183
181
|
|
|
184
182
|
const unpackEmpty = /** @type {const} */{ length: 0n, uint: 0n }
|
|
185
183
|
|
|
184
|
+
/**
|
|
185
|
+
* The element-to-`Unpacked` maps the two {@link mappedListToVec} instances
|
|
186
|
+
* differ by. Neither depends on a bit order, so both are bound once here
|
|
187
|
+
* (`fjs/AGENTS.md` §3.3).
|
|
188
|
+
*
|
|
189
|
+
* @type {(_: number) => Unpacked}
|
|
190
|
+
*/
|
|
191
|
+
const u8ToUnpacked = b => ({ length: 8n, uint: BigInt(b) })
|
|
192
|
+
|
|
186
193
|
/**
|
|
187
194
|
* Concatenation as a monoid over `Nullable<Unpacked>`, where `null` means "the
|
|
188
195
|
* concatenation is longer than `maxLength`" and is an **absorbing** element:
|
|
@@ -198,7 +205,7 @@ const unpackEmpty = /** @type {const} */{ length: 0n, uint: 0n }
|
|
|
198
205
|
* result because the result is what must not be built: `maxLength` is the
|
|
199
206
|
* smallest `bigint` size supported across FunctionalScript's runtimes. The two
|
|
200
207
|
* lengths are exact and additive — this is the length, not an estimate of it
|
|
201
|
-
* (
|
|
208
|
+
* (`DESIGN.md` §6).
|
|
202
209
|
*
|
|
203
210
|
* Being absorbing is also what keeps the fold's walk bounded: `foldAbsorbing`
|
|
204
211
|
* stops at the first merge that overflows instead of reading the rest of a list
|
|
@@ -241,8 +248,26 @@ const tryUnpackConcat = unpackConcat => ({
|
|
|
241
248
|
const unpackListToVec = unpackConcat =>
|
|
242
249
|
compose(foldAbsorbing(tryUnpackConcat(unpackConcat)))(nullableMap(pack))
|
|
243
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Concatenates a list of `I` values into one vector, mapping each element to
|
|
253
|
+
* its `Unpacked` form first; `null` when the result would exceed `maxLength`.
|
|
254
|
+
*
|
|
255
|
+
* The concatenation counterpart of {@link mappedChunkList}. Everything about
|
|
256
|
+
* the operation is fixed except how one element becomes `Unpacked`, so each
|
|
257
|
+
* element type supplies just that map. The `bo` parameter is structural rather
|
|
258
|
+
* than a whole `BitOrder` because `bo`'s own body applies this before the
|
|
259
|
+
* record exists.
|
|
260
|
+
*
|
|
261
|
+
* @type {<I>(g: (i: I) => Unpacked) => (bo: { readonly unpackConcat: _UnpackConcat }) => (list: List<I>) => Nullable<Vec>}
|
|
262
|
+
*/
|
|
263
|
+
const mappedListToVec = g => ({ unpackConcat }) => {
|
|
264
|
+
const f = unpackListToVec(unpackConcat)
|
|
265
|
+
const mg = map(g)
|
|
266
|
+
return list => f(mg(list))
|
|
267
|
+
}
|
|
268
|
+
|
|
244
269
|
/** @type {(base: _Base) => BitOrder} */
|
|
245
|
-
const bo = ({
|
|
270
|
+
const bo = ({ norm, uintCmp, unpackSplit, unpackConcatUint }) => {
|
|
246
271
|
/** @param {bigint} len */
|
|
247
272
|
const unpackPopFront = len => {
|
|
248
273
|
const m = mask(len)
|
|
@@ -253,6 +278,19 @@ const bo = ({ front, removeFront, norm, uintCmp, unpackSplit, unpackConcatUint }
|
|
|
253
278
|
return /** @type {const} */([uint & m, { length: v.length - len, uint: rest }])
|
|
254
279
|
}
|
|
255
280
|
}
|
|
281
|
+
// `front` and `removeFront` are the two projections of `unpackPopFront`,
|
|
282
|
+
// so each bit order supplies only `unpackSplit` and both fall out of it.
|
|
283
|
+
// `pack` re-masks, so `removeFront` can hand on the unmasked rest.
|
|
284
|
+
/** @type {(len: bigint) => (v: Vec) => bigint} */
|
|
285
|
+
const front = len => {
|
|
286
|
+
const f = unpackPopFront(len)
|
|
287
|
+
return v => f(unpack(v))[0]
|
|
288
|
+
}
|
|
289
|
+
/** @type {(len: bigint) => (v: Vec) => Vec} */
|
|
290
|
+
const removeFront = len => {
|
|
291
|
+
const f = unpackPopFront(len)
|
|
292
|
+
return v => pack(f(unpack(v))[1])
|
|
293
|
+
}
|
|
256
294
|
/** @type {_UnpackConcat} */
|
|
257
295
|
const unpackConcat = a => b => ({
|
|
258
296
|
length: a.length + b.length,
|
|
@@ -272,9 +310,7 @@ const bo = ({ front, removeFront, norm, uintCmp, unpackSplit, unpackConcatUint }
|
|
|
272
310
|
const bu = unpack(b)
|
|
273
311
|
return pack(unpackConcat(au)(bu))
|
|
274
312
|
}
|
|
275
|
-
const
|
|
276
|
-
/** @param {List<Vec>} list */
|
|
277
|
-
const tryListToVec = list => unpackedListToVec(map(unpack)(list))
|
|
313
|
+
const tryListToVec = mappedListToVec(unpack)({ unpackConcat })
|
|
278
314
|
return {
|
|
279
315
|
front,
|
|
280
316
|
removeFront,
|
|
@@ -298,7 +334,8 @@ const bo = ({ front, removeFront, norm, uintCmp, unpackSplit, unpackConcatUint }
|
|
|
298
334
|
unpackConcat,
|
|
299
335
|
startsWith: prefix => {
|
|
300
336
|
const { length: n, uint: u } = unpack(prefix)
|
|
301
|
-
|
|
337
|
+
const f = front(n)
|
|
338
|
+
return v => length(v) < n ? false : f(v) === u
|
|
302
339
|
}
|
|
303
340
|
}
|
|
304
341
|
}
|
|
@@ -315,14 +352,6 @@ const lsbUnpackConcatUint =
|
|
|
315
352
|
* Usually associated with Little-Endian (LE) byte order.
|
|
316
353
|
*/
|
|
317
354
|
export const lsb = bo({
|
|
318
|
-
front: len => {
|
|
319
|
-
const m = mask(len)
|
|
320
|
-
return v => uint(v) & m
|
|
321
|
-
},
|
|
322
|
-
removeFront: len => v => {
|
|
323
|
-
const { length, uint } = unpack(v)
|
|
324
|
-
return vec(length - len)(uint >> len)
|
|
325
|
-
},
|
|
326
355
|
norm: ({ uint: a }) => ({ uint: b }) => () =>
|
|
327
356
|
({ a, b }),
|
|
328
357
|
uintCmp: a => b => {
|
|
@@ -341,17 +370,6 @@ export const lsb = bo({
|
|
|
341
370
|
* Usually associated with Big-Endian (BE) byte order.
|
|
342
371
|
*/
|
|
343
372
|
export const msb = bo({
|
|
344
|
-
front: len => {
|
|
345
|
-
const m = mask(len)
|
|
346
|
-
return v => {
|
|
347
|
-
const { length, uint } = unpack(v)
|
|
348
|
-
return (uint >> (length - len)) & m
|
|
349
|
-
}
|
|
350
|
-
},
|
|
351
|
-
removeFront: len => v => {
|
|
352
|
-
const { length, uint } = unpack(v)
|
|
353
|
-
return vec(length - len)(uint)
|
|
354
|
-
},
|
|
355
373
|
norm: ({ length: al, uint: a }) => ({ length: bl, uint: b }) => len =>
|
|
356
374
|
({ a: a << (len - al), b: b << (len - bl) }),
|
|
357
375
|
uintCmp: cmp,
|
|
@@ -366,11 +384,7 @@ export const msb = bo({
|
|
|
366
384
|
*
|
|
367
385
|
* @type {(_: BitOrder) => (list: List<number>) => Nullable<Vec>}
|
|
368
386
|
*/
|
|
369
|
-
export const tryU8ListToVec = (
|
|
370
|
-
const unpackedListToVec = unpackListToVec(unpackConcat)
|
|
371
|
-
return list => unpackedListToVec(
|
|
372
|
-
map(/** @type {(_: number) => Unpacked} */b => ({ length: 8n, uint: BigInt(b) }))(list))
|
|
373
|
-
}
|
|
387
|
+
export const tryU8ListToVec = mappedListToVec(u8ToUnpacked)
|
|
374
388
|
|
|
375
389
|
/**
|
|
376
390
|
* Converts a list of unsigned 8-bit integers to a bit vector using the provided bit order.
|
|
@@ -193,9 +193,9 @@ export const proof = {
|
|
|
193
193
|
},
|
|
194
194
|
removeBack: () => {
|
|
195
195
|
const v = vec(17n)(0x12345n)
|
|
196
|
-
assertEq(v, unsafeVec(0x12345n), (
|
|
196
|
+
assertEq(v, unsafeVec(0x12345n), (asBase(v)).toString(16))
|
|
197
197
|
const r = lsb.removeFront(9n)(v)
|
|
198
|
-
assertEq(r, unsafeVec(0x91n), (
|
|
198
|
+
assertEq(r, unsafeVec(0x91n), (asBase(r)).toString(16))
|
|
199
199
|
},
|
|
200
200
|
uint: [
|
|
201
201
|
// 0
|
|
@@ -130,7 +130,7 @@ export const nodeRemove = c => node => {
|
|
|
130
130
|
const { first, tail } = find(c)(node)
|
|
131
131
|
/** @type {(n: TNode<T>) => (f: (v: T) => PathItem<T>) => _RemovePath<T>} */
|
|
132
132
|
const branch = n => f => {
|
|
133
|
-
const [v, p] = path(
|
|
133
|
+
const [v, p] = path(null)(n)
|
|
134
134
|
return { first: p.first, tail: concat(p.tail)({ first: f(v), tail }) }
|
|
135
135
|
}
|
|
136
136
|
const [i, n] = first
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { collapseRoot } from '../types/module.f.mjs'
|
|
12
12
|
import { find } from '../find/module.f.mjs'
|
|
13
13
|
import { fold } from '../../list/module.f.mjs'
|
|
14
|
+
import { assert } from '../../../asserts/module.f.mjs'
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* @template T
|
|
@@ -80,30 +81,27 @@ const nodeSet = c => g => node => {
|
|
|
80
81
|
// insert
|
|
81
82
|
const value = g(null)
|
|
82
83
|
// TODO: remove after TSGO fix the regression.
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
const xL = x.length
|
|
85
|
+
// See https://github.com/microsoft/typescript-go/issues/4613
|
|
86
|
+
assert(xL === 1 || xL === 2)
|
|
87
|
+
switch (xL) {
|
|
85
88
|
case 1: { return [[x[0], value]] }
|
|
86
89
|
case 2: { return [[x[0]], value, [x[1]]] }
|
|
87
90
|
}
|
|
88
|
-
// TODO: remove after TSGO fix the regression.
|
|
89
|
-
// See https://github.com/microsoft/typescript-go/issues/4613
|
|
90
|
-
throw 'unreachable'
|
|
91
91
|
}
|
|
92
92
|
case 3: {
|
|
93
93
|
// replace
|
|
94
94
|
// TODO: remove after TSGO fix the regression.
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
const xL = x.length
|
|
96
|
+
// See https://github.com/microsoft/typescript-go/issues/4613
|
|
97
|
+
assert(xL === 2 || xL === 5)
|
|
98
|
+
switch (xL) {
|
|
97
99
|
case 2: { return [[x[0], g(x[1])]] }
|
|
98
100
|
case 5: { return [[x[0], x[1], x[2], g(x[3]), x[4]]] }
|
|
99
101
|
}
|
|
100
|
-
// TODO: remove after TSGO fix the regression.
|
|
101
|
-
throw 'unreachable'
|
|
102
102
|
}
|
|
103
103
|
case 4: {
|
|
104
104
|
// insert
|
|
105
|
-
// TODO: remove after TSGO fix the regression.
|
|
106
|
-
// const _xl: 2 = x.length
|
|
107
105
|
const [v0, v1] = x
|
|
108
106
|
return [[v0], v1, [g(null)]]
|
|
109
107
|
}
|
|
@@ -424,6 +424,18 @@ const test = [
|
|
|
424
424
|
jsonStr(replacedSecond),
|
|
425
425
|
'[[["1"],"100",["121","144"]],"16",[["169"],"25",["36"]],"4-updated",[["49"],"64",["81","9"]]]',
|
|
426
426
|
)
|
|
427
|
+
},
|
|
428
|
+
|
|
429
|
+
// Replacing the first value of a two-value leaf exercises the
|
|
430
|
+
// `x.length === 2` arm of the `i === 1` "replace" case, which the
|
|
431
|
+
// fixtures above never reach — their two-value-leaf replaces all land on
|
|
432
|
+
// the second value.
|
|
433
|
+
() => {
|
|
434
|
+
/** @type {TNode<string>} */
|
|
435
|
+
const _map = set(['1'])('2')
|
|
436
|
+
assertEq(jsonStr(_map), '["1","2"]')
|
|
437
|
+
const replaced = replace(_map)('1')(() => '1-updated')
|
|
438
|
+
assertEq(jsonStr(replaced), '["1-updated","2"]')
|
|
427
439
|
}
|
|
428
440
|
]
|
|
429
441
|
|
|
@@ -5,11 +5,9 @@
|
|
|
5
5
|
* @module
|
|
6
6
|
*
|
|
7
7
|
* @import { RangeMap } from '../range_map/types.ts'
|
|
8
|
-
* @import { SortedSet } from '../sorted_set/types.ts'
|
|
9
8
|
* @import { ByteSet } from './types.ts'
|
|
10
9
|
*/
|
|
11
10
|
import type { RangeMap } from '../range_map/types.ts';
|
|
12
|
-
import type { SortedSet } from '../sorted_set/types.ts';
|
|
13
11
|
import type { ByteSet } from './types.ts';
|
|
14
12
|
export type _Byte = number;
|
|
15
13
|
/** @typedef {number} _Byte */
|
|
@@ -31,5 +29,14 @@ export declare const set: (_: number) => (b: ByteSet) => ByteSet;
|
|
|
31
29
|
export declare const setRange: (_: readonly [number, number]) => (b: ByteSet) => ByteSet;
|
|
32
30
|
/** @type {(n: _Byte) => (s: ByteSet) => ByteSet} */
|
|
33
31
|
export declare const unset: (n: _Byte) => (s: ByteSet) => ByteSet;
|
|
34
|
-
/**
|
|
35
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Re-expresses the set as a range map: one entry per membership boundary,
|
|
34
|
+
* carrying whether the range up to that byte is in the set.
|
|
35
|
+
*
|
|
36
|
+
* The payload is the set's own answer — `boolean` — and nothing more. A caller
|
|
37
|
+
* that needs ranges labelled with something else maps over the result; that
|
|
38
|
+
* labelling belongs to the caller, not to a byte set.
|
|
39
|
+
*
|
|
40
|
+
* @type {(n: ByteSet) => RangeMap<boolean>}
|
|
41
|
+
*/
|
|
42
|
+
export declare const toRangeMap: (n: ByteSet) => RangeMap<boolean>;
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* @module
|
|
6
6
|
*
|
|
7
7
|
* @import { RangeMap } from '../range_map/types.ts'
|
|
8
|
-
* @import { SortedSet } from '../sorted_set/types.ts'
|
|
9
8
|
* @import { ByteSet } from './types.ts'
|
|
10
9
|
*/
|
|
11
10
|
|
|
@@ -57,12 +56,21 @@ export const unset = n => s => difference(s)(one(n))
|
|
|
57
56
|
|
|
58
57
|
const counter = reverse(countdown(256))
|
|
59
58
|
|
|
60
|
-
/** @type {(n: ByteSet) => (
|
|
61
|
-
const toRangeMapOp = n =>
|
|
59
|
+
/** @type {(n: ByteSet) => (i: number) => RangeMap<boolean>} */
|
|
60
|
+
const toRangeMapOp = n => i => {
|
|
62
61
|
const current = has(i + 1)(n)
|
|
63
62
|
const prev = has(i)(n)
|
|
64
|
-
return current === prev ? null : [[prev
|
|
63
|
+
return current === prev ? null : [[prev, i]]
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
/**
|
|
68
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Re-expresses the set as a range map: one entry per membership boundary,
|
|
68
|
+
* carrying whether the range up to that byte is in the set.
|
|
69
|
+
*
|
|
70
|
+
* The payload is the set's own answer — `boolean` — and nothing more. A caller
|
|
71
|
+
* that needs ranges labelled with something else maps over the result; that
|
|
72
|
+
* labelling belongs to the caller, not to a byte set.
|
|
73
|
+
*
|
|
74
|
+
* @type {(n: ByteSet) => RangeMap<boolean>}
|
|
75
|
+
*/
|
|
76
|
+
export const toRangeMap = n => flat(map(toRangeMapOp(n))(counter))
|
|
@@ -65,22 +65,22 @@ export const proof = {
|
|
|
65
65
|
},
|
|
66
66
|
toRangeMap: [
|
|
67
67
|
() => {
|
|
68
|
-
const result = stringify(toArray(toRangeMap(empty)
|
|
68
|
+
const result = stringify(toArray(toRangeMap(empty)))
|
|
69
69
|
assertEq(result, '[]')
|
|
70
70
|
},
|
|
71
71
|
() => {
|
|
72
72
|
const s = set(0)(empty)
|
|
73
|
-
const result = stringify(toArray(toRangeMap(s)
|
|
74
|
-
assertEq(result, '[[
|
|
73
|
+
const result = stringify(toArray(toRangeMap(s)))
|
|
74
|
+
assertEq(result, '[[true,0]]')
|
|
75
75
|
},
|
|
76
76
|
() => {
|
|
77
77
|
const s = setRange([1, 2])(empty)
|
|
78
|
-
const result = stringify(toArray(toRangeMap(s)
|
|
79
|
-
assertEq(result, '[[
|
|
78
|
+
const result = stringify(toArray(toRangeMap(s)))
|
|
79
|
+
assertEq(result, '[[false,0],[true,2]]')
|
|
80
80
|
},
|
|
81
81
|
() => {
|
|
82
|
-
const result = stringify(toArray(toRangeMap(universe)
|
|
83
|
-
assertEq(result, '[[
|
|
82
|
+
const result = stringify(toArray(toRangeMap(universe)))
|
|
83
|
+
assertEq(result, '[[true,255]]')
|
|
84
84
|
},
|
|
85
85
|
]
|
|
86
86
|
}
|
|
@@ -7,14 +7,21 @@
|
|
|
7
7
|
* @import { Cmp1, Cmp2, Compare, Sign } from './types.ts'
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { assert } from '../../../asserts/module.f.mjs'
|
|
11
|
+
|
|
10
12
|
/** @type {<T>(cmp: Compare<T>) => (value: T) => Index<3>} */
|
|
11
|
-
export const index3
|
|
12
|
-
|
|
13
|
+
export const index3 = cmp => value => {
|
|
14
|
+
const i = cmp(value) + 1
|
|
15
|
+
assert(i === 0 || i === 1 || i === 2, i)
|
|
16
|
+
return i
|
|
17
|
+
}
|
|
13
18
|
|
|
14
19
|
/** @type {<T>(cmp: Compare<T>) => (v2: Tuple<2, T>) => Index<5>} */
|
|
15
20
|
export const index5 = cmp => ([v0, v1]) => {
|
|
16
21
|
const _0 = cmp(v0)
|
|
17
|
-
|
|
22
|
+
const i = _0 <= 0 ? _0 + 1 : cmp(v1) + 3
|
|
23
|
+
assert(i === 0 || i === 1 || i === 2 || i === 3 || i === 4, i)
|
|
24
|
+
return i
|
|
18
25
|
}
|
|
19
26
|
|
|
20
27
|
/** @type {<A extends Cmp1>(a: A) => <B extends Cmp2<A, B>>(b: B) => Sign} */
|
|
@@ -77,7 +77,7 @@ export declare const reduce: <T>(op: Reduce<T>) => <D>(def: D) => (input: List<T
|
|
|
77
77
|
* Folds `input` with an {@link Accumulator}, short-circuiting to `null` the
|
|
78
78
|
* moment `update` rejects an item; otherwise finalizes with `end`. This is the
|
|
79
79
|
* list-level `try*` sibling of {@link fold} for accumulations that can fail
|
|
80
|
-
* partway through (see the `try*`/`Nullable` convention in `
|
|
80
|
+
* partway through (see the `try*`/`Nullable` convention in `DESIGN.md` §6).
|
|
81
81
|
*
|
|
82
82
|
* @type {<I, T, R>({ init, update, end }: Accumulator<I, T, R>) => (input: List<I>) => Nullable<R>}
|
|
83
83
|
*/
|
|
@@ -238,7 +238,7 @@ export const reduce = op => def => compose(scan(reduceToScan(op)))(last(def))
|
|
|
238
238
|
* Folds `input` with an {@link Accumulator}, short-circuiting to `null` the
|
|
239
239
|
* moment `update` rejects an item; otherwise finalizes with `end`. This is the
|
|
240
240
|
* list-level `try*` sibling of {@link fold} for accumulations that can fail
|
|
241
|
-
* partway through (see the `try*`/`Nullable` convention in `
|
|
241
|
+
* partway through (see the `try*`/`Nullable` convention in `DESIGN.md` §6).
|
|
242
242
|
*
|
|
243
243
|
* @type {<I, T, R>({ init, update, end }: Accumulator<I, T, R>) => (input: List<I>) => Nullable<R>}
|
|
244
244
|
*/
|
|
@@ -9,13 +9,27 @@
|
|
|
9
9
|
import type { Option } from '../option/types.ts';
|
|
10
10
|
import type { Nullable } from './types.ts';
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Folds a `Nullable<T>` into a single value: `f` for a present value, `none`
|
|
13
|
+
* for `null`.
|
|
14
|
+
*
|
|
15
|
+
* The two branches carry independent result types, and `R2` lives on its own
|
|
16
|
+
* curry step on purpose. With `T`, `R1` and `R2` all on the outer generic they
|
|
17
|
+
* are instantiated together at `match(f)` — before `none` exists — so `R2` has
|
|
18
|
+
* nothing to infer from and collapses to `unknown`. Inferring it at the second
|
|
19
|
+
* call instead is what lets {@link map} be derived below.
|
|
20
|
+
*
|
|
21
|
+
* @type {<T, R1>(f: (_: T) => R1) => <R2>(none: () => R2) => (_: Nullable<T>) => R1 | R2}
|
|
13
22
|
*/
|
|
14
|
-
export declare const
|
|
23
|
+
export declare const match: <T, R1>(f: (_: T) => R1) => <R2>(none: () => R2) => (_: Nullable<T>) => R1 | R2;
|
|
15
24
|
/**
|
|
16
|
-
*
|
|
25
|
+
* Projects the present value of a `Nullable<T>`, passing `null` through.
|
|
26
|
+
*
|
|
27
|
+
* `map` is `match` with the absent branch fixed to `null`, so the
|
|
28
|
+
* `value === null` guard is written once, in `match`.
|
|
29
|
+
*
|
|
30
|
+
* @type {<T, R>(f: (value: T) => R) => (value: Nullable<T>) => Nullable<R>}
|
|
17
31
|
*/
|
|
18
|
-
export declare const
|
|
32
|
+
export declare const map: <T, R>(f: (value: T) => R) => (value: Nullable<T>) => Nullable<R>;
|
|
19
33
|
/**
|
|
20
34
|
* @type {<T>(value: Nullable<T>) => Option<T>}
|
|
21
35
|
*/
|
|
@@ -11,14 +11,31 @@ import { assert } from '../../asserts/module.f.mjs'
|
|
|
11
11
|
import { fn } from '../function/module.f.mjs'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Folds a `Nullable<T>` into a single value: `f` for a present value, `none`
|
|
15
|
+
* for `null`.
|
|
16
|
+
*
|
|
17
|
+
* The two branches carry independent result types, and `R2` lives on its own
|
|
18
|
+
* curry step on purpose. With `T`, `R1` and `R2` all on the outer generic they
|
|
19
|
+
* are instantiated together at `match(f)` — before `none` exists — so `R2` has
|
|
20
|
+
* nothing to infer from and collapses to `unknown`. Inferring it at the second
|
|
21
|
+
* call instead is what lets {@link map} be derived below.
|
|
22
|
+
*
|
|
23
|
+
* @type {<T, R1>(f: (_: T) => R1) => <R2>(none: () => R2) => (_: Nullable<T>) => R1 | R2}
|
|
15
24
|
*/
|
|
16
|
-
export const
|
|
25
|
+
export const match = f => none => value => value === null ? none() : f(value)
|
|
26
|
+
|
|
27
|
+
/** The absent branch `map` fixes `match`'s `none` to. */
|
|
28
|
+
const noneIsNull = () => null
|
|
17
29
|
|
|
18
30
|
/**
|
|
19
|
-
*
|
|
31
|
+
* Projects the present value of a `Nullable<T>`, passing `null` through.
|
|
32
|
+
*
|
|
33
|
+
* `map` is `match` with the absent branch fixed to `null`, so the
|
|
34
|
+
* `value === null` guard is written once, in `match`.
|
|
35
|
+
*
|
|
36
|
+
* @type {<T, R>(f: (value: T) => R) => (value: Nullable<T>) => Nullable<R>}
|
|
20
37
|
*/
|
|
21
|
-
export const
|
|
38
|
+
export const map = f => match(f)(noneIsNull)
|
|
22
39
|
|
|
23
40
|
/**
|
|
24
41
|
* @type {<T>(value: Nullable<T>) => Option<T>}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { Assert } from '../../asserts/types.ts'
|
|
3
|
+
* @import { Equal } from '../ts/types.ts'
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
import { fromUndefined, map, match, toOption } from './module.f.mjs'
|
|
2
7
|
import { assert, assertEq } from '../../asserts/module.f.mjs'
|
|
3
8
|
|
|
@@ -24,6 +29,16 @@ export const proof = [
|
|
|
24
29
|
assertEq(double(3), 6)
|
|
25
30
|
assertEq(double(null), -1)
|
|
26
31
|
},
|
|
32
|
+
() => {
|
|
33
|
+
// The two branches carry independent result types: `describe` is
|
|
34
|
+
// `(_: Nullable<number>) => number | string`, not one unified `R`.
|
|
35
|
+
/** @type {(v: number) => number} */
|
|
36
|
+
const twice = v => v * 2
|
|
37
|
+
const describe = match(twice)(() => 'none')
|
|
38
|
+
/** @typedef {Assert<Equal<ReturnType<typeof describe>, number | string>>} _Branches */
|
|
39
|
+
assertEq(describe(3), 6)
|
|
40
|
+
assertEq(describe(null), 'none')
|
|
41
|
+
},
|
|
27
42
|
() => {
|
|
28
43
|
assertEq(fromUndefined(undefined), null, 0)
|
|
29
44
|
assertEq(fromUndefined(5), 5, 1)
|
|
@@ -41,5 +41,15 @@ export declare const isObject: (value: unknown) => value is { readonly [k in str
|
|
|
41
41
|
* @type {<T>(map: StringMap<Exclude<T, undefined>>) => readonly Exclude<T, undefined>[]}
|
|
42
42
|
*/
|
|
43
43
|
export declare const definedValues: <T>(map: StringMap<Exclude<T, undefined>>) => readonly Exclude<T, undefined>[];
|
|
44
|
-
/**
|
|
45
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Returns only the defined (non-undefined) entries of a partial record.
|
|
46
|
+
*
|
|
47
|
+
* `T` is the record's own value type, which `StringMap` already makes
|
|
48
|
+
* optional. Writing the parameter as `StringMap<Exclude<T, undefined>>`
|
|
49
|
+
* instead would leave `T` in a non-inference position, so a record whose value
|
|
50
|
+
* type is itself generic — the leaf-parameterized JSON tree, say — could not
|
|
51
|
+
* be passed at all.
|
|
52
|
+
*
|
|
53
|
+
* @type {<T>(cmd: StringMap<T>) => readonly Entry<T>[]}
|
|
54
|
+
*/
|
|
55
|
+
export declare const definedEntries: <T>(cmd: StringMap<T>) => readonly Entry<T>[];
|
|
@@ -61,7 +61,17 @@ export const definedValues =
|
|
|
61
61
|
map =>
|
|
62
62
|
values(map).filter(v => v !== undefined)
|
|
63
63
|
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Returns only the defined (non-undefined) entries of a partial record.
|
|
66
|
+
*
|
|
67
|
+
* `T` is the record's own value type, which `StringMap` already makes
|
|
68
|
+
* optional. Writing the parameter as `StringMap<Exclude<T, undefined>>`
|
|
69
|
+
* instead would leave `T` in a non-inference position, so a record whose value
|
|
70
|
+
* type is itself generic — the leaf-parameterized JSON tree, say — could not
|
|
71
|
+
* be passed at all.
|
|
72
|
+
*
|
|
73
|
+
* @type {<T>(cmd: StringMap<T>) => readonly Entry<T>[]}
|
|
74
|
+
*/
|
|
65
75
|
export const definedEntries =
|
|
66
76
|
cmd =>
|
|
67
77
|
entries(cmd).flatMap(([a, b]) => b === undefined ? [] : [[a, b]])
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* @import { Candidate, Create, PatriciaTrie } from './types.ts'
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { splitLast } from '../array/module.f.mjs'
|
|
10
|
+
|
|
9
11
|
/**
|
|
10
12
|
* Creates a Patricia trie whose node merging is delegated to `create`.
|
|
11
13
|
*
|
|
@@ -14,24 +16,37 @@
|
|
|
14
16
|
export const patriciaTrie = create => ({
|
|
15
17
|
push: (c, [storage, stack]) => {
|
|
16
18
|
const [u] = c
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
// Carry propagation: merge the top two candidates for as long as they
|
|
20
|
+
// are more tightly coupled to each other than the right one is to the
|
|
21
|
+
// incoming leaf. Genuinely sequential — each merge decides whether the
|
|
22
|
+
// next one happens — so the loop stays, but the stack is read by
|
|
23
|
+
// splitting rather than by index arithmetic. Either split answering
|
|
24
|
+
// `null` means fewer than two candidates are left, which is where the
|
|
25
|
+
// old `stack.length >= 2` guard stopped.
|
|
26
|
+
while (true) {
|
|
27
|
+
const top = splitLast(stack)
|
|
28
|
+
if (top === null) { break }
|
|
29
|
+
const [belowR, [rLeaf, rHash]] = top
|
|
30
|
+
const below = splitLast(belowR)
|
|
31
|
+
if (below === null) { break }
|
|
32
|
+
const [rest, [lLeaf, lHash]] = below
|
|
20
33
|
if ((lLeaf ^ rLeaf) >= (rLeaf ^ u)) { break }
|
|
21
34
|
const [h, newS] = create(lHash, rHash, storage)
|
|
22
35
|
storage = newS
|
|
23
|
-
stack = [...
|
|
36
|
+
stack = [...rest, [rLeaf, h]]
|
|
24
37
|
}
|
|
25
38
|
return [storage, [...stack, c]]
|
|
26
39
|
},
|
|
40
|
+
// Drain the right spine into a root: a right fold whose seed is the last
|
|
41
|
+
// candidate's identity. `splitLast` supplies both halves at once, so the
|
|
42
|
+
// empty stack is the `null` branch rather than a separate length guard.
|
|
27
43
|
end: ([storage, stack]) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
[h,
|
|
33
|
-
|
|
34
|
-
return [h, storage]
|
|
44
|
+
const split = splitLast(stack)
|
|
45
|
+
if (split === null) { return [undefined, storage] }
|
|
46
|
+
const [rest, [, lastHash]] = split
|
|
47
|
+
return rest.reduceRight(
|
|
48
|
+
([h, s], [, lHash]) => create(lHash, h, s),
|
|
49
|
+
/** @type {readonly [typeof lastHash, typeof storage]} */([lastHash, storage]))
|
|
35
50
|
}
|
|
36
51
|
})
|
|
37
52
|
|
|
@@ -64,8 +64,8 @@ export declare const mapOk: <T, R>(f: (value: T) => R) => <E>(r: Result<T, E>) =
|
|
|
64
64
|
/**
|
|
65
65
|
* Chains a `Result`-returning step onto a `Result`, passing an `error` through
|
|
66
66
|
* unchanged. The monadic bind to {@link mapOk}'s functor map, and the pure
|
|
67
|
-
* sibling of `fjs/effects`' `
|
|
68
|
-
*
|
|
67
|
+
* sibling of the branch `fjs/effects`'s `step` writes for an effect that
|
|
68
|
+
* also performs operations.
|
|
69
69
|
*
|
|
70
70
|
* The two error types are **unioned, not unified**. A validation chain
|
|
71
71
|
* typically widens its error as it goes — a JSON parse failure (`string`)
|
|
@@ -80,7 +80,7 @@ export declare const mapOk: <T, R>(f: (value: T) => R) => <E>(r: Result<T, E>) =
|
|
|
80
80
|
*
|
|
81
81
|
* Reach for it when the step needs **only** the value it is handed. A chain
|
|
82
82
|
* whose later steps also read an earlier one's value would have to nest a
|
|
83
|
-
* closure per link to keep those values in scope, which AGENTS.md §
|
|
83
|
+
* closure per link to keep those values in scope, which `fjs/AGENTS.md` §3.4 rules
|
|
84
84
|
* out for the same reason it rules out nested `step`; write those as a flat
|
|
85
85
|
* sequence of guards.
|
|
86
86
|
*
|
|
@@ -72,8 +72,8 @@ export const mapOk = f => r => r[0] === 'ok' ? ok(f(r[1])) : r
|
|
|
72
72
|
/**
|
|
73
73
|
* Chains a `Result`-returning step onto a `Result`, passing an `error` through
|
|
74
74
|
* unchanged. The monadic bind to {@link mapOk}'s functor map, and the pure
|
|
75
|
-
* sibling of `fjs/effects`' `
|
|
76
|
-
*
|
|
75
|
+
* sibling of the branch `fjs/effects`'s `step` writes for an effect that
|
|
76
|
+
* also performs operations.
|
|
77
77
|
*
|
|
78
78
|
* The two error types are **unioned, not unified**. A validation chain
|
|
79
79
|
* typically widens its error as it goes — a JSON parse failure (`string`)
|
|
@@ -88,7 +88,7 @@ export const mapOk = f => r => r[0] === 'ok' ? ok(f(r[1])) : r
|
|
|
88
88
|
*
|
|
89
89
|
* Reach for it when the step needs **only** the value it is handed. A chain
|
|
90
90
|
* whose later steps also read an earlier one's value would have to nest a
|
|
91
|
-
* closure per link to keep those values in scope, which AGENTS.md §
|
|
91
|
+
* closure per link to keep those values in scope, which `fjs/AGENTS.md` §3.4 rules
|
|
92
92
|
* out for the same reason it rules out nested `step`; write those as a flat
|
|
93
93
|
* sequence of guards.
|
|
94
94
|
*
|