functionalscript 0.32.4 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +1 -1
  2. package/fs/asserts/module.f.d.ts +1 -1
  3. package/fs/asserts/module.f.js +4 -1
  4. package/fs/bnf/data/module.f.d.ts +0 -103
  5. package/fs/bnf/data/module.f.js +10 -246
  6. package/fs/bnf/data/proof.f.d.ts +0 -7
  7. package/fs/bnf/data/proof.f.js +3 -636
  8. package/fs/bnf/descent/module.f.d.ts +56 -0
  9. package/fs/bnf/descent/module.f.js +119 -0
  10. package/fs/bnf/descent/proof.f.d.ts +5 -0
  11. package/fs/bnf/descent/proof.f.js +296 -0
  12. package/fs/bnf/ll1/module.f.d.ts +72 -0
  13. package/fs/bnf/ll1/module.f.js +153 -0
  14. package/fs/bnf/ll1/proof.f.d.ts +9 -0
  15. package/fs/bnf/ll1/proof.f.js +358 -0
  16. package/fs/cas/cli/module.f.d.ts +6 -0
  17. package/fs/cas/cli/module.f.js +56 -0
  18. package/fs/cas/cli/proof.f.d.ts +14 -0
  19. package/fs/cas/cli/proof.f.js +149 -0
  20. package/fs/cas/mcp/module.f.d.ts +9 -17
  21. package/fs/cas/mcp/module.f.js +117 -83
  22. package/fs/cas/mcp/proof.f.d.ts +5 -1
  23. package/fs/cas/mcp/proof.f.js +79 -32
  24. package/fs/cas/module.f.d.ts +33 -27
  25. package/fs/cas/module.f.js +151 -126
  26. package/fs/cas/proof.f.d.ts +16 -13
  27. package/fs/cas/proof.f.js +255 -130
  28. package/fs/ci/config/module.f.d.ts +15 -15
  29. package/fs/ci/config/module.f.js +15 -15
  30. package/fs/ci/proof.f.js +8 -6
  31. package/fs/cli/proof.f.js +2 -12
  32. package/fs/djs/parser/module.f.d.ts +0 -5
  33. package/fs/djs/proof.f.js +5 -6
  34. package/fs/djs/serializer/module.f.d.ts +1 -3
  35. package/fs/djs/tokenizer-new/module.f.js +3 -2
  36. package/fs/djs/tokenizer-new/proof.f.d.ts +3 -0
  37. package/fs/djs/tokenizer-new/proof.f.js +458 -296
  38. package/fs/djs/transpiler/proof.f.js +10 -10
  39. package/fs/effects/list/module.f.d.ts +31 -0
  40. package/fs/effects/list/module.f.js +16 -0
  41. package/fs/effects/module.f.d.ts +11 -5
  42. package/fs/effects/module.f.js +16 -6
  43. package/fs/effects/node/module.f.d.ts +29 -3
  44. package/fs/effects/node/module.f.js +35 -1
  45. package/fs/effects/node/module.js +32 -18
  46. package/fs/effects/node/proof.f.js +36 -36
  47. package/fs/effects/node/virtual/module.f.d.ts +16 -2
  48. package/fs/effects/node/virtual/module.f.js +129 -20
  49. package/fs/effects/node/virtual/proof.f.d.ts +4 -0
  50. package/fs/effects/node/virtual/proof.f.js +47 -14
  51. package/fs/effects/proof.f.d.ts +4 -0
  52. package/fs/effects/proof.f.js +18 -1
  53. package/fs/emergent_testing/proof.f.js +3 -11
  54. package/fs/fjs/module.f.js +2 -8
  55. package/fs/fjs/proof.f.js +2 -11
  56. package/fs/html/module.f.js +6 -8
  57. package/fs/js/tokenizer/module.f.d.ts +5 -0
  58. package/fs/js/tokenizer/module.f.js +13 -0
  59. package/fs/json/serializer/module.f.js +0 -1
  60. package/fs/mcp/module.f.d.ts +1 -1
  61. package/fs/mime/module.f.d.ts +101 -5
  62. package/fs/mime/module.f.js +159 -6
  63. package/fs/mime/proof.f.d.ts +25 -0
  64. package/fs/mime/proof.f.js +193 -3
  65. package/fs/text/code_point/module.f.d.ts +39 -2
  66. package/fs/text/code_point/module.f.js +74 -2
  67. package/fs/text/code_point/proof.f.d.ts +8 -0
  68. package/fs/text/code_point/proof.f.js +72 -0
  69. package/fs/text/sgr/proof.f.js +2 -11
  70. package/fs/text/utf16/module.f.js +4 -26
  71. package/fs/text/utf8/module.f.d.ts +27 -0
  72. package/fs/text/utf8/module.f.js +8 -14
  73. package/fs/types/bigint/module.f.d.ts +8 -15
  74. package/fs/types/bigint/module.f.js +9 -22
  75. package/fs/types/bigint/proof.f.d.ts +0 -2
  76. package/fs/types/bigint/proof.f.js +6 -16
  77. package/fs/types/function/operator/module.f.d.ts +26 -0
  78. package/fs/types/list/module.f.d.ts +3 -0
  79. package/fs/types/result/module.d.ts +2 -4
  80. package/fs/types/result/module.js +9 -3
  81. package/package.json +3 -3
  82. package/issues/demo/data/data.f.js +0 -12
  83. package/issues/demo/data/shared.f.js +0 -3
  84. package/issues/demo/fs/app.js +0 -4
  85. package/issues/demo/fs/math.f.js +0 -4
  86. package/issues/demo/sample/proof.f.js +0 -13
  87. /package/{issues → todo}/031-json.f.d.ts +0 -0
  88. /package/{issues → todo}/031-json.f.js +0 -0
  89. /package/{issues → todo}/proof.f.d.ts +0 -0
  90. /package/{issues → todo}/proof.f.js +0 -0
