functionalscript 0.44.0 → 0.46.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/README.md +5 -3
- package/fjs/asn.1/module.f.mjs +8 -1
- package/fjs/asn.1/proof.f.d.mts +15 -0
- package/fjs/asn.1/proof.f.mjs +31 -3
- package/fjs/asserts/module.f.d.mts +14 -0
- package/fjs/asserts/module.f.mjs +20 -0
- package/fjs/asserts/proof.f.d.mts +3 -0
- package/fjs/asserts/proof.f.mjs +15 -1
- package/fjs/basen/base128/module.f.mjs +22 -5
- package/fjs/basen/base128/proof.f.d.mts +3 -1
- package/fjs/basen/base128/proof.f.mjs +3 -1
- package/fjs/basen/base64/module.f.mjs +7 -3
- package/fjs/basen/base64/proof.f.d.mts +3 -1
- package/fjs/basen/base64/proof.f.mjs +7 -4
- package/fjs/basen/cbase32/proof.f.d.mts +3 -1
- package/fjs/basen/cbase32/proof.f.mjs +3 -1
- 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 -4
- package/fjs/bnf/data/types.d.ts +20 -2
- package/fjs/bnf/descent/module.f.d.mts +34 -5
- package/fjs/bnf/descent/module.f.mjs +176 -54
- package/fjs/bnf/descent/proof.f.d.mts +3 -0
- package/fjs/bnf/descent/proof.f.mjs +189 -27
- package/fjs/bnf/descent/types.d.ts +24 -18
- package/fjs/bnf/ll1/module.f.d.mts +74 -6
- package/fjs/bnf/ll1/module.f.mjs +297 -95
- package/fjs/bnf/ll1/proof.f.d.mts +17 -2
- package/fjs/bnf/ll1/proof.f.mjs +372 -137
- package/fjs/bnf/ll1/types.d.ts +25 -27
- 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/module.f.d.mts +15 -6
- package/fjs/bnf/module.f.mjs +52 -11
- package/fjs/bnf/proof.f.d.mts +2 -0
- package/fjs/bnf/proof.f.mjs +79 -3
- package/fjs/bnf/testlib.f.d.mts +31 -0
- package/fjs/bnf/testlib.f.mjs +80 -0
- package/fjs/bnf/token_symbol/module.f.d.mts +4 -3
- package/fjs/bnf/token_symbol/module.f.mjs +7 -6
- package/fjs/bnf/token_symbol/proof.f.mjs +5 -2
- package/fjs/bnf/token_symbol/types.d.ts +2 -2
- package/fjs/bnf/types.d.ts +10 -3
- 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 +4 -4
- package/fjs/cas/cli/proof.f.mjs +47 -34
- package/fjs/cas/evo/module.f.d.mts +71 -31
- package/fjs/cas/evo/module.f.mjs +223 -138
- package/fjs/cas/evo/proof.f.d.mts +10 -1
- package/fjs/cas/evo/proof.f.mjs +311 -226
- package/fjs/cas/evo/types.d.ts +45 -9
- package/fjs/cas/module.f.d.mts +18 -32
- package/fjs/cas/module.f.mjs +164 -176
- 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/common/module.f.d.mts +1 -1
- package/fjs/ci/common/module.f.mjs +1 -0
- package/fjs/ci/config/module.f.d.mts +3 -3
- package/fjs/ci/config/module.f.mjs +3 -3
- 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.d.mts +2 -0
- package/fjs/ci/nix/proof.f.mjs +4 -4
- package/fjs/ci/proof.f.d.mts +4 -2
- package/fjs/ci/proof.f.mjs +13 -8
- package/fjs/cli/module.f.d.mts +4 -6
- package/fjs/cli/module.f.mjs +4 -8
- package/fjs/cli/proof.f.d.mts +4 -2
- package/fjs/cli/proof.f.mjs +21 -18
- package/fjs/cli/types.d.ts +2 -3
- package/fjs/common/monoid/module.f.d.mts +70 -12
- package/fjs/common/monoid/module.f.mjs +177 -14
- package/fjs/common/monoid/proof.f.d.mts +12 -1
- package/fjs/common/monoid/proof.f.mjs +88 -4
- package/fjs/common/monoid/types.d.ts +23 -0
- package/fjs/crypto/hmac/module.f.mjs +2 -2
- package/fjs/crypto/secp/proof.f.d.mts +3 -1
- package/fjs/crypto/secp/proof.f.mjs +3 -1
- package/fjs/crypto/sha2/module.f.mjs +3 -1
- package/fjs/crypto/sha2/proof.f.d.mts +4 -1
- package/fjs/crypto/sha2/proof.f.mjs +27 -1
- package/fjs/crypto/sha2/types.d.ts +11 -0
- package/fjs/crypto/sign/module.f.mjs +2 -2
- package/fjs/crypto/vdf/module.f.d.mts +23 -4
- package/fjs/crypto/vdf/module.f.mjs +6 -4
- package/fjs/dev/module.f.d.mts +17 -5
- package/fjs/dev/module.f.mjs +60 -30
- package/fjs/dev/update/module.f.d.mts +11 -3
- package/fjs/dev/update/module.f.mjs +16 -11
- package/fjs/dev/update/proof.f.d.mts +4 -3
- package/fjs/dev/update/proof.f.mjs +11 -7
- 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 +16 -3
- package/fjs/djs/parser/module.f.mjs +135 -16
- package/fjs/djs/parser/proof.f.d.mts +8 -1
- package/fjs/djs/parser/proof.f.mjs +287 -13
- package/fjs/djs/parser/types.d.ts +7 -1
- package/fjs/djs/proof.f.d.mts +20 -1
- package/fjs/djs/proof.f.mjs +190 -12
- package/fjs/djs/serializer/module.f.d.mts +25 -8
- package/fjs/djs/serializer/module.f.mjs +66 -19
- 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 +120 -73
- package/fjs/djs/tokenizer/proof.f.d.mts +3 -0
- package/fjs/djs/tokenizer/proof.f.mjs +86 -67
- package/fjs/djs/transpiler/module.f.d.mts +13 -19
- package/fjs/djs/transpiler/module.f.mjs +79 -72
- package/fjs/djs/transpiler/types.d.ts +29 -0
- package/fjs/djs/types.d.ts +7 -1
- package/fjs/effects/list/module.f.d.mts +23 -12
- package/fjs/effects/list/module.f.mjs +16 -12
- package/fjs/effects/list/types.d.ts +27 -7
- package/fjs/effects/memory/module.f.d.mts +6 -3
- package/fjs/effects/memory/module.f.mjs +7 -7
- package/fjs/effects/memory/proof.f.d.mts +4 -0
- package/fjs/effects/memory/proof.f.mjs +18 -9
- package/fjs/effects/memory/types.d.ts +4 -3
- package/fjs/effects/mock/module.f.d.mts +28 -4
- package/fjs/effects/mock/module.f.mjs +39 -5
- package/fjs/effects/mock/types.d.ts +10 -1
- package/fjs/effects/module.d.mts +12 -2
- package/fjs/effects/module.f.d.mts +469 -281
- package/fjs/effects/module.f.mjs +538 -299
- package/fjs/effects/module.mjs +11 -2
- package/fjs/effects/node/memory/module.d.mts +7 -2
- package/fjs/effects/node/memory/module.mjs +9 -5
- package/fjs/effects/node/memory/proof.d.mts +2 -0
- package/fjs/effects/node/memory/proof.mjs +12 -5
- package/fjs/effects/node/module.d.mts +8 -2
- package/fjs/effects/node/module.f.d.mts +183 -43
- package/fjs/effects/node/module.f.mjs +260 -62
- package/fjs/effects/node/module.mjs +61 -50
- 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 +21 -4
- package/fjs/effects/node/virtual/module.f.mjs +113 -70
- package/fjs/effects/node/virtual/proof.f.d.mts +31 -2
- package/fjs/effects/node/virtual/proof.f.mjs +201 -8
- package/fjs/effects/proof.f.d.mts +69 -34
- package/fjs/effects/proof.f.mjs +413 -130
- package/fjs/effects/types.d.ts +161 -33
- package/fjs/emergent_testing/all.test.d.mts +8 -0
- package/fjs/emergent_testing/all.test.mjs +14 -0
- package/fjs/emergent_testing/module.f.d.mts +22 -10
- package/fjs/emergent_testing/module.f.mjs +119 -85
- package/fjs/emergent_testing/proof.f.d.mts +21 -7
- package/fjs/emergent_testing/proof.f.mjs +169 -35
- package/fjs/emergent_testing/types.d.ts +22 -4
- package/fjs/fsc/bnf.f.d.mts +3 -0
- package/fjs/fsc/bnf.f.mjs +4 -1
- package/fjs/fsc/json.f.d.mts +3 -0
- package/fjs/fsc/json.f.mjs +4 -1
- package/fjs/fsc/module.f.d.mts +9 -0
- package/fjs/fsc/module.f.mjs +5 -3
- package/fjs/fsm/module.f.d.mts +14 -4
- package/fjs/fsm/module.f.mjs +54 -37
- package/fjs/fsm/proof.f.d.mts +5 -0
- package/fjs/fsm/proof.f.mjs +87 -115
- package/fjs/js/keywords/module.f.d.mts +52 -0
- package/fjs/js/keywords/module.f.mjs +72 -0
- package/fjs/{emergent_testing/scenarios/return-value.pass.d.ts → js/keywords/proof.f.d.mts} +1 -1
- package/fjs/js/keywords/proof.f.mjs +13 -0
- package/fjs/js/tokenizer/module.f.d.mts +30 -3
- package/fjs/js/tokenizer/module.f.mjs +161 -211
- 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 +39 -4
- package/fjs/mcp/module.f.mjs +14 -12
- package/fjs/mcp/proof.f.d.mts +13 -1
- package/fjs/mcp/proof.f.mjs +120 -61
- package/fjs/media/html/module.f.d.mts +12 -0
- package/fjs/media/html/module.f.mjs +7 -5
- package/fjs/media/html/proof.f.d.mts +3 -0
- package/fjs/media/html/proof.f.mjs +4 -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 +133 -72
- 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 +38 -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.d.mts +3 -0
- package/fjs/media/json/rtti/proof.f.mjs +12 -12
- package/fjs/media/json/schema/module.f.d.mts +61 -27
- package/fjs/media/json/schema/module.f.mjs +218 -63
- package/fjs/media/json/schema/proof.f.d.mts +41 -1
- package/fjs/media/json/schema/proof.f.mjs +220 -9
- package/fjs/media/json/serializer/module.f.d.mts +44 -0
- package/fjs/media/json/serializer/module.f.mjs +71 -9
- package/fjs/media/json/tokenizer/module.f.d.mts +8 -0
- package/fjs/media/json/tokenizer/module.f.mjs +31 -8
- 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/nix/module.f.d.mts +13 -0
- package/fjs/media/nix/module.f.mjs +4 -2
- package/fjs/media/nix/proof.f.d.mts +3 -0
- package/fjs/media/nix/proof.f.mjs +4 -1
- 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 +83 -7
- package/fjs/media/revision/module.f.mjs +127 -23
- package/fjs/media/revision/proof.f.d.mts +14 -0
- package/fjs/media/revision/proof.f.mjs +93 -2
- package/fjs/media/revision/types.d.ts +34 -5
- package/fjs/media/type/module.f.d.mts +53 -18
- package/fjs/media/type/module.f.mjs +87 -97
- package/fjs/media/type/proof.f.d.mts +17 -0
- package/fjs/media/type/proof.f.mjs +73 -13
- package/fjs/module.d.mts +5 -0
- package/fjs/module.f.d.mts +8 -0
- package/fjs/module.f.mjs +33 -10
- package/fjs/module.mjs +6 -0
- 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/path/module.f.d.mts +8 -0
- package/fjs/path/module.f.mjs +4 -2
- package/fjs/proof.f.d.mts +7 -3
- package/fjs/proof.f.mjs +41 -12
- package/fjs/protocol/json_rpc/module.f.d.mts +3 -3
- package/fjs/protocol/json_rpc/module.f.mjs +10 -7
- package/fjs/protocol/json_rpc/proof.f.d.mts +6 -0
- package/fjs/protocol/json_rpc/proof.f.mjs +26 -5
- 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 +16 -3
- package/fjs/protocol/mcp/proof.f.mjs +224 -69
- package/fjs/protocol/mcp/stdio/module.f.d.mts +17 -11
- package/fjs/protocol/mcp/stdio/module.f.mjs +39 -33
- package/fjs/protocol/mcp/stdio/proof.f.d.mts +5 -3
- package/fjs/protocol/mcp/stdio/proof.f.mjs +46 -13
- package/fjs/protocol/mcp/stdio/types.d.ts +14 -0
- package/fjs/protocol/mcp/types.d.ts +17 -6
- package/fjs/sul/id/module.f.d.mts +4 -0
- package/fjs/sul/id/module.f.mjs +6 -6
- package/fjs/sul/level/hash/module.f.d.mts +4 -1
- package/fjs/sul/level/hash/module.f.mjs +6 -4
- package/fjs/sul/level/hash/proof.f.d.mts +4 -0
- package/fjs/sul/level/hash/proof.f.mjs +7 -4
- package/fjs/sul/level/literal/module.f.d.mts +4 -1
- package/fjs/sul/level/literal/module.f.mjs +4 -3
- package/fjs/sul/level/literal/proof.f.d.mts +3 -0
- package/fjs/sul/level/literal/proof.f.mjs +4 -1
- package/fjs/sul/module.f.d.mts +5 -3
- package/fjs/sul/module.f.mjs +23 -17
- package/fjs/sul/proof.f.d.mts +4 -0
- package/fjs/sul/proof.f.mjs +5 -2
- package/fjs/text/ascii/module.f.d.mts +26 -0
- package/fjs/text/ascii/module.f.mjs +49 -1
- package/fjs/text/ascii/proof.f.d.mts +10 -0
- package/fjs/text/ascii/proof.f.mjs +33 -1
- package/fjs/text/code_point/module.f.d.mts +29 -3
- package/fjs/text/code_point/module.f.mjs +32 -9
- package/fjs/text/code_point/proof.f.d.mts +2 -0
- package/fjs/text/code_point/proof.f.mjs +39 -0
- package/fjs/text/module.f.d.mts +4 -2
- package/fjs/text/module.f.mjs +4 -3
- package/fjs/text/proof.f.d.mts +3 -0
- package/fjs/text/proof.f.mjs +4 -1
- package/fjs/text/sgr/module.f.d.mts +6 -5
- package/fjs/text/sgr/module.f.mjs +8 -8
- package/fjs/text/sgr/proof.f.d.mts +3 -0
- package/fjs/text/sgr/proof.f.mjs +4 -1
- package/fjs/text/utf16/module.f.d.mts +5 -1
- package/fjs/text/utf16/module.f.mjs +38 -35
- package/fjs/text/utf16/proof.f.d.mts +3 -1
- package/fjs/text/utf16/proof.f.mjs +19 -2
- package/fjs/text/utf8/module.f.d.mts +9 -5
- package/fjs/text/utf8/module.f.mjs +20 -20
- package/fjs/types/array/module.f.d.mts +2 -1
- package/fjs/types/array/module.f.mjs +16 -4
- package/fjs/types/bigfloat/module.f.d.mts +21 -1
- package/fjs/types/bigfloat/module.f.mjs +33 -7
- package/fjs/types/bigfloat/proof.f.d.mts +1 -0
- package/fjs/types/bigfloat/proof.f.mjs +46 -0
- package/fjs/types/bigint/module.f.d.mts +4 -0
- package/fjs/types/bigint/module.f.mjs +4 -3
- package/fjs/types/bit_vec/module.f.d.mts +10 -16
- package/fjs/types/bit_vec/module.f.mjs +99 -95
- package/fjs/types/bit_vec/proof.f.d.mts +6 -0
- package/fjs/types/bit_vec/proof.f.mjs +31 -5
- package/fjs/types/btree/find/module.f.d.mts +5 -1
- package/fjs/types/btree/find/module.f.mjs +5 -5
- package/fjs/types/btree/find/proof.f.d.mts +5 -1
- package/fjs/types/btree/find/proof.f.mjs +5 -3
- package/fjs/types/btree/module.f.d.mts +3 -0
- package/fjs/types/btree/module.f.mjs +3 -2
- package/fjs/types/btree/proof.f.d.mts +5 -1
- package/fjs/types/btree/proof.f.mjs +5 -3
- package/fjs/types/btree/remove/module.f.d.mts +11 -0
- package/fjs/types/btree/remove/module.f.mjs +10 -10
- package/fjs/types/btree/remove/proof.f.d.mts +3 -0
- package/fjs/types/btree/remove/proof.f.mjs +4 -1
- package/fjs/types/btree/set/module.f.d.mts +9 -0
- package/fjs/types/btree/set/module.f.mjs +14 -17
- package/fjs/types/btree/set/proof.f.d.mts +3 -0
- package/fjs/types/btree/set/proof.f.mjs +16 -1
- package/fjs/types/btree/types/module.f.d.mts +2 -1
- package/fjs/types/btree/types/module.f.mjs +2 -1
- package/fjs/types/byte_set/module.f.d.mts +20 -4
- package/fjs/types/byte_set/module.f.mjs +18 -8
- package/fjs/types/byte_set/proof.f.d.mts +3 -1
- package/fjs/types/byte_set/proof.f.mjs +10 -8
- package/fjs/types/function/compare/module.f.d.mts +3 -2
- package/fjs/types/function/compare/module.f.mjs +13 -5
- package/fjs/types/function/module.f.d.mts +8 -1
- package/fjs/types/function/module.f.mjs +8 -1
- package/fjs/types/function/operator/module.f.d.mts +2 -1
- package/fjs/types/function/operator/module.f.mjs +2 -2
- package/fjs/types/list/module.f.d.mts +10 -3
- package/fjs/types/list/module.f.mjs +6 -4
- package/fjs/types/list/proof.f.d.mts +4 -1
- package/fjs/types/list/proof.f.mjs +4 -2
- package/fjs/types/nibble_set/module.f.d.mts +2 -1
- package/fjs/types/nibble_set/module.f.mjs +2 -2
- package/fjs/types/nominal/module.f.d.mts +2 -1
- package/fjs/types/nominal/module.f.mjs +2 -1
- package/fjs/types/nullable/module.f.d.mts +26 -6
- package/fjs/types/nullable/module.f.mjs +25 -6
- package/fjs/types/nullable/proof.f.d.mts +4 -0
- package/fjs/types/nullable/proof.f.mjs +15 -0
- package/fjs/types/number/module.f.d.mts +4 -0
- package/fjs/types/number/module.f.mjs +4 -3
- package/fjs/types/object/module.f.d.mts +26 -4
- package/fjs/types/object/module.f.mjs +26 -7
- package/fjs/types/object/proof.f.d.mts +5 -2
- package/fjs/types/object/proof.f.mjs +6 -3
- package/fjs/types/object/structurally_same/module.f.d.mts +39 -0
- package/fjs/types/object/structurally_same/module.f.mjs +59 -0
- package/fjs/types/object/structurally_same/proof.f.d.mts +6 -0
- package/fjs/types/object/structurally_same/proof.f.mjs +73 -0
- package/fjs/types/ordered_map/module.f.d.mts +5 -0
- package/fjs/types/ordered_map/module.f.mjs +5 -4
- package/fjs/types/ordered_map/proof.f.d.mts +3 -0
- package/fjs/types/ordered_map/proof.f.mjs +4 -1
- package/fjs/types/patricia_trie/module.f.d.mts +2 -1
- package/fjs/types/patricia_trie/module.f.mjs +27 -12
- package/fjs/types/patricia_trie/proof.f.d.mts +3 -0
- package/fjs/types/patricia_trie/proof.f.mjs +4 -1
- package/fjs/types/prime_field/module.f.d.mts +3 -1
- package/fjs/types/prime_field/module.f.mjs +3 -2
- package/fjs/types/range/module.f.d.mts +2 -1
- package/fjs/types/range/module.f.mjs +2 -2
- package/fjs/types/range_map/module.f.d.mts +6 -0
- package/fjs/types/range_map/module.f.mjs +6 -9
- package/fjs/types/range_map/proof.f.d.mts +5 -1
- package/fjs/types/range_map/proof.f.mjs +5 -3
- package/fjs/types/range_set/module.f.d.mts +5 -0
- package/fjs/types/range_set/module.f.mjs +1 -0
- package/fjs/types/range_set/proof.f.d.mts +3 -0
- package/fjs/types/range_set/proof.f.mjs +4 -1
- package/fjs/types/result/module.d.mts +8 -0
- package/fjs/types/result/module.f.d.mts +37 -7
- package/fjs/types/result/module.f.mjs +38 -8
- package/fjs/types/result/module.mjs +9 -1
- package/fjs/types/result/proof.f.d.mts +5 -0
- package/fjs/types/result/proof.f.mjs +22 -2
- package/fjs/types/rtti/common/module.f.d.mts +44 -14
- package/fjs/types/rtti/common/module.f.mjs +42 -36
- package/fjs/types/rtti/common/proof.f.d.mts +4 -0
- package/fjs/types/rtti/common/proof.f.mjs +10 -7
- package/fjs/types/rtti/data/module.f.d.mts +134 -0
- package/fjs/types/rtti/data/module.f.mjs +1053 -0
- package/fjs/types/rtti/data/proof.f.d.mts +76 -0
- package/fjs/types/rtti/data/proof.f.mjs +589 -0
- package/fjs/types/rtti/data/types.d.ts +83 -0
- package/fjs/types/rtti/module.f.d.mts +12 -5
- package/fjs/types/rtti/module.f.mjs +7 -5
- package/fjs/types/rtti/parse/module.f.d.mts +48 -0
- package/fjs/types/rtti/parse/module.f.mjs +45 -34
- package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
- package/fjs/types/rtti/parse/proof.f.mjs +51 -52
- package/fjs/types/rtti/proof.f.d.mts +3 -1
- package/fjs/types/rtti/proof.f.mjs +6 -2
- package/fjs/types/rtti/ts/module.f.d.mts +68 -9
- package/fjs/types/rtti/ts/module.f.mjs +258 -30
- package/fjs/types/rtti/ts/proof.f.d.mts +44 -0
- package/fjs/types/rtti/ts/proof.f.mjs +152 -4
- package/fjs/types/rtti/ts/types.d.ts +25 -1
- package/fjs/types/rtti/types.d.ts +40 -0
- package/fjs/types/sorted_list/module.f.d.mts +4 -1
- package/fjs/types/sorted_list/module.f.mjs +21 -12
- package/fjs/types/sorted_list/proof.f.d.mts +3 -1
- package/fjs/types/sorted_list/proof.f.mjs +3 -1
- package/fjs/types/sorted_set/module.f.d.mts +49 -1
- package/fjs/types/sorted_set/module.f.mjs +26 -2
- package/fjs/types/sorted_set/proof.f.d.mts +4 -1
- package/fjs/types/sorted_set/proof.f.mjs +19 -2
- package/fjs/types/string/module.f.d.mts +4 -0
- package/fjs/types/string/module.f.mjs +4 -3
- package/fjs/types/string_set/module.f.d.mts +3 -1
- package/fjs/types/string_set/module.f.mjs +3 -2
- package/fjs/types/ts/module.f.d.mts +2 -0
- package/fjs/types/ts/module.f.mjs +3 -3
- package/fjs/types/ts/proof.f.d.mts +1 -0
- package/fjs/types/ts/proof.f.mjs +5 -0
- package/fjs/types/ts/types.d.ts +6 -1
- package/fjs/types/uint8array/module.f.d.mts +13 -2
- package/fjs/types/uint8array/module.f.mjs +20 -15
- package/fjs/website/module.f.d.mts +5 -2
- package/fjs/website/module.f.mjs +6 -8
- package/fjs/website/proof.f.mjs +2 -1
- package/package.json +3 -3
- package/fjs/asn.1/types.js +0 -6
- package/fjs/asserts/types.js +0 -6
- package/fjs/basen/types.js +0 -6
- package/fjs/bnf/data/types.js +0 -6
- package/fjs/bnf/descent/types.js +0 -6
- package/fjs/bnf/ll1/types.js +0 -6
- package/fjs/bnf/token_symbol/types.js +0 -6
- package/fjs/bnf/types.js +0 -6
- package/fjs/cas/evo/types.js +0 -7
- package/fjs/cas/types.js +0 -6
- package/fjs/ci/common/types.js +0 -1
- package/fjs/ci/nix/types.js +0 -6
- package/fjs/ci/types.js +0 -6
- package/fjs/cli/types.js +0 -6
- package/fjs/common/monoid/types.js +0 -6
- package/fjs/crypto/pow/types.js +0 -6
- package/fjs/crypto/secp/types.js +0 -6
- package/fjs/crypto/sha2/types.js +0 -6
- package/fjs/crypto/sign/types.js +0 -6
- package/fjs/crypto/vdf/types.js +0 -6
- package/fjs/dev/package_json/module.f.d.mts +0 -32
- package/fjs/dev/package_json/module.f.mjs +0 -37
- package/fjs/dev/package_json/proof.f.d.mts +0 -6
- package/fjs/dev/package_json/proof.f.mjs +0 -32
- package/fjs/dev/types.js +0 -6
- package/fjs/djs/ast/types.js +0 -8
- package/fjs/djs/parser/types.js +0 -7
- package/fjs/djs/tokenizer/types.js +0 -7
- package/fjs/djs/types.js +0 -7
- package/fjs/effects/eff/module.f.d.mts +0 -10
- package/fjs/effects/eff/module.f.mjs +0 -68
- package/fjs/effects/eff/proof.f.d.mts +0 -12
- package/fjs/effects/eff/proof.f.mjs +0 -66
- package/fjs/effects/eff/types.d.ts +0 -71
- package/fjs/effects/eff/types.js +0 -6
- package/fjs/effects/list/types.js +0 -6
- package/fjs/effects/memory/types.js +0 -6
- package/fjs/effects/mock/types.js +0 -6
- package/fjs/effects/node/types.js +0 -6
- package/fjs/effects/node/virtual/types.js +0 -7
- package/fjs/effects/types.js +0 -6
- package/fjs/emergent_testing/all.test.d.ts +0 -1
- package/fjs/emergent_testing/all.test.js +0 -5
- package/fjs/emergent_testing/scenarios/all.d.ts +0 -1
- package/fjs/emergent_testing/scenarios/all.js +0 -1
- package/fjs/emergent_testing/scenarios/async-subtests.fail.d.ts +0 -6
- package/fjs/emergent_testing/scenarios/async-subtests.fail.js +0 -9
- package/fjs/emergent_testing/scenarios/async-subtests.pass.d.ts +0 -6
- package/fjs/emergent_testing/scenarios/async-subtests.pass.js +0 -9
- package/fjs/emergent_testing/scenarios/async.fail.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/async.fail.js +0 -6
- package/fjs/emergent_testing/scenarios/async.pass.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/async.pass.js +0 -5
- package/fjs/emergent_testing/scenarios/fail.fail.d.ts +0 -3
- package/fjs/emergent_testing/scenarios/fail.fail.js +0 -3
- package/fjs/emergent_testing/scenarios/return-value.pass.js +0 -4
- package/fjs/emergent_testing/scenarios/thenable.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/thenable.pass.js +0 -11
- package/fjs/emergent_testing/scenarios/thenable2.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/thenable2.pass.js +0 -3
- package/fjs/emergent_testing/scenarios/throw.pass.d.ts +0 -5
- package/fjs/emergent_testing/scenarios/throw.pass.js +0 -3
- package/fjs/emergent_testing/types.js +0 -6
- package/fjs/js/tokenizer/types.js +0 -6
- package/fjs/media/html/types.js +0 -6
- package/fjs/media/json/parser/types.js +0 -6
- package/fjs/media/json/tokenizer/types.js +0 -6
- package/fjs/media/json/types.js +0 -13
- package/fjs/media/nix/types.js +0 -6
- package/fjs/media/revision/types.js +0 -8
- package/fjs/media/type/types.js +0 -6
- package/fjs/media/types.js +0 -7
- package/fjs/nanvm/types.js +0 -11
- package/fjs/protocol/json_rpc/types.js +0 -8
- package/fjs/protocol/mcp/types.js +0 -8
- package/fjs/sul/id/types.js +0 -6
- package/fjs/sul/level/hash/types.js +0 -6
- package/fjs/sul/level/literal/types.js +0 -6
- package/fjs/sul/types.js +0 -6
- package/fjs/text/sgr/types.js +0 -6
- package/fjs/text/types.js +0 -6
- package/fjs/text/utf16/types.js +0 -6
- package/fjs/text/utf8/types.js +0 -6
- package/fjs/types/array/types.js +0 -6
- package/fjs/types/bigfloat/types.js +0 -6
- package/fjs/types/bigint/types.js +0 -6
- package/fjs/types/bit_vec/types.js +0 -6
- package/fjs/types/btree/find/types.js +0 -6
- package/fjs/types/btree/types/types.js +0 -6
- package/fjs/types/byte_set/types.js +0 -6
- package/fjs/types/function/compare/types.js +0 -6
- package/fjs/types/function/operator/types.js +0 -6
- package/fjs/types/function/types.js +0 -6
- package/fjs/types/list/types.js +0 -6
- package/fjs/types/nibble_set/types.js +0 -6
- package/fjs/types/nominal/types.js +0 -6
- package/fjs/types/nullable/types.js +0 -6
- package/fjs/types/object/types.js +0 -8
- package/fjs/types/option/types.js +0 -6
- package/fjs/types/ordered_map/types.js +0 -6
- package/fjs/types/patricia_trie/types.js +0 -6
- package/fjs/types/phantom/types.js +0 -11
- package/fjs/types/prime_field/types.js +0 -6
- package/fjs/types/range/types.js +0 -6
- package/fjs/types/range_map/types.js +0 -6
- package/fjs/types/result/types.js +0 -6
- package/fjs/types/rtti/common/types.js +0 -1
- package/fjs/types/rtti/parse/types.js +0 -1
- package/fjs/types/rtti/ts/types.js +0 -1
- package/fjs/types/rtti/types.js +0 -1
- package/fjs/types/rtti/validate/module.f.d.mts +0 -6
- package/fjs/types/rtti/validate/module.f.mjs +0 -169
- package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
- package/fjs/types/rtti/validate/proof.f.mjs +0 -437
- package/fjs/types/rtti/validate/types.d.ts +0 -6
- package/fjs/types/rtti/validate/types.js +0 -1
- package/fjs/types/sorted_list/types.js +0 -6
- package/fjs/types/sorted_set/types.js +0 -6
- package/fjs/types/string_set/types.js +0 -6
- package/fjs/types/ts/types.js +0 -8
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { Unknown } from './types.ts'
|
|
3
|
+
*/
|
|
4
|
+
export declare const proof: {
|
|
5
|
+
bigint: {
|
|
6
|
+
positive: () => void;
|
|
7
|
+
negative: () => void;
|
|
8
|
+
zero: () => void;
|
|
9
|
+
beyondSafeInteger: () => void;
|
|
10
|
+
oversized: () => void;
|
|
11
|
+
};
|
|
12
|
+
number: {
|
|
13
|
+
negativeZero: () => void;
|
|
14
|
+
fraction: () => void;
|
|
15
|
+
wholeFraction: () => void;
|
|
16
|
+
exponent: () => void;
|
|
17
|
+
capitalExponent: () => void;
|
|
18
|
+
negativeExponent: () => void;
|
|
19
|
+
underflow: () => void;
|
|
20
|
+
exponentSpelling: () => void;
|
|
21
|
+
};
|
|
22
|
+
overflow: {
|
|
23
|
+
exponent: () => void;
|
|
24
|
+
negativeExponent: () => void;
|
|
25
|
+
unboundedExponent: () => void;
|
|
26
|
+
malformed: () => void;
|
|
27
|
+
};
|
|
28
|
+
containers: {
|
|
29
|
+
array: () => void;
|
|
30
|
+
object: () => void;
|
|
31
|
+
undefinedProperty: () => void;
|
|
32
|
+
};
|
|
33
|
+
nonFinite: {
|
|
34
|
+
nan: () => void;
|
|
35
|
+
infinity: () => void;
|
|
36
|
+
negativeInfinity: () => void;
|
|
37
|
+
};
|
|
38
|
+
serialize: {
|
|
39
|
+
oneToOne: () => void;
|
|
40
|
+
largeBigintHasNoExponent: () => void;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { Unknown } from './types.ts'
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { parse, stringify as extendedStringify } from './module.f.mjs'
|
|
6
|
+
import { sort } from '../../../types/object/module.f.mjs'
|
|
7
|
+
import { unwrap } from '../../../types/result/module.f.mjs'
|
|
8
|
+
import { assert, assertEq, assertStructurallySame } from '../../../asserts/module.f.mjs'
|
|
9
|
+
|
|
10
|
+
const stringify = extendedStringify(sort)
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The runtime type a token parses to, and the text that value serializes back
|
|
14
|
+
* to — the two halves of the extended codec's round trip.
|
|
15
|
+
*
|
|
16
|
+
* @type {(text: string) => readonly [string, string]}
|
|
17
|
+
*/
|
|
18
|
+
const parsed = text => {
|
|
19
|
+
const value = unwrap(parse(text))
|
|
20
|
+
return [typeof value, stringify(value)]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** @type {(text: string) => Unknown} */
|
|
24
|
+
const parseValue = text => unwrap(parse(text))
|
|
25
|
+
|
|
26
|
+
/** @type {(text: string) => string} */
|
|
27
|
+
const parseError = text => {
|
|
28
|
+
const [tag, message] = parse(text)
|
|
29
|
+
assertEq(tag, 'error')
|
|
30
|
+
return `${message}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Long enough that `Number` of it is `Infinity` and `10 ** exponent` is not a
|
|
34
|
+
// computation anyone can afford.
|
|
35
|
+
const hugeExp = '99999999999999999999'
|
|
36
|
+
|
|
37
|
+
export const proof = {
|
|
38
|
+
// bare integer syntax is `bigint`, whatever the magnitude
|
|
39
|
+
bigint: {
|
|
40
|
+
positive: () => assertStructurallySame(parsed('123'), ['bigint', '123']),
|
|
41
|
+
negative: () => assertStructurallySame(parsed('-123'), ['bigint', '-123']),
|
|
42
|
+
zero: () => assertStructurallySame(parsed('0'), ['bigint', '0']),
|
|
43
|
+
// beyond `Number.MAX_SAFE_INTEGER`, so a materializer that went
|
|
44
|
+
// through `number` first would round here
|
|
45
|
+
beyondSafeInteger: () => {
|
|
46
|
+
assertEq(parseValue('12345678901234567890123'), 12345678901234567890123n)
|
|
47
|
+
assertEq(parseValue('-12345678901234567890123'), -12345678901234567890123n)
|
|
48
|
+
},
|
|
49
|
+
// an integer of a size no `number` can even approximate
|
|
50
|
+
oversized: () => {
|
|
51
|
+
const digits = `1${'0'.repeat(2000)}`
|
|
52
|
+
assertStructurallySame(parsed(digits), ['bigint', digits])
|
|
53
|
+
assertEq(parseValue(digits), 10n ** 2000n)
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
// `.`/`e`/`E` means `number`, even when the value is a whole number
|
|
57
|
+
number: {
|
|
58
|
+
negativeZero: () => {
|
|
59
|
+
assertStructurallySame(parsed('-0'), ['number', '-0'])
|
|
60
|
+
// the sign is the whole point: `bigint` has no negative zero
|
|
61
|
+
assert(Object.is(parseValue('-0'), -0))
|
|
62
|
+
},
|
|
63
|
+
fraction: () => assertStructurallySame(parsed('1.5'), ['number', '1.5']),
|
|
64
|
+
wholeFraction: () => assertStructurallySame(parsed('1.0'), ['number', '1.0']),
|
|
65
|
+
exponent: () => assertStructurallySame(parsed('1e3'), ['number', '1000.0']),
|
|
66
|
+
capitalExponent: () => assertStructurallySame(parsed('1E3'), ['number', '1000.0']),
|
|
67
|
+
negativeExponent: () => assertStructurallySame(parsed('1e-3'), ['number', '0.001']),
|
|
68
|
+
// ordinary `number` rounding is not an error: an exponent below the
|
|
69
|
+
// range is zero, as it is everywhere else in JavaScript
|
|
70
|
+
underflow: () => assertStructurallySame(parsed('1e-400'), ['number', '0.0']),
|
|
71
|
+
// a `number` big enough to spell itself with an exponent keeps that
|
|
72
|
+
// spelling — appending `.0` to it would not even be valid JSON
|
|
73
|
+
exponentSpelling: () => assertStructurallySame(parsed('1e21'), ['number', '1e+21']),
|
|
74
|
+
},
|
|
75
|
+
// a valid token the extended domain cannot represent is an ordinary
|
|
76
|
+
// parse error, never `Infinity` and never a throw
|
|
77
|
+
overflow: {
|
|
78
|
+
exponent: () => assertEq(
|
|
79
|
+
parseError('1e400'),
|
|
80
|
+
'number is out of the finite range: 1e400'),
|
|
81
|
+
negativeExponent: () => assertEq(
|
|
82
|
+
parseError('-1e400'),
|
|
83
|
+
'number is out of the finite range: -1e400'),
|
|
84
|
+
// exponent text far beyond `number` precision: the tokenizer keeps
|
|
85
|
+
// every digit, and the policy rejects the token rather than losing them
|
|
86
|
+
unboundedExponent: () => assertEq(
|
|
87
|
+
parseError(`1e${hugeExp}`),
|
|
88
|
+
`number is out of the finite range: 1e${hugeExp}`),
|
|
89
|
+
// malformed input is still an ordinary error
|
|
90
|
+
malformed: () => assertEq(parseError('{'), 'unexpected end'),
|
|
91
|
+
},
|
|
92
|
+
containers: {
|
|
93
|
+
array: () => assertEq(
|
|
94
|
+
stringify(parseValue('[1,2.0,-0,"x",true,false,null]')),
|
|
95
|
+
'[1,2.0,-0,"x",true,false,null]'),
|
|
96
|
+
object: () => assertEq(
|
|
97
|
+
stringify(parseValue('{"b":[1e2],"a":{"c":-7}}')),
|
|
98
|
+
'{"a":{"c":-7},"b":[100.0]}'),
|
|
99
|
+
// a missing property is not a leaf
|
|
100
|
+
undefinedProperty: () => assertEq(stringify({ a: 1n, b: undefined }), '{"a":1}'),
|
|
101
|
+
},
|
|
102
|
+
// programmatic values: JSON has no syntax for these, so the serializer
|
|
103
|
+
// spells them `null` — the same choice `JSON.stringify` makes
|
|
104
|
+
nonFinite: {
|
|
105
|
+
nan: () => assertEq(stringify(NaN), 'null'),
|
|
106
|
+
infinity: () => assertEq(stringify(Infinity), 'null'),
|
|
107
|
+
negativeInfinity: () => assertEq(stringify(-Infinity), 'null'),
|
|
108
|
+
},
|
|
109
|
+
// the spellings that keep `number` and `bigint` apart across a round trip
|
|
110
|
+
serialize: {
|
|
111
|
+
oneToOne: () => {
|
|
112
|
+
assertEq(stringify(0n), '0')
|
|
113
|
+
assertEq(stringify(0), '0.0')
|
|
114
|
+
assertEq(stringify(-0), '-0')
|
|
115
|
+
assertEq(stringify(3n), '3')
|
|
116
|
+
assertEq(stringify(3), '3.0')
|
|
117
|
+
assertEq(stringify(1.5), '1.5')
|
|
118
|
+
},
|
|
119
|
+
// a bigint is never shortened to exponent notation, however large:
|
|
120
|
+
// that syntax would parse back as a `number`
|
|
121
|
+
largeBigintHasNoExponent: () => {
|
|
122
|
+
const text = stringify(10n ** 30n)
|
|
123
|
+
assertEq(text, `1${'0'.repeat(30)}`)
|
|
124
|
+
assertStructurallySame(parsed(text), ['bigint', text])
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript counterparts of the extended JSON data model: ordinary JSON's
|
|
3
|
+
* containers with `bigint` added to the primitive leaf set.
|
|
4
|
+
*
|
|
5
|
+
* This is a runtime representation, not a new syntax: an extended value's
|
|
6
|
+
* serialized form is ordinary valid JSON text, with no `123n` literal, tagged
|
|
7
|
+
* object, or quoted-integer convention.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import type { Primitive as JsonPrimitive, Tree, TreeObject, TreeArray, TreeMapEntries } from '../types.ts';
|
|
12
|
+
/**
|
|
13
|
+
* `null | boolean | string | number | bigint`.
|
|
14
|
+
*
|
|
15
|
+
* `bigint` carries JSON's bare integer syntax exactly, whatever its
|
|
16
|
+
* magnitude; `number` carries decimal and exponent syntax, and the one bare
|
|
17
|
+
* integer that `bigint` cannot represent — negative zero.
|
|
18
|
+
*/
|
|
19
|
+
export type Primitive = JsonPrimitive | bigint;
|
|
20
|
+
export type Unknown = Tree<Primitive>;
|
|
21
|
+
export type Object = TreeObject<Primitive>;
|
|
22
|
+
export type Array = TreeArray<Primitive>;
|
|
23
|
+
export type _MapEntries = TreeMapEntries<Primitive>;
|
|
@@ -9,11 +9,17 @@
|
|
|
9
9
|
* [`./types.ts`](./types.ts), and the rtti schemas they are pinned against in
|
|
10
10
|
* [`./rtti/module.f.mjs`](./rtti/module.f.mjs).
|
|
11
11
|
*
|
|
12
|
+
* This is the standard, bigint-free codec: numbers are JavaScript `number`s.
|
|
13
|
+
* [`./extended/module.f.mjs`](./extended/module.f.mjs) is the sibling codec
|
|
14
|
+
* that keeps JSON's bare integer syntax as `bigint`. Both are numeric policies
|
|
15
|
+
* over the same tokenizer and the same structural parser — see
|
|
16
|
+
* [`./README.md`](./README.md).
|
|
17
|
+
*
|
|
12
18
|
* @module
|
|
13
19
|
*
|
|
14
|
-
* @import { StringMap } from '../../types/object/types.ts'
|
|
15
20
|
* @import { Result } from '../../types/result/types.ts'
|
|
16
|
-
* @import { _MapEntries,
|
|
21
|
+
* @import { _MapEntries, Primitive, Unknown, } from './types.ts'
|
|
22
|
+
* @import { NumberPolicy } from './parser/types.ts'
|
|
17
23
|
* @import { List } from '../../types/list/types.ts'
|
|
18
24
|
*/
|
|
19
25
|
import type { Result } from '../../types/result/types.ts';
|
|
@@ -9,22 +9,29 @@
|
|
|
9
9
|
* [`./types.ts`](./types.ts), and the rtti schemas they are pinned against in
|
|
10
10
|
* [`./rtti/module.f.mjs`](./rtti/module.f.mjs).
|
|
11
11
|
*
|
|
12
|
+
* This is the standard, bigint-free codec: numbers are JavaScript `number`s.
|
|
13
|
+
* [`./extended/module.f.mjs`](./extended/module.f.mjs) is the sibling codec
|
|
14
|
+
* that keeps JSON's bare integer syntax as `bigint`. Both are numeric policies
|
|
15
|
+
* over the same tokenizer and the same structural parser — see
|
|
16
|
+
* [`./README.md`](./README.md).
|
|
17
|
+
*
|
|
12
18
|
* @module
|
|
13
19
|
*
|
|
14
|
-
* @import { StringMap } from '../../types/object/types.ts'
|
|
15
20
|
* @import { Result } from '../../types/result/types.ts'
|
|
16
|
-
* @import { _MapEntries,
|
|
21
|
+
* @import { _MapEntries, Primitive, Unknown, } from './types.ts'
|
|
22
|
+
* @import { NumberPolicy } from './parser/types.ts'
|
|
17
23
|
* @import { List } from '../../types/list/types.ts'
|
|
18
24
|
*/
|
|
19
25
|
|
|
20
|
-
import { next
|
|
26
|
+
import { next } from '../../types/list/module.f.mjs'
|
|
21
27
|
import { concat } from '../../types/string/module.f.mjs'
|
|
22
28
|
import { stringToList } from '../../text/utf16/module.f.mjs'
|
|
23
29
|
import { parse as parseTokens } from './parser/module.f.mjs'
|
|
24
30
|
import { tokenize } from './tokenizer/module.f.mjs'
|
|
25
|
-
import { at
|
|
26
|
-
import { compose
|
|
27
|
-
import {
|
|
31
|
+
import { at } from '../../types/object/module.f.mjs'
|
|
32
|
+
import { compose } from '../../types/function/module.f.mjs'
|
|
33
|
+
import { ok } from '../../types/result/module.f.mjs'
|
|
34
|
+
import { treeSerialize, stringSerialize, numberSerialize, nullSerialize, boolSerialize } from './serializer/module.f.mjs'
|
|
28
35
|
|
|
29
36
|
// ── JSON utilities ────────────────────────────────────────────────────────────
|
|
30
37
|
|
|
@@ -43,42 +50,23 @@ export const setProperty = value => {
|
|
|
43
50
|
return f
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
/**
|
|
54
|
+
* The standard codec's leaf spelling. The containers around it are
|
|
55
|
+
* `treeSerialize`'s, shared with every other JSON codec.
|
|
56
|
+
*
|
|
57
|
+
* @type {(value: Primitive) => List<string>}
|
|
58
|
+
*/
|
|
59
|
+
const primitiveSerialize = value => {
|
|
60
|
+
switch (typeof value) {
|
|
61
|
+
case 'boolean': { return boolSerialize(value) }
|
|
62
|
+
case 'number': { return numberSerialize(value) }
|
|
63
|
+
case 'string': { return stringSerialize(value) }
|
|
64
|
+
default: { return nullSerialize }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
50
67
|
|
|
51
68
|
/** @type {(mapEntries: _MapEntries) => (value: Unknown) => List<string>} */
|
|
52
|
-
export const serialize =
|
|
53
|
-
/** @type {(kv: readonly[string, Unknown]) => List<string>} */
|
|
54
|
-
const propertySerialize = ([k, v]) => flat([
|
|
55
|
-
stringSerialize(k),
|
|
56
|
-
colon,
|
|
57
|
-
f(v)
|
|
58
|
-
])
|
|
59
|
-
const mapPropertySerialize = map(propertySerialize)
|
|
60
|
-
/** @type {(object: Object) => List<string>} */
|
|
61
|
-
const objectSerialize = fn(df)
|
|
62
|
-
.map(sort)
|
|
63
|
-
.map(mapPropertySerialize)
|
|
64
|
-
.map(objectWrap)
|
|
65
|
-
.result
|
|
66
|
-
/** @type {(value: Unknown) => List<string>} */
|
|
67
|
-
const f = value => {
|
|
68
|
-
switch (typeof value) {
|
|
69
|
-
case 'boolean': { return boolSerialize(value) }
|
|
70
|
-
case 'number': { return numberSerialize(value) }
|
|
71
|
-
case 'string': { return stringSerialize(value) }
|
|
72
|
-
default: {
|
|
73
|
-
if (value === null) { return nullSerialize }
|
|
74
|
-
if (value instanceof Array) { return arraySerialize(value) }
|
|
75
|
-
return objectSerialize(value)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
const arraySerialize = compose(map(f))(arrayWrap)
|
|
80
|
-
return f
|
|
81
|
-
}
|
|
69
|
+
export const serialize = treeSerialize(primitiveSerialize)
|
|
82
70
|
|
|
83
71
|
/**
|
|
84
72
|
* The standard `JSON.stringify` rules determined by
|
|
@@ -89,6 +77,20 @@ export const serialize = sort => {
|
|
|
89
77
|
*/
|
|
90
78
|
export const stringify = sort => compose(serialize(sort))(concat)
|
|
91
79
|
|
|
80
|
+
/**
|
|
81
|
+
* The standard codec's numeric policy: every JSON number token becomes a
|
|
82
|
+
* JavaScript `number`, read from the token's own lexeme.
|
|
83
|
+
*
|
|
84
|
+
* It is total — no valid JSON number is rejected — so a magnitude outside the
|
|
85
|
+
* finite `number` range materializes the way JavaScript itself reads that
|
|
86
|
+
* text (`1e400` is `Infinity`, `1e-400` is `0`). The bigint-free domain has
|
|
87
|
+
* nothing more exact to offer; the extended codec keeps such distinctions,
|
|
88
|
+
* from the same token, without this one having to.
|
|
89
|
+
*
|
|
90
|
+
* @type {NumberPolicy<number>}
|
|
91
|
+
*/
|
|
92
|
+
const numberPolicy = token => ok(parseFloat(token.value))
|
|
93
|
+
|
|
92
94
|
/**
|
|
93
95
|
* Parses `text` as JSON with this module's own pure tokenizer and parser,
|
|
94
96
|
* reporting failure as a `Result` rather than throwing: malformed input is
|
|
@@ -101,4 +103,4 @@ export const stringify = sort => compose(serialize(sort))(concat)
|
|
|
101
103
|
*
|
|
102
104
|
* @type {(text: string) => Result<Unknown, string>}
|
|
103
105
|
*/
|
|
104
|
-
export const parse = text => parseTokens(tokenize(stringToList(text)))
|
|
106
|
+
export const parse = text => parseTokens(numberPolicy)(tokenize(stringToList(text)))
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded lexical analysis of a JSON number token.
|
|
3
|
+
*
|
|
4
|
+
* `NumberToken.value` is the canonical lossless numeric source, and these
|
|
5
|
+
* helpers read it **without narrowing it first**: every operation here costs
|
|
6
|
+
* at most the length of the token, so a valid JSON number is classified
|
|
7
|
+
* correctly whatever its magnitude. In particular no helper builds a
|
|
8
|
+
* coefficient bigint, converts an arbitrary exponent to `number`, or evaluates
|
|
9
|
+
* a power such as `10 ** exponent`.
|
|
10
|
+
*
|
|
11
|
+
* That matters for schema-directed consumers, which have to decide questions
|
|
12
|
+
* such as "is this token an integer?" *before* a materializer rounds the value
|
|
13
|
+
* into `number`: `1.00000000000000001` and `1` are the same `number` but
|
|
14
|
+
* different tokens.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*
|
|
18
|
+
* @import { Sign } from '../../../types/function/compare/types.ts'
|
|
19
|
+
* @import { NumberLexeme } from './types.ts'
|
|
20
|
+
*/
|
|
21
|
+
import type { NumberLexeme } from './types.ts';
|
|
22
|
+
/**
|
|
23
|
+
* Splits a JSON number token into its lexical parts.
|
|
24
|
+
*
|
|
25
|
+
* The token is grammar-validated by the tokenizer —
|
|
26
|
+
* `-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?` — so this is a split, not a
|
|
27
|
+
* validation.
|
|
28
|
+
*
|
|
29
|
+
* @type {(value: string) => NumberLexeme}
|
|
30
|
+
*/
|
|
31
|
+
export declare const numberLexeme: (value: string) => NumberLexeme;
|
|
32
|
+
/**
|
|
33
|
+
* Whether the lexeme is bare integer syntax: no `.` and no `e` / `E`.
|
|
34
|
+
*
|
|
35
|
+
* The distinction is lexical, not mathematical — `1e3` is not bare integer
|
|
36
|
+
* syntax even though its value is the integer `1000`.
|
|
37
|
+
*
|
|
38
|
+
* @type {(lexeme: NumberLexeme) => boolean}
|
|
39
|
+
*/
|
|
40
|
+
export declare const isBareInteger: (lexeme: NumberLexeme) => boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the lexeme spells a mathematical integer.
|
|
43
|
+
*
|
|
44
|
+
* This is the exact question, not the lexical one: `1e3` and `1.00` are
|
|
45
|
+
* integral while `1.5` is not. It stays bounded by the token's length.
|
|
46
|
+
*
|
|
47
|
+
* The value is `coefficient × 10 ** (exponent - fractionDigits)`, so it is an
|
|
48
|
+
* integer exactly when the exponent shifts the decimal point no further right
|
|
49
|
+
* than the coefficient's own trailing zeros allow. Both sides of that
|
|
50
|
+
* comparison — the fraction-digit count and the trailing-zero count — are
|
|
51
|
+
* bounded by the token, so the exponent only ever has to be compared against a
|
|
52
|
+
* small number.
|
|
53
|
+
*
|
|
54
|
+
* A zero coefficient is the simple case: zero is integral for any exponent, so
|
|
55
|
+
* the exponent is not examined at all.
|
|
56
|
+
*
|
|
57
|
+
* @type {(lexeme: NumberLexeme) => boolean}
|
|
58
|
+
*/
|
|
59
|
+
export declare const isIntegral: (lexeme: NumberLexeme) => boolean;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded lexical analysis of a JSON number token.
|
|
3
|
+
*
|
|
4
|
+
* `NumberToken.value` is the canonical lossless numeric source, and these
|
|
5
|
+
* helpers read it **without narrowing it first**: every operation here costs
|
|
6
|
+
* at most the length of the token, so a valid JSON number is classified
|
|
7
|
+
* correctly whatever its magnitude. In particular no helper builds a
|
|
8
|
+
* coefficient bigint, converts an arbitrary exponent to `number`, or evaluates
|
|
9
|
+
* a power such as `10 ** exponent`.
|
|
10
|
+
*
|
|
11
|
+
* That matters for schema-directed consumers, which have to decide questions
|
|
12
|
+
* such as "is this token an integer?" *before* a materializer rounds the value
|
|
13
|
+
* into `number`: `1.00000000000000001` and `1` are the same `number` but
|
|
14
|
+
* different tokens.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*
|
|
18
|
+
* @import { Sign } from '../../../types/function/compare/types.ts'
|
|
19
|
+
* @import { NumberLexeme } from './types.ts'
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { cmp } from '../../../types/function/compare/module.f.mjs'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Splits a JSON number token into its lexical parts.
|
|
26
|
+
*
|
|
27
|
+
* The token is grammar-validated by the tokenizer —
|
|
28
|
+
* `-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?` — so this is a split, not a
|
|
29
|
+
* validation.
|
|
30
|
+
*
|
|
31
|
+
* @type {(value: string) => NumberLexeme}
|
|
32
|
+
*/
|
|
33
|
+
export const numberLexeme = value => {
|
|
34
|
+
const sign = value.startsWith('-') ? '-' : ''
|
|
35
|
+
const unsigned = value.slice(sign.length)
|
|
36
|
+
// at most one of 'e'/'E' can occur, so whichever `indexOf` finds is it
|
|
37
|
+
const lowerE = unsigned.indexOf('e')
|
|
38
|
+
const eIndex = lowerE < 0 ? unsigned.indexOf('E') : lowerE
|
|
39
|
+
const coefficient = eIndex < 0 ? unsigned : unsigned.slice(0, eIndex)
|
|
40
|
+
const expText = eIndex < 0 ? '' : unsigned.slice(eIndex + 1)
|
|
41
|
+
const dotIndex = coefficient.indexOf('.')
|
|
42
|
+
const int = dotIndex < 0 ? coefficient : coefficient.slice(0, dotIndex)
|
|
43
|
+
const frac = dotIndex < 0 ? '' : coefficient.slice(dotIndex + 1)
|
|
44
|
+
const expSign = expText.startsWith('-')
|
|
45
|
+
? '-'
|
|
46
|
+
: expText.startsWith('+') ? '+' : ''
|
|
47
|
+
return { sign, int, frac, expSign, exp: expText.slice(expSign.length) }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Whether the lexeme is bare integer syntax: no `.` and no `e` / `E`.
|
|
52
|
+
*
|
|
53
|
+
* The distinction is lexical, not mathematical — `1e3` is not bare integer
|
|
54
|
+
* syntax even though its value is the integer `1000`.
|
|
55
|
+
*
|
|
56
|
+
* @type {(lexeme: NumberLexeme) => boolean}
|
|
57
|
+
*/
|
|
58
|
+
export const isBareInteger = ({ frac, exp }) => frac === '' && exp === ''
|
|
59
|
+
|
|
60
|
+
/** @type {(digits: string) => string} */
|
|
61
|
+
const stripLeadingZeros = digits => {
|
|
62
|
+
let i = 0
|
|
63
|
+
while (i < digits.length && digits[i] === '0') { i += 1 }
|
|
64
|
+
return digits.slice(i)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** @type {(digits: string) => number} */
|
|
68
|
+
const trailingZeroCount = digits => {
|
|
69
|
+
let n = 0
|
|
70
|
+
while (n < digits.length && digits[digits.length - 1 - n] === '0') { n += 1 }
|
|
71
|
+
return n
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Compares arbitrarily long non-negative digit text against an ordinary
|
|
76
|
+
* non-negative integer, in the length of that text.
|
|
77
|
+
*
|
|
78
|
+
* Leading zeros are dropped, so equal-length digit strings compare
|
|
79
|
+
* numerically as strings and unequal lengths are decided by length alone.
|
|
80
|
+
* `bound` therefore never has to be turned into digit text long enough to
|
|
81
|
+
* match `digits`, and `digits` never has to become a number.
|
|
82
|
+
*
|
|
83
|
+
* @type {(digits: string) => (bound: number) => Sign}
|
|
84
|
+
*/
|
|
85
|
+
const compareDigits = digits => bound => {
|
|
86
|
+
const a = stripLeadingZeros(digits)
|
|
87
|
+
const b = stripLeadingZeros(`${bound}`)
|
|
88
|
+
const byLength = cmp(a.length)(b.length)
|
|
89
|
+
return byLength === 0 ? cmp(a)(b) : byLength
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether the lexeme's exponent is at least `bound`, an ordinary integer
|
|
94
|
+
* small enough to have come from the token's own length.
|
|
95
|
+
*
|
|
96
|
+
* The exponent itself is never converted: its sign decides which side of the
|
|
97
|
+
* comparison can already be answered, and only its digit text is compared —
|
|
98
|
+
* so `1e-99999999999999999999` is settled by looking at the sign and a length,
|
|
99
|
+
* not by representing that exponent.
|
|
100
|
+
*
|
|
101
|
+
* @type {(lexeme: NumberLexeme) => (bound: number) => boolean}
|
|
102
|
+
*/
|
|
103
|
+
const exponentAtLeast = ({ expSign, exp }) => bound =>
|
|
104
|
+
expSign === '-'
|
|
105
|
+
// a negative exponent reaches `bound` only if `bound` is not positive
|
|
106
|
+
// and the exponent's magnitude stays within `-bound`
|
|
107
|
+
? bound <= 0 && compareDigits(exp)(-bound) <= 0
|
|
108
|
+
// a non-negative exponent (`''` — an absent exponent — included, since
|
|
109
|
+
// its digit text is then empty and compares as zero) always reaches a
|
|
110
|
+
// non-positive `bound`
|
|
111
|
+
: bound <= 0 || compareDigits(exp)(bound) >= 0
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Whether the lexeme spells a mathematical integer.
|
|
115
|
+
*
|
|
116
|
+
* This is the exact question, not the lexical one: `1e3` and `1.00` are
|
|
117
|
+
* integral while `1.5` is not. It stays bounded by the token's length.
|
|
118
|
+
*
|
|
119
|
+
* The value is `coefficient × 10 ** (exponent - fractionDigits)`, so it is an
|
|
120
|
+
* integer exactly when the exponent shifts the decimal point no further right
|
|
121
|
+
* than the coefficient's own trailing zeros allow. Both sides of that
|
|
122
|
+
* comparison — the fraction-digit count and the trailing-zero count — are
|
|
123
|
+
* bounded by the token, so the exponent only ever has to be compared against a
|
|
124
|
+
* small number.
|
|
125
|
+
*
|
|
126
|
+
* A zero coefficient is the simple case: zero is integral for any exponent, so
|
|
127
|
+
* the exponent is not examined at all.
|
|
128
|
+
*
|
|
129
|
+
* @type {(lexeme: NumberLexeme) => boolean}
|
|
130
|
+
*/
|
|
131
|
+
export const isIntegral = lexeme => {
|
|
132
|
+
const { int, frac } = lexeme
|
|
133
|
+
const coefficient = `${int}${frac}`
|
|
134
|
+
const zeros = trailingZeroCount(coefficient)
|
|
135
|
+
return zeros === coefficient.length || exponentAtLeast(lexeme)(frac.length - zeros)
|
|
136
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const proof: {
|
|
2
|
+
numberLexeme: {
|
|
3
|
+
int: () => void;
|
|
4
|
+
negative: () => void;
|
|
5
|
+
fraction: () => void;
|
|
6
|
+
exponent: () => void;
|
|
7
|
+
capitalExponent: () => void;
|
|
8
|
+
plusExponent: () => void;
|
|
9
|
+
minusExponent: () => void;
|
|
10
|
+
unbounded: () => void;
|
|
11
|
+
};
|
|
12
|
+
isBareInteger: {
|
|
13
|
+
int: () => void;
|
|
14
|
+
zero: () => void;
|
|
15
|
+
fraction: () => void;
|
|
16
|
+
exponent: () => void;
|
|
17
|
+
};
|
|
18
|
+
isIntegral: {
|
|
19
|
+
zero: (() => void)[];
|
|
20
|
+
plain: (() => void)[];
|
|
21
|
+
exponent: (() => void)[];
|
|
22
|
+
unbounded: (() => void)[];
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { isBareInteger, isIntegral, numberLexeme } from './module.f.mjs'
|
|
2
|
+
import { assert, assertStructurallySame } from '../../../asserts/module.f.mjs'
|
|
3
|
+
|
|
4
|
+
/** @type {(value: string) => boolean} */
|
|
5
|
+
const integral = value => isIntegral(numberLexeme(value))
|
|
6
|
+
|
|
7
|
+
/** @type {(value: string) => boolean} */
|
|
8
|
+
const bareInteger = value => isBareInteger(numberLexeme(value))
|
|
9
|
+
|
|
10
|
+
// An exponent long enough that representing it as a `number` loses digits and
|
|
11
|
+
// `10 ** exponent` is not a computation anyone can afford. Every check below
|
|
12
|
+
// that uses it must be decided by the token's shape alone.
|
|
13
|
+
const hugeExp = '99999999999999999999'
|
|
14
|
+
|
|
15
|
+
export const proof = {
|
|
16
|
+
numberLexeme: {
|
|
17
|
+
int: () => assertStructurallySame(
|
|
18
|
+
numberLexeme('123'),
|
|
19
|
+
{ sign: '', int: '123', frac: '', expSign: '', exp: '' }),
|
|
20
|
+
negative: () => assertStructurallySame(
|
|
21
|
+
numberLexeme('-123'),
|
|
22
|
+
{ sign: '-', int: '123', frac: '', expSign: '', exp: '' }),
|
|
23
|
+
fraction: () => assertStructurallySame(
|
|
24
|
+
numberLexeme('-0.125'),
|
|
25
|
+
{ sign: '-', int: '0', frac: '125', expSign: '', exp: '' }),
|
|
26
|
+
exponent: () => assertStructurallySame(
|
|
27
|
+
numberLexeme('1e10'),
|
|
28
|
+
{ sign: '', int: '1', frac: '', expSign: '', exp: '10' }),
|
|
29
|
+
capitalExponent: () => assertStructurallySame(
|
|
30
|
+
numberLexeme('1.5E10'),
|
|
31
|
+
{ sign: '', int: '1', frac: '5', expSign: '', exp: '10' }),
|
|
32
|
+
plusExponent: () => assertStructurallySame(
|
|
33
|
+
numberLexeme('1e+10'),
|
|
34
|
+
{ sign: '', int: '1', frac: '', expSign: '+', exp: '10' }),
|
|
35
|
+
minusExponent: () => assertStructurallySame(
|
|
36
|
+
numberLexeme('1e-10'),
|
|
37
|
+
{ sign: '', int: '1', frac: '', expSign: '-', exp: '10' }),
|
|
38
|
+
// nothing is narrowed, so an unrepresentable exponent is just text
|
|
39
|
+
unbounded: () => assertStructurallySame(
|
|
40
|
+
numberLexeme(`-1.5e-${hugeExp}`),
|
|
41
|
+
{ sign: '-', int: '1', frac: '5', expSign: '-', exp: hugeExp }),
|
|
42
|
+
},
|
|
43
|
+
// bare integer syntax: no `.` and no `e`/`E`, whatever the value is
|
|
44
|
+
isBareInteger: {
|
|
45
|
+
int: () => assert(bareInteger('-1230')),
|
|
46
|
+
zero: () => assert(bareInteger('-0')),
|
|
47
|
+
fraction: () => assert(!bareInteger('1.0')),
|
|
48
|
+
exponent: () => assert(!bareInteger('1e3')),
|
|
49
|
+
},
|
|
50
|
+
isIntegral: {
|
|
51
|
+
// a zero coefficient is integral at any exponent, and is decided
|
|
52
|
+
// without looking at the exponent at all
|
|
53
|
+
zero: [
|
|
54
|
+
() => assert(integral('0')),
|
|
55
|
+
() => assert(integral('-0.000')),
|
|
56
|
+
() => assert(integral(`0.0e-${hugeExp}`)),
|
|
57
|
+
],
|
|
58
|
+
plain: [
|
|
59
|
+
() => assert(integral('123')),
|
|
60
|
+
() => assert(integral('1.00')),
|
|
61
|
+
() => assert(!integral('1.5')),
|
|
62
|
+
() => assert(!integral('1.50')),
|
|
63
|
+
],
|
|
64
|
+
// the exponent moves the point; only the coefficient's own trailing
|
|
65
|
+
// zeros can absorb a move to the right
|
|
66
|
+
exponent: [
|
|
67
|
+
() => assert(integral('1e3')),
|
|
68
|
+
() => assert(integral('1.5e1')),
|
|
69
|
+
() => assert(integral('1.5e2')),
|
|
70
|
+
() => assert(integral('150e-1')),
|
|
71
|
+
() => assert(!integral('1.5e-1')),
|
|
72
|
+
() => assert(!integral('15e-2')),
|
|
73
|
+
() => assert(!integral('1.55e1')),
|
|
74
|
+
() => assert(!integral('1.0000000000001e5')),
|
|
75
|
+
// leading zeros in the exponent are not extra magnitude
|
|
76
|
+
() => assert(integral('1.5e001')),
|
|
77
|
+
],
|
|
78
|
+
// decided from lengths and a sign, never by representing the exponent
|
|
79
|
+
unbounded: [
|
|
80
|
+
() => assert(integral(`1e${hugeExp}`)),
|
|
81
|
+
() => assert(integral(`1.5e${hugeExp}`)),
|
|
82
|
+
() => assert(!integral(`1e-${hugeExp}`)),
|
|
83
|
+
() => assert(!integral(`1.5e-${hugeExp}`)),
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the lexical view of a JSON number token.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The parts of a JSON number lexeme, each kept as text.
|
|
8
|
+
*
|
|
9
|
+
* Nothing here is narrowed to a runtime numeric type, so a lexeme describes
|
|
10
|
+
* every syntactically valid JSON number — including coefficients larger than
|
|
11
|
+
* the runtime can build as a `bigint` and exponents beyond `number` precision.
|
|
12
|
+
*
|
|
13
|
+
* The empty string means "absent" for both optional parts, which is
|
|
14
|
+
* unambiguous: JSON requires at least one digit after `.` and at least one
|
|
15
|
+
* exponent digit, so a present part is never empty.
|
|
16
|
+
*/
|
|
17
|
+
export type NumberLexeme = {
|
|
18
|
+
/** `'-'` for a negative number, `''` otherwise. */
|
|
19
|
+
readonly sign: '' | '-';
|
|
20
|
+
/** The integer digits; always at least one digit. */
|
|
21
|
+
readonly int: string;
|
|
22
|
+
/** The fraction digits, or `''` when the lexeme has no `.`. */
|
|
23
|
+
readonly frac: string;
|
|
24
|
+
/** The exponent sign as written, or `''` when it is omitted. */
|
|
25
|
+
readonly expSign: '' | '+' | '-';
|
|
26
|
+
/** The exponent digits, or `''` when the lexeme has no `e` / `E`. */
|
|
27
|
+
readonly exp: string;
|
|
28
|
+
};
|