functionalscript 0.11.8 → 0.11.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.11.8",
3
+ "version": "0.11.10",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "**/*.js",
@@ -13,7 +13,7 @@
13
13
  "test": "tsc && node --test --experimental-strip-types --experimental-test-coverage --test-coverage-include=**/module.f.ts",
14
14
  "index": "node ./fjs/module.ts r ./dev/index/module.f.ts",
15
15
  "fst": "node ./fjs/module.ts t",
16
- "fjs": "node ./fjs/module.ts",
16
+ "start": "node ./fjs/module.ts",
17
17
  "ci-update": "node ./fjs/module.ts r ./ci/module.f.ts",
18
18
  "update": "git clean -fdx && npm install && npm run index && npm run ci-update",
19
19
  "website": "node --experimental-strip-types ./fjs/module.ts r ./website/module.f.ts"
@@ -1,5 +1,5 @@
1
1
  import { bitLength, max } from "../bigint/module.f.js";
2
- import { empty, isVec, length, listToVec, msb, msbCmp, uint, unpack, vec, vec8 } from "../bit_vec/module.f.js";
2
+ import { empty, isVec, length, listToVec, msb, uint, unpack, vec, vec8 } from "../bit_vec/module.f.js";
3
3
  import { identity } from "../function/module.f.js";
4
4
  import { encode as b128encode, decode as b128decode } from "../base128/module.f.js";
5
5
  const pop = msb.popFront;
@@ -163,7 +163,7 @@ export const decodeSequence = (v) => {
163
163
  return result;
164
164
  };
165
165
  /** Encodes a SET payload with canonical byte ordering. */
166
- export const encodeSet = genericEncodeSequence(v => v.toSorted((a, b) => msbCmp(a)(b)));
166
+ export const encodeSet = genericEncodeSequence(v => v.toSorted((a, b) => msb.cmp(a)(b)));
167
167
  /** Decodes a SET payload. */
168
168
  export const decodeSet = decodeSequence;
169
169
  // encode
@@ -153,6 +153,16 @@ export type BitOrder = {
153
153
  readonly xor: Reduce;
154
154
  readonly unpackPopFront: PopFront<Unpacked>;
155
155
  readonly norm: NormOp;
156
+ /**
157
+ * Lexically compares two vectors.
158
+ *
159
+ * a < b => -1
160
+ * a > b => 1
161
+ * a === b => 0
162
+ */
163
+ readonly cmp: (a: Vec) => (b: Vec) => Sign;
164
+ readonly unpackSplit: (len: bigint) => (u: Unpacked) => readonly [bigint, bigint];
165
+ readonly unpackConcat: (a: Unpacked) => (b: Unpacked) => Unpacked;
156
166
  };
157
167
  /**
158
168
  * Implements operations for handling vectors in a least-significant-bit (LSb) first order.
@@ -177,7 +187,7 @@ export declare const msb: BitOrder;
177
187
  * @param list The list of unsigned 8-bit integers to be converted.
178
188
  * @returns The resulting vector based on the provided bit order.
179
189
  */
180
- export declare const u8ListToVec: ({ concat }: BitOrder) => (list: List<number>) => Vec;
190
+ export declare const u8ListToVec: ({ unpackConcat }: BitOrder) => (list: List<number>) => Vec;
181
191
  /**
182
192
  * Converts a bit vector to a list of unsigned 8-bit integers based on the provided bit order.
183
193
  *
@@ -185,7 +195,7 @@ export declare const u8ListToVec: ({ concat }: BitOrder) => (list: List<number>)
185
195
  * @param v The vector to be converted.
186
196
  * @returns A thunk that produces a list of unsigned 8-bit integers.
187
197
  */
188
- export declare const u8List: ({ unpackPopFront }: BitOrder) => (v: Vec) => Thunk<number>;
198
+ export declare const u8List: ({ unpackSplit }: BitOrder) => (v: Vec) => Thunk<number>;
189
199
  /**
190
200
  * Concatenates a list of vectors using the provided bit order.
191
201
  */
@@ -195,14 +205,4 @@ export declare const listToVec: ({ concat }: BitOrder) => (list: List<Vec>) => V
195
205
  */
196
206
  export declare const repeat: Fold<bigint, Vec>;