@@ -1,12 +1,15 @@
1
1
  /**
2
2
  * Shared Unicode code-point contract for the UTF-8 and UTF-16 decoders: the
3
- * error-tag mask used to flag invalid sequences, and a streaming `decoder`
3
+ * error-tag mask used to flag invalid sequences, the streaming `decoder`
4
4
  * factory that wraps a per-unit step and an end-of-input step into a single
5
- * `List`-to-`List` conversion.
5
+ * `List`-to-`List` conversion, and the code-point classification predicates
6
+ * (BMP / surrogate / supplementary-plane / overall validity) that both codecs
7
+ * share.
6
8
  *
7
9
  * @module
8
10
  */
9
11
  import { flat, stateScan } from "../../types/list/module.f.js";
12
+ import { contains } from "../../types/range/module.f.js";
10
13
  /**
11
14
  * Error mask used to tag invalid code points or encoding errors. A decoded
12
15
  * value with this bit set represents a malformed unit rather than a valid
@@ -29,3 +32,72 @@ export const decoder = (byteOp, eofOp) => {
29
32
  const run = stateScan(op)(null);
30
33
  return input => flat(run(flat([input, [null]])));
31
34
  };
35
+ /**
36
+ * Unicode code-point classification boundaries. The surrogate block
37
+ * (`0xD800`–`0xDFFF`) splits into a high half (`0xD800`–`0xDBFF`) and a low half
38
+ * (`0xDC00`–`0xDFFF`); the BMP ends at `0xFFFF` and `maxCodePoint` (`0x10FFFF`)
39
+ * is the largest assignable code point. Every predicate below is derived from
40
+ * these constants so the surrogate bounds and the maximum appear exactly once.
41
+ */
42
+ const surrogateMin = 0xd800;
43
+ const lowSurrogateMin = 0xdc00;
44
+ const surrogateMax = 0xdfff;
45
+ const bmpMax = 0xffff;
46
+ const maxCodePoint = 0x10_ffff;
47
+ /**
48
+ * Checks whether the 16-bit word (U16) is a high surrogate.
49
+ * Range: 0xD800 - 0xDBFF.
50
+ */
51
+ export const isHighSurrogate = contains([surrogateMin, lowSurrogateMin - 1]);
52
+ /**
53
+ * Checks whether the 16-bit word (U16) is a low surrogate.
54
+ * Range: 0xDC00 - 0xDFFF.
55
+ */
56
+ export const isLowSurrogate = contains([lowSurrogateMin, surrogateMax]);
57
+ /**
58
+ * Ranges of code points for the lower (Low) and higher (High) parts of the BMP
59
+ * (Basic Multilingual Plane), i.e. the BMP with the surrogate block removed.
60
+ */
61
+ const lowBmp = contains([0x0000, surrogateMin - 1]);
62
+ const highBmp = contains([surrogateMax + 1, bmpMax]);
63
+ /**
64
+ * Checks whether the code point is in the BMP range.
65
+ * BMP is the main Unicode plane that covers code points 0x0000 - 0xFFFF, except
66
+ * for the range of surrogates.
67
+ */
68
+ export const isBmpCodePoint = (codePoint) => lowBmp(codePoint) || highBmp(codePoint);
69
+ /**
70
+ * Checks whether the code point belongs to a supplementary (additional) Unicode
71
+ * plane. Supplementary planes cover code points from 0x010000 to 0x10FFFF.
72
+ */
73
+ export const isSupplementaryPlane = contains([bmpMax + 1, maxCodePoint]);
74
+ /**
75
+ * The full assignable code-point range and the surrogate block, used to gate
76
+ * overall validity below.
77
+ */
78
+ const validRange = contains([0, maxCodePoint]);
79
+ const isSurrogate = contains([surrogateMin, surrogateMax]);
80
+ /**
81
+ * Checks whether the code point is a valid scalar value: within the assignable
82
+ * Unicode range (0x0000 - 0x10FFFF) and not a surrogate.
83
+ */
84
+ export const isValidCodePoint = (c) => validRange(c) && !isSurrogate(c);
85
+ /**
86
+ * The control-character blocks and the whitespace exception used to separate
87
+ * *text* code points from binary control bytes. C0 controls span 0x0000 -
88
+ * 0x001F; 0x007F (DEL) and the C1 controls (0x0080 - 0x009F) form one
89
+ * contiguous run; the whitespace block 0x0009 - 0x000D (TAB, LF, VT, FF, CR) is
90
+ * the only control range legitimate in text.
91
+ */
92
+ const c0Control = contains([0x00, 0x1f]);
93
+ const delAndC1Control = contains([0x7f, 0x9f]);
94
+ const textWhitespace = contains([0x09, 0x0d]);
95
+ /**
96
+ * Checks whether the code point is a *text* code point — distinct from
97
+ * {@link isValidCodePoint}, which gates well-formedness for decoding. A code
98
+ * point is text unless it is a control character: the controls are 0x0000 -
99
+ * 0x001F, 0x007F (DEL), and 0x0080 - 0x009F (C1), minus the whitespace block
100
+ * 0x0009 - 0x000D (TAB, LF, VT, FF, CR), which is legitimate in text. Every
101
+ * code point at or above 0x0020 that is not DEL or a C1 control is text.
102
+ */
103
+ export const isTextCodePoint = (c) => textWhitespace(c) || !(c0Control(c) || delAndC1Control(c));
@@ -0,0 +1,8 @@
1
+ export declare const proof: {
2
+ isHighSurrogate: (() => void)[];
3
+ isLowSurrogate: (() => void)[];
4
+ isBmpCodePoint: (() => void)[];
5
+ isSupplementaryPlane: (() => void)[];
6
+ isValidCodePoint: (() => void)[];
7
+ isTextCodePoint: (() => void)[];
8
+ };
@@ -0,0 +1,72 @@
1
+ import { isBmpCodePoint, isHighSurrogate, isLowSurrogate, isSupplementaryPlane, isTextCodePoint, isValidCodePoint, } from "./module.f.js";
2
+ const check = (actual, expected) => {
3
+ if (actual !== expected) {
4
+ throw `${actual} !== ${expected}`;
5
+ }
6
+ };
7
+ export const proof = {
8
+ isHighSurrogate: [
9
+ () => check(isHighSurrogate(0xd800), true),
10
+ () => check(isHighSurrogate(0xdbff), true),
11
+ () => check(isHighSurrogate(0xd7ff), false),
12
+ () => check(isHighSurrogate(0xdc00), false),
13
+ ],
14
+ isLowSurrogate: [
15
+ () => check(isLowSurrogate(0xdc00), true),
16
+ () => check(isLowSurrogate(0xdfff), true),
17
+ () => check(isLowSurrogate(0xdbff), false),
18
+ () => check(isLowSurrogate(0xe000), false),
19
+ ],
20
+ isBmpCodePoint: [
21
+ // lowBmp branch true
22
+ () => check(isBmpCodePoint(0x0000), true),
23
+ () => check(isBmpCodePoint(0xd7ff), true),
24
+ // lowBmp false, highBmp true
25
+ () => check(isBmpCodePoint(0xe000), true),
26
+ () => check(isBmpCodePoint(0xffff), true),
27
+ // both false: surrogate and supplementary
28
+ () => check(isBmpCodePoint(0xd800), false),
29
+ () => check(isBmpCodePoint(0x10000), false),
30
+ ],
31
+ isSupplementaryPlane: [
32
+ () => check(isSupplementaryPlane(0x10000), true),
33
+ () => check(isSupplementaryPlane(0x10ffff), true),
34
+ () => check(isSupplementaryPlane(0xffff), false),
35
+ () => check(isSupplementaryPlane(0x110000), false),
36
+ ],
37
+ isValidCodePoint: [
38
+ // in range, not surrogate
39
+ () => check(isValidCodePoint(0x0000), true),
40
+ () => check(isValidCodePoint(0x10ffff), true),
41
+ // in range, surrogate -> invalid
42
+ () => check(isValidCodePoint(0xd800), false),
43
+ () => check(isValidCodePoint(0xdfff), false),
44
+ // out of range -> validRange short-circuits false
45
+ () => check(isValidCodePoint(-1), false),
46
+ () => check(isValidCodePoint(0x110000), false),
47
+ ],
48
+ isTextCodePoint: [
49
+ // C0 controls are binary...
50
+ () => check(isTextCodePoint(0x00), false), // NUL
51
+ () => check(isTextCodePoint(0x08), false), // BS
52
+ () => check(isTextCodePoint(0x1b), false), // ESC
53
+ () => check(isTextCodePoint(0x1f), false), // US
54
+ // ...except the whitespace block 0x09 - 0x0D
55
+ () => check(isTextCodePoint(0x09), true), // TAB
56
+ () => check(isTextCodePoint(0x0a), true), // LF
57
+ () => check(isTextCodePoint(0x0b), true), // VT
58
+ () => check(isTextCodePoint(0x0c), true), // FF
59
+ () => check(isTextCodePoint(0x0d), true), // CR
60
+ // printable ASCII is text
61
+ () => check(isTextCodePoint(0x20), true), // space
62
+ () => check(isTextCodePoint(0x41), true), // 'A'
63
+ () => check(isTextCodePoint(0x7e), true), // '~'
64
+ // DEL and the C1 controls are binary
65
+ () => check(isTextCodePoint(0x7f), false), // DEL
66
+ () => check(isTextCodePoint(0x80), false), // C1 start
67
+ () => check(isTextCodePoint(0x9f), false), // C1 end
68
+ // above C1 is text again
69
+ () => check(isTextCodePoint(0xa0), true), // NBSP
70
+ () => check(isTextCodePoint(0x10ffff), true),
71
+ ],
72
+ };
@@ -1,15 +1,6 @@
1
1
  import { fgRed, reset, createConsoleText, backspace, csiWrite } from "./module.f.js";