197
207
  export declare const isVec: <T>(v: Vec | T) => v is Vec;
198
- /**
199
- * Lexically compares two vectors based on their unsigned integer values,
200
- * normalizing them to the same length. If the values are equal,
201
- * the shorter vector is considered smaller.
202
- *
203
- * a < b => -1
204
- * a > b => 1
205
- * a === b => 0
206
- */
207
- export declare const msbCmp: (av: Vec) => (bv: Vec) => Sign;
208
208
  export {};
@@ -107,18 +107,26 @@ const op = (norm) => (op) => ap => bp => {
107
107
  const { a, b } = norm(au)(bu)(len);
108
108
  return vec(len)(op(a)(b));
109
109
  };
110
- const bo = ({ front, removeFront, concat, rawPopFront, norm }) => {
110
+ const bo = ({ front, removeFront, norm, uintCmp, unpackSplit, unpackConcatUint }) => {
111
111
  const unpackPopFront = (len) => {
112
112
  const m = mask(len);
113
+ const us = unpackSplit(len);
113
114
  return (v) => {
114
- const [uint, rest] = rawPopFront(len)(v);
115
- return [uint & m, rest];
115
+ const [uint, rest] = us(v);
116
+ return [uint & m, { length: v.length - len, uint: rest }];
116
117
  };
117
118
  };
119
+ const unpackConcat = (a) => (b) => ({
120
+ length: a.length + b.length, uint: unpackConcatUint(a)(b)
121
+ });
118
122
  return {
119
123
  front,
120
124
  removeFront,
121
- concat,
125
+ concat: a => b => {
126
+ const au = unpack(a);
127
+ const bu = unpack(b);
128
+ return pack(unpackConcat(au)(bu));
129
+ },
122
130
  xor: op(norm)(xor),
123
131
  unpackPopFront,
124
132
  popFront: len => {
@@ -129,8 +137,20 @@ const bo = ({ front, removeFront, concat, rawPopFront, norm }) => {
129
137
  };
130
138
  },
131
139
  norm,
140
+ cmp: a => b => {
141
+ const au = unpack(a);
142
+ const bu = unpack(b);
143
+ const al = au.length;
144
+ const bl = bu.length;
145
+ const { a: aui, b: bui } = norm(au)(bu)(min(al)(bl));
146
+ const c = uintCmp(aui)(bui);
147
+ return c === 0 ? cmp(al)(bl) : c;
148
+ },
149
+ unpackSplit,
150
+ unpackConcat,
132
151
  };
133
152
  };
153
+ const lsbUnpackConcatUint = ({ uint: a, length }) => ({ uint: b }) => (b << length) | a;
134
154
  /**
135
155
  * Implements operations for handling vectors in a least-significant-bit (LSb) first order.
136
156
  *
@@ -147,13 +167,13 @@ export const lsb = bo({
147
167
  const { length, uint } = unpack(v);
148
168
  return vec(length - len)(uint >> len);
149
169
  },
150
- concat: (a) => (b) => {
151
- const { length: al, uint: au } = unpack(a);
152
- const { length: bl, uint: bu } = unpack(b);
153
- return vec(al + bl)((bu << al) | au);
154
- },
155
170
  norm: ({ uint: a }) => ({ uint: b }) => () => ({ a, b }),
156
- rawPopFront: len => ({ length, uint }) => [uint, { length: length - len, uint: uint >> len }]
171
+ uintCmp: a => b => {
172
+ const diff = a ^ b;
173
+ return diff === 0n ? 0 : (a & (diff & -diff)) === 0n ? -1 : 1;
174
+ },
175
+ unpackSplit: len => ({ uint }) => [uint, uint >> len],
176
+ unpackConcatUint: lsbUnpackConcatUint
157
177
  });
158
178
  /**
159
179
  * Implements operations for handling vectors in a most-significant-bit (MSb) first order.
@@ -174,13 +194,12 @@ export const msb = bo({
174
194
  const { length, uint } = unpack(v);
175
195
  return vec(length - len)(uint);
176
196
  },
177
- concat: flip(lsb.concat),
178
197
  norm: ({ length: al, uint: a }) => ({ length: bl, uint: b }) => len => ({ a: a << (len - al), b: b << (len - bl) }),
179
- rawPopFront: len => ({ length, uint }) => {
180
- const d = length - len;
181
- return [uint >> d, { length: d, uint }];
182
- }
198
+ uintCmp: cmp,
199
+ unpackSplit: len => ({ length, uint }) => [uint >> (length - len), uint],
200
+ unpackConcatUint: flip(lsbUnpackConcatUint),
183
201
  });
202
+ const unpackEmpty = { length: 0n, uint: 0n };
184
203
  /**
185
204
  * Converts a list of unsigned 8-bit integers to a bit vector using the provided bit order.
186
205
  *
@@ -188,16 +207,10 @@ export const msb = bo({
188
207
  * @param list The list of unsigned 8-bit integers to be converted.
189
208
  * @returns The resulting vector based on the provided bit order.
190
209
  */
191
- export const u8ListToVec = ({ concat }) => (list) => {
192
- // much faster than: `fold(appendU8(bo))(empty)(list)`
193
- // where `appendU8` is defined as
194
- // ```
195
- // const appendU8 = ({ concat }: BitOrder) => (u8: number) => (a: Vec) =>
196
- // concat(a)(vec8(BigInt(u8)))
197
- // ```
210
+ export const u8ListToVec = ({ unpackConcat }) => (list) => {
198
211
  let result = [];
199
212
  for (const b of iterable(list)) {
200
- let v = vec8(BigInt(b));
213
+ let v = { length: 8n, uint: BigInt(b) };
201
214
  let i = 0;
202
215
  while (true) {
203
216
  if (result.length <= i) {
@@ -205,16 +218,16 @@ export const u8ListToVec = ({ concat }) => (list) => {
205
218
  break;
206
219
  }
207
220
  const old = result[i];
208
- if (old === empty) {
221
+ if (old.length === 0n) {
209
222
  result = result.toSpliced(i, 1, v);
210
223
  break;
211
224
  }
212
- result = result.toSpliced(i, 1, empty);
213
- v = concat(old)(v);
225
+ result = result.toSpliced(i, 1, unpackEmpty);
226
+ v = unpackConcat(old)(v);
214
227
  i++;
215
228
  }
216
229
  }
217
- return result.reduce((p, c) => concat(c)(p), empty);
230
+ return pack(result.reduce((p, c) => unpackConcat(c)(p), unpackEmpty));
218
231
  };
219
232
  /**
220
233
  * Converts a bit vector to a list of unsigned 8-bit integers based on the provided bit order.
@@ -223,16 +236,30 @@ export const u8ListToVec = ({ concat }) => (list) => {
223
236
  * @param v The vector to be converted.
224
237
  * @returns A thunk that produces a list of unsigned 8-bit integers.
225
238
  */
226
- export const u8List = ({ unpackPopFront }) => {
227
- const pf = unpackPopFront(8n);
228
- const f = (u) => () => {
229
- if (u.length <= 0n) {
230
- return null;
239
+ export const u8List = ({ unpackSplit }) => (v) => {
240
+ if (v === empty) {
241
+ return () => null;
242
+ }
243
+ const f = (stack) => () => {
244
+ while (true) {
245
+ const [first, rest] = stack;
246
+ const { length, uint } = first;
247
+ if (length <= 8n) {
248
+ // the last unpack split is required to align data.
249
+ const v = length < 8n ? unpackSplit(8n)(first)[0] : uint;
250
+ return { first: Number(v), tail: rest !== undefined ? f(rest) : null };
251
+ }
252
+ // `length` is bigger than `8n` so `newLen` is `8n` or bigger.
253
+ const aLength = ((length + 7n) >> 4n) << 3n;
254
+ const bLength = length - aLength;
255
+ const [a, b] = unpackSplit(aLength)(first);
256
+ stack = [
257
+ { length: aLength, uint: a & mask(aLength) },
258
+ [{ length: bLength, uint: b & mask(bLength) }, rest],
259
+ ];
231
260
  }
232
- const [first, tail] = pf(u);
233
- return { first: Number(first), tail: f(tail) };
234
261
  };
235
- return v => f(unpack(v));
262
+ return f([unpack(v), undefined]);
236
263
  };
237
264
  /**
238
265
  * Concatenates a list of vectors using the provided bit order.
@@ -243,21 +270,3 @@ export const listToVec = ({ concat }) => fold(flip(concat))(empty);
243
270
  */
244
271
  export const repeat = mRepeat({ identity: empty, operation: lsb.concat });
245
272
  export const isVec = (v) => typeof v === 'bigint';
246
- /**
247
- * Lexically compares two vectors based on their unsigned integer values,
248
- * normalizing them to the same length. If the values are equal,
249
- * the shorter vector is considered smaller.
250
- *
251
- * a < b => -1
252
- * a > b => 1
253
- * a === b => 0
254
- */
255
- export const msbCmp = (av) => (bv) => {
256
- const au = unpack(av);
257
- const bu = unpack(bv);
258
- const al = au.length;
259
- const bl = bu.length;
260
- const { a, b } = msb.norm(au)(bu)(min(al)(bl));
261
- const result = cmp(a)(b);
262
- return result !== 0 ? result : cmp(al)(bl);
263
- };
@@ -37,6 +37,7 @@ declare const _default: {
37
37
  lsbXor: () => void;
38
38
  msbXor: () => void;
39
39
  repeat: () => void;
40
+ lsbCmp: () => void;
40
41
  msbCmp: () => void;
41
42
  u8ListToVec: () => () => void;
42
43
  u8ListUnaligned: () => void;
@@ -1,6 +1,6 @@
1
1
  import { mask } from "../bigint/module.f.js";
2
2
  import { asBase, asNominal } from "../nominal/module.f.js";
3
- import { length, empty, uint, vec, lsb, msb, repeat, vec8, msbCmp, u8ListToVec, u8List } from "./module.f.js";
3
+ import { length, empty, uint, vec, lsb, msb, repeat, vec8, u8ListToVec, u8List } from "./module.f.js";
4
4
  import { repeat as listRepeat, toArray } from "../list/module.f.js";
5
5
  const unsafeVec = (a) => asNominal(a);
6
6
  // 0x8 = 0b1000 = 0 + 8
@@ -430,9 +430,23 @@ export default {
430
430
  throw 'repeat failed';
431
431
  }
432
432
  },
433
+ lsbCmp: () => {
434
+ const c = (a) => (b) => (r) => {
435
+ const result = lsb.cmp(a)(b);
436
+ if (result !== r) {
437
+ throw `result: ${result}, expected: ${r}`;
438
+ }
439
+ };
440
+ c(vec(4n)(0x5n))(vec(4n)(0x5n))(0); // [1,0,1,0] == [1,0,1,0]
441
+ c(vec(4n)(0x5n))(vec(4n)(0x6n))(1); // bit0: 1 > 0
442
+ c(vec(4n)(0x6n))(vec(4n)(0x5n))(-1); // bit0: 0 < 1
443
+ c(vec(4n)(0x5n))(vec(5n)(0x5n))(-1); // equal prefix, shorter is less
444
+ c(vec(5n)(0x5n))(vec(4n)(0x5n))(1); // equal prefix, longer is greater
445
+ c(vec(4n)(0x5n))(vec(5n)(0xan))(1); // bit0: 1 > 0
446
+ },
433
447
  msbCmp: () => {
434
448
  const c = (a) => (b) => (r) => {
435
- const result = msbCmp(a)(b);
449
+ const result = msb.cmp(a)(b);
436
450
  if (result !== r) {
437
451
  throw `result: ${result}, expected: ${r}`;
438
452
  }
@@ -451,7 +465,7 @@ export default {
451
465
  const m = u8List(msb)(x);
452
466
  const y = toArray(m);
453
467
  if (y.length !== 131_071) {
454
- throw y.length;
468
+ throw `y.lenght: ${y.length}`;
455
469
  }
456
470
  };
457
471
  },
@@ -459,7 +473,7 @@ export default {
459
473
  const x = vec(9n)(0x83n);
460
474
  const a = toArray(u8List(msb)(x));
461
475
  if (a.length !== 2) {
462
- throw a;
476
+ throw `a.lenght: ${a.length}`;
463
477
  }
464
478
  const [a0, a1] = a;
465
479
  if (a0 !== 0x41) {
@@ -4,7 +4,7 @@ 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
- type NonEmpty<T> = {
7
+ export type NonEmpty<T> = {
8
8
  readonly first: T;
9
9
  readonly tail: List<T>;
10
10
  };