2
- import { virtual, emptyState } from "../../effects/node/virtual/module.f.js";
3
- const makeOptions = (isTTY) => ({
4
- args: [],
5
- env: {},
6
- home: '.',
7
- std: { stdout: { isTTY }, stderr: { isTTY } },
8
- testContext: { test: async () => { } },
9
- bunTestContext: { test: async () => { } },
10
- playwrightTestContext: { test: async () => { } },
11
- engine: 'node',
12
- });
2
+ import { virtual, emptyState, defaultNodeProgramOptions } from "../../effects/node/virtual/module.f.js";
3
+ const makeOptions = (isTTY) => ({ ...defaultNodeProgramOptions, std: { stdout: { isTTY }, stderr: { isTTY } } });
13
4
  export const proof = [
14
5
  () => {
15
6
  if (fgRed !== '\x1b[31m') {
@@ -9,33 +9,11 @@ import { map, reduce, flatMap, empty, } from "../../types/list/module.f.js";
9
9
  import { concat } from "../../types/function/operator/module.f.js";
10
10
  import { contains } from "../../types/range/module.f.js";
11
11
  import { fn } from "../../types/function/module.f.js";
12
- import { decoder, errorMask } from "../code_point/module.f.js";
13
- /**
14
- * Ranges of code points for the lower (Low) and higher (High) parts of the BMP (Basic Multilingual Plane) plane.
15
- */
16
- const lowBmp = contains([0x0000, 0xd7ff]);
17
- const highBmp = contains([0xe000, 0xffff]);
18
- /**
19
- * Checks whether the code point is in the BMP range.
20
- * BMP is the main multi-plane Unicode plane that covers code points 0x0000 - 0xFFFF, except for the range of surrogates.
21
- */
22
- const isBmpCodePoint = (codePoint) => lowBmp(codePoint) || highBmp(codePoint);
23
- /**
24
- * Checks whether the 16-bit word (U16) is a surrogate of the high part.
25
- * Range: 0xD800 - 0xDBFF.
26
- */
27
- const isHighSurrogate = contains([0xd800, 0xdbff]);
28
- /**
29
- * Checks whether the 16-bit word (U16) is a substitute for the low part.
30
- * Range: 0xDC00 – 0xDFFF.
31
- */
32
- const isLowSurrogate = contains([0xdc00, 0xdfff]);
33
- /**
34
- * Checks whether the code point belongs to the additional (Supplementary) plane of Unicode.
35
- * Additional planes include code points from 0x010000 to 0x10FFFF.
36
- */
37
- const isSupplementaryPlane = contains([0x01_0000, 0x10_ffff]);
12
+ import { decoder, errorMask, isBmpCodePoint, isHighSurrogate, isLowSurrogate, isSupplementaryPlane, } from "../code_point/module.f.js";
38
13
  /**
14
+ * The BMP / surrogate / supplementary-plane predicates used below live in
15
+ * `code_point`, the shared Unicode contract; see that module for their ranges.
16
+ *
39
17
  * Converts a Unicode code point to its corresponding UTF-16 representation.
40
18
  *
41
19
  * This function handles:
@@ -4,6 +4,7 @@
4
4
  * @module
5
5
  */
6
6
  import { type List, type Thunk } from '../../types/list/module.f.ts';
7
+ import type { StateScan } from '../../types/function/operator/module.f.ts';
7
8
  import type { Array1, Array2, Array3 } from '../../types/array/module.f.ts';
8
9
  import { type Vec } from '../../types/bit_vec/module.f.ts';
9
10
  /**
@@ -35,6 +36,32 @@ export type Utf8State = null | Utf8NonEmptyState;
35
36
  * @returns A thunk that lazily produces a sequence of UTF-8 bytes.
36
37
  */
37
38
  export declare const fromCodePointList: (input: List<number>) => Thunk<U8>;
39
+ /**
40
+ * Converts a non-empty UTF-8 decoding state to an error code.
41
+ *
42
+ * @param state - A non-empty UTF-8 decoding state.
43
+ * @returns An I32 error code derived from the invalid UTF-8 state.
44
+ */
45
+ export declare const utf8StateToError: (state: Utf8NonEmptyState) => I32;
46
+ /**
47
+ * Decodes a byte into a Unicode code point, using a given UTF-8 state.
48
+ *
49
+ * @param state - The current UTF-8 decoding state.
50
+ * @param byte - A single byte to decode.
51
+ * @returns A tuple containing:
52
+ * - A list of decoded Unicode code points or error codes.
53
+ * - The updated UTF-8 state.
54
+ */
55
+ export declare const utf8ByteToCodePointOp: StateScan<number, Utf8State, readonly I32[]>;
56
+ /**
57
+ * Handles the end-of-file (EOF) case for UTF-8 decoding.
58
+ *
59
+ * @param state - The current UTF-8 decoding state.
60
+ * @returns A tuple containing:
61
+ * - A list of decoded Unicode code points or error codes.
62
+ * - The reset UTF-8 state (`null`).
63
+ */
64
+ export declare const utf8EofToCodePointOp: (state: Utf8State) => readonly [List<I32>, Utf8State];
38
65
  /**
39
66
  * Converts a list of UTF-8 bytes into a list of Unicode code points.
40
67
  *
@@ -4,7 +4,7 @@
4
4
  * @module
5
5
  */
6
6
  import { flatMap, toArray } from "../../types/list/module.f.js";
7
- import { decoder, errorMask } from "../code_point/module.f.js";
7
+ import { decoder, errorMask, isValidCodePoint } from "../code_point/module.f.js";
8
8
  import { msb, u8List, length } from "../../types/bit_vec/module.f.js";
9
9
  import { codePointListToString } from "../utf16/module.f.js";
10
10
  /**
@@ -106,7 +106,7 @@ export const fromCodePointList = flatMap(codePointToUtf8);
106
106
  * @param state - A non-empty UTF-8 decoding state.
107
107
  * @returns An I32 error code derived from the invalid UTF-8 state.
108
108
  */
109
- const utf8StateToError = (state) => {
109
+ export const utf8StateToError = (state) => {
110
110
  let x;
111
111
  switch (state.length) {
112
112
  case 1: {
@@ -127,8 +127,8 @@ const utf8StateToError = (state) => {
127
127
  contPayload(s2) + 0b1000_0000_0000_0000;
128
128
  break;
129
129
  }
130
- default:
131
- throw 'invalid state';
130
+ //default:
131
+ // throw 'invalid state'
132
132
  }
133
133
  return x | errorMask;
134
134
  };
@@ -141,7 +141,7 @@ const utf8StateToError = (state) => {
141
141
  * - A list of decoded Unicode code points or error codes.
142
142
  * - The updated UTF-8 state.
143
143
  */
144
- const utf8ByteToCodePointOp = (byte, state) => {
144
+ export const utf8ByteToCodePointOp = (byte, state) => {
145
145
  if (byte < 0x00 || byte > 0xff) {
146
146
  return [[errorMask], state];
147
147
  }
@@ -199,7 +199,7 @@ const utf8ByteToCodePointOp = (byte, state) => {
199
199
  * - A list of decoded Unicode code points or error codes.
200
200
  * - The reset UTF-8 state (`null`).
201
201
  */
202
- const utf8EofToCodePointOp = (state) => [
202
+ export const utf8EofToCodePointOp = (state) => [
203
203
  state === null ? null : [utf8StateToError(state)],
204
204
  null,
205
205
  ];
@@ -216,18 +216,12 @@ export const toCodePointList = decoder(utf8ByteToCodePointOp, utf8EofToCodePoint
216
216
  * code points.
217
217
  */
218
218
  export const fromVec = (v) => {
219
- if (length(v) % 8n !== 0n) {
219
+ if ((length(v) & 7n) !== 0n) {
220
220
  return null;
221
221
  }
222
222
  const arr = toArray(toCodePointList(u8List(msb)(v)));
223
223
  for (const cp of arr) {
224
- if (cp < 0) {
225
- return null;
226
- }
227
- if (cp > 0x10FFFF) {
228
- return null;
229
- }
230
- if (cp >= 0xD800 && cp <= 0xDFFF) {
224
+ if (!isValidCodePoint(cp)) {
231
225
  return null;
232
226
  }
233
227
  }
@@ -156,24 +156,17 @@ export declare const xor: Reduce;
156
156
  export declare const divUp: (b: bigint) => Unary;
157
157
  export declare const roundUp: (b: bigint) => Unary;
158
158
  /**
159
- * Divides a bigint value up to the nearest multiple of 2^e (shift-based, power-of-two only).
159
+ * Converts a bit count to a byte count, rounding up divides by `8`.
160
160
  *
161
- * @param e - The exponent (divisor = 2^e).
162
- * @returns A function that rounds a value up by the given power of two.
163
- */
164
- export declare const divUpE2: (e: bigint) => Unary;
165
- /**
166
- * Rounds a bigint value up to the nearest multiple of 2^e (shift-based, power-of-two only).
167
- *
168
- * @param e - The exponent (multiple = 2^e).
169
- * @returns A function that rounds a value up to the nearest multiple of the given power of two.
170
- */
171
- export declare const roundUpE2: (e: bigint) => Unary;
172
- /**
173
- * Converts a bit count to a byte count, rounding up — divides by `8` (`2^3` bits per byte).
161
+ * Domain: non-negative inputs (bit/byte counts). On negative inputs `divUp`
162
+ * truncates toward zero rather than flooring toward −∞, so the rounding
163
+ * direction is only meaningful for `v >= 0n`.
174
164
  */
175
165
  export declare const divUp8: Unary;
176
166
  /**
177
- * Rounds a bit count up to the nearest whole byte — the nearest multiple of `8` (`2^3` bits per byte).
167
+ * Rounds a bit count up to the nearest whole byte — the nearest multiple of `8`.
168
+ *
169
+ * Domain: non-negative inputs (bit/byte counts). See `divUp8` for the
170
+ * truncate-vs-floor caveat on negative values.
178
171
  */
179
172
  export declare const roundUp8: Unary;
@@ -234,30 +234,17 @@ export const roundUp = (b) => {
234
234
  return v => d(v) * b;
235
235
  };
236
236
  /**
237
- * Divides a bigint value up to the nearest multiple of 2^e (shift-based, power-of-two only).
237
+ * Converts a bit count to a byte count, rounding up divides by `8`.
238
238
  *
239
- * @param e - The exponent (divisor = 2^e).
240
- * @returns A function that rounds a value up by the given power of two.
239
+ * Domain: non-negative inputs (bit/byte counts). On negative inputs `divUp`
240
+ * truncates toward zero rather than flooring toward −∞, so the rounding
241
+ * direction is only meaningful for `v >= 0n`.
241
242
  */
242
- export const divUpE2 = (e) => {
243
- const m = mask(e);
244
- return v => (v + m) >> e;
245
- };
243
+ export const divUp8 = divUp(8n);
246
244
  /**
247
- * Rounds a bigint value up to the nearest multiple of 2^e (shift-based, power-of-two only).
245
+ * Rounds a bit count up to the nearest whole byte the nearest multiple of `8`.
248
246
  *
249
- * @param e - The exponent (multiple = 2^e).
250
- * @returns A function that rounds a value up to the nearest multiple of the given power of two.
251
- */
252
- export const roundUpE2 = (e) => {
253
- const d = divUpE2(e);
254
- return v => d(v) << e;
255
- };
256
- /**
257
- * Converts a bit count to a byte count, rounding up — divides by `8` (`2^3` bits per byte).
258
- */
259
- export const divUp8 = divUpE2(3n);
260
- /**
261
- * Rounds a bit count up to the nearest whole byte — the nearest multiple of `8` (`2^3` bits per byte).
247
+ * Domain: non-negative inputs (bit/byte counts). See `divUp8` for the
248
+ * truncate-vs-floor caveat on negative values.
262
249
  */
263
- export const roundUp8 = roundUpE2(3n);
250
+ export const roundUp8 = roundUp(8n);
@@ -29,8 +29,6 @@ export declare const proof: {
29
29
  combination3: () => void;
30
30
  divUp: () => void;
31
31
  roundUp: () => void;
32
- divUpE2: () => void;
33
- roundUpE2: () => void;
34
32
  divUp8: () => void;
35
33
  roundUp8: () => void;
36
34
  xor: () => void;
@@ -1,4 +1,4 @@
1
- import { sum, abs, serialize, log2, bitLength, mask, combination, factorial, xor, multiple, product, divUp, roundUp, divUpE2, roundUpE2, divUp8, roundUp8 } from "./module.f.js";
1
+ import { sum, abs, serialize, log2, bitLength, mask, combination, factorial, xor, multiple, product, divUp, roundUp, divUp8, roundUp8 } from "./module.f.js";
2
2
  import { assertEq } from "../../asserts/module.f.js";
3
3
  import { min } from "../function/compare/module.f.js";
4
4
  const oldLog2 = (v) => {
@@ -463,32 +463,22 @@ export const proof = {
463
463
  assertEq(roundUp(8n)(15n), 16n);
464
464
  assertEq(roundUp(8n)(3n), 8n);
465
465
  },
466
- divUpE2: () => {
467
- assertEq(divUpE2(3n)(8n), 1n);
468
- assertEq(divUpE2(3n)(15n), 2n);
469
- assertEq(divUpE2(3n)(0n), 0n);
470
- assertEq(divUpE2(3n)(8n), 1n);
471
- assertEq(divUpE2(3n)(9n), 2n);
472
- },
473
- roundUpE2: () => {
474
- assertEq(roundUpE2(3n)(8n), 8n);
475
- assertEq(roundUpE2(3n)(15n), 16n);
476
- assertEq(roundUpE2(3n)(3n), 8n);
477
- assertEq(roundUpE2(3n)(0n), 0n);
478
- assertEq(roundUpE2(3n)(8n), 8n);
479
- assertEq(roundUpE2(3n)(9n), 16n);
480
- },
481
466
  divUp8: () => {
482
467
  assertEq(divUp8(0n), 0n);
483
468
  assertEq(divUp8(1n), 1n);
484
469
  assertEq(divUp8(8n), 1n);
470
+ assertEq(divUp8(8n), 1n);
485
471
  assertEq(divUp8(9n), 2n);
472
+ assertEq(divUp8(15n), 2n);
486
473
  },
487
474
  roundUp8: () => {
488
475
  assertEq(roundUp8(0n), 0n);
489
476
  assertEq(roundUp8(1n), 8n);
477
+ assertEq(roundUp8(3n), 8n);
478
+ assertEq(roundUp8(8n), 8n);
490
479
  assertEq(roundUp8(8n), 8n);
491
480
  assertEq(roundUp8(9n), 16n);
481
+ assertEq(roundUp8(15n), 16n);
492
482
  },
493
483
  xor: () => {
494
484
  assertEq(xor(5n)(3n), 6n);
@@ -12,6 +12,32 @@ export declare const logicalNot: Unary<boolean, boolean>;
12
12
  export type Equal<T> = Binary<T, T, boolean>;
13
13
  export declare const strictEqual: <T>(a: T) => (b: T) => boolean;
14
14
  export type Scan<I, O> = (input: I) => readonly [O, Scan<I, O>];
15
+ /**
16
+ * One step of a stream transducer: given an `input` symbol and the `prior`
17
+ * state, produce an `output` and the next state. It both maps an input stream
18
+ * to an output stream and threads state, so it models tokenizers, decoders, and
19
+ * other stream-to-stream stages.
20
+ *
21
+ * This is the *shape* of a [Mealy machine](https://en.wikipedia.org/wiki/Mealy_machine)
22
+ * — a [finite-state transducer](https://en.wikipedia.org/wiki/Finite-state_transducer)
23
+ * — but only its signature. The state `S` (and `I`, `O`) is an arbitrary type,
24
+ * not a finite set, so a `StateScan` is strictly more expressive than a Mealy
25
+ * machine — its power is the power of `S`:
26
+ * - a finite `S`/`I`/`O` recovers the classical finite-state machine (e.g. the
27
+ * DFA states in `../../../fsm/module.f.ts`);
28
+ * - an `S` that is a stack makes it a
29
+ * [pushdown / stack machine](https://en.wikipedia.org/wiki/Pushdown_automaton)
30
+ * (context-free power — balanced brackets, nested structure, the AST tier);
31
+ * - an unbounded `S` like `bigint` can count, which no finite automaton can.
32
+ *
33
+ * And `O` may be a list (0+ symbols per input), not the single symbol strict
34
+ * Mealy emits. (Functional/coalgebraic usage still calls this `(input, state)
35
+ * => [output, state]` shape a "Mealy machine", finiteness aside.)
36
+ *
37
+ * A {@link Fold} is the output-less special case (state only); driving a
38
+ * `StateScan` over a `List` is `stateScan` in `../../list/module.f.ts`, and
39
+ * {@link stateScanToScan} hides the state to recover a {@link Scan}.
40
+ */
15
41
  export type StateScan<I, S, O> = (input: I, prior: S) => readonly [O, S];
16
42
  export declare const stateScanToScan: <I, S, O>(op: StateScan<I, S, O>) => (prior: S) => Scan<I, O>;
17
43
  export declare const foldToScan: <I, O>(fold: Fold<I, O>) => (prior: O) => Scan<I, O>;
@@ -4,6 +4,9 @@ type NotLazy<T> = Result<T> | Concat<T> | readonly T[];
4
4
  type Empty = null;
5
5
  export type Result<T> = Empty | NonEmpty<T>;
6
6
  export type Thunk<T> = () => List<T>;
7
+ /**
8
+ * See also https://en.wikipedia.org/wiki/Cons#Lists
9
+ */
7
10
  export type NonEmpty<T> = {
8
11
  readonly first: T;
9
12
  readonly tail: List<T>;
@@ -1,5 +1,3 @@
1
1
  import { type Result } from './module.f.ts';
2
- declare const _default: {
3
- readonly tryCatch: <T>(f: () => T) => Result<T, unknown>;
4
- };
5
- export default _default;
2
+ export declare const tryCatch: <T>(f: () => T) => Result<T, unknown>;
3
+ export declare const asyncTryCatch: <T>(f: () => Promise<T>) => Promise<Result<T, unknown>>;
@@ -1,5 +1,5 @@
1
1
  import { ok, error } from "./module.f.js";
2
- const tryCatch = f => {
2
+ export const tryCatch = f => {
3
3
  // Side effect: `try catch` is not allowed in FunctionalScript.
4
4
  try {
5
5
  return ok(f());
@@ -8,6 +8,12 @@ const tryCatch = f => {
8
8
  return error(e);
9
9
  }
10
10
  };
11
- export default {
12
- tryCatch,
11
+ export const asyncTryCatch = async (f) => {
12
+ // Side effect: `try catch` is not allowed in FunctionalScript.
13
+ try {
14
+ return ok(await f());
15
+ }
16
+ catch (e) {
17
+ return error(e);
18
+ }
13
19
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.32.4",
3
+ "version": "0.34.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "**/*.js",
@@ -43,8 +43,8 @@
43
43
  },
44
44
  "homepage": "https://github.com/functionalscript/functionalscript#readme",
45
45
  "devDependencies": {
46
- "@playwright/test": "1.61.0",
47
- "@types/node": "26.0.0",
46
+ "@playwright/test": "1.61.1",
47
+ "@types/node": "26.0.1",
48
48
  "typescript": "6.0.3"
49
49
  }
50
50
  }
@@ -1,12 +0,0 @@
1
- import shared from "./shared.f.js"
2
-
3
- // comment
4
- const s = "Hello, world!"
5
-
6
- export default {
7
- "a": shared,
8
- "b": shared,
9
- "s": s,
10
- d: -24n,
11
- x: undefined,
12
- }
@@ -1,3 +0,0 @@
1
- export default {
2
- "name": "shared object"
3
- }
@@ -1,4 +0,0 @@
1
- import math from "./math.f.js"
2
-
3
- const add2 = math.add(2)
4
- console.log("5 ===", add2(3))
@@ -1,4 +0,0 @@
1
- export default {
2
- add: a => b => a + b,
3
- mul: a => b => a * b,
4
- }
@@ -1,13 +0,0 @@
1
- const arrayOfTests = [
2
- () => {
3
- if (2 + 2 !== 4) throw "It's the end of the world as we know it!"
4
- },
5
- () => {
6
- if (2n + 2n !== 4n) throw "It's the end of the world as we know it!"
7
- }
8
- ]
9
-
10
- export const proof = {
11
- arrayOfTests,
12
- generatingTests: () => arrayOfTests,
13
- }
File without changes
File without changes
File without changes
File without changes