functionalscript 0.16.1 → 0.18.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/fs/asn.1/module.f.js +6 -0
- package/fs/ci/bun/module.f.js +6 -0
- package/fs/ci/common/module.f.d.ts +11 -5
- package/fs/ci/common/module.f.js +11 -4
- package/fs/ci/config/module.f.d.ts +11 -4
- package/fs/ci/config/module.f.js +11 -4
- package/fs/ci/deno/module.f.js +6 -0
- package/fs/ci/node/module.f.js +6 -0
- package/fs/ci/playwright/module.f.js +6 -0
- package/fs/ci/rust/module.f.js +7 -0
- package/fs/ci/test.f.js +2 -4
- package/fs/crypto/secp/module.f.d.ts +7 -0
- package/fs/dev/index/module.f.d.ts +6 -0
- package/fs/dev/index/module.f.js +6 -0
- package/fs/dev/module.f.d.ts +4 -3
- package/fs/dev/module.f.js +13 -11
- package/fs/dev/tf/module.d.ts +1 -0
- package/fs/dev/tf/module.f.d.ts +70 -22
- package/fs/dev/tf/module.f.js +134 -97
- package/fs/dev/tf/module.js +66 -16
- package/fs/dev/tf/test.f.d.ts +21 -20
- package/fs/dev/tf/test.f.js +249 -31
- package/fs/djs/module.f.d.ts +5 -2
- package/fs/djs/module.f.js +16 -21
- package/fs/djs/test.f.d.ts +11 -0
- package/fs/djs/test.f.js +74 -0
- package/fs/djs/tokenizer-new/test.f.js +126 -78
- package/fs/djs/transpiler/module.f.d.ts +3 -3
- package/fs/djs/transpiler/module.f.js +34 -29
- package/fs/djs/transpiler/test.f.js +19 -26
- package/fs/fjs/module.f.d.ts +2 -7
- package/fs/fjs/module.f.js +17 -17
- package/fs/fjs/module.js +2 -2
- package/fs/html/module.f.d.ts +6 -0
- package/fs/html/module.f.js +6 -0
- package/fs/io/module.d.ts +3 -3
- package/fs/io/module.f.d.ts +8 -2
- package/fs/io/module.f.js +25 -4
- package/fs/io/module.js +54 -15
- package/fs/js/tokenizer/module.f.js +7 -0
- package/fs/json/module.f.d.ts +7 -0
- package/fs/json/module.f.js +7 -0
- package/fs/path/module.f.d.ts +6 -0
- package/fs/path/module.f.js +6 -0
- package/fs/path/test.f.d.ts +3 -5
- package/fs/path/test.f.js +67 -49
- package/fs/text/module.f.d.ts +7 -0
- package/fs/text/module.f.js +7 -0
- package/fs/text/sgr/module.f.d.ts +9 -1
- package/fs/text/sgr/module.f.js +16 -5
- package/fs/text/utf16/module.f.d.ts +7 -0
- package/fs/text/utf16/module.f.js +7 -0
- package/fs/types/effects/node/module.f.d.ts +51 -9
- package/fs/types/effects/node/module.f.js +39 -2
- package/fs/types/effects/node/test.f.d.ts +4 -0
- package/fs/types/effects/node/test.f.js +33 -6
- package/fs/types/effects/node/virtual/module.f.d.ts +12 -3
- package/fs/types/effects/node/virtual/module.f.js +32 -9
- package/fs/types/function/compare/module.f.d.ts +12 -0
- package/fs/types/function/compare/module.f.js +33 -0
- package/fs/types/function/operator/test.f.d.ts +10 -0
- package/fs/types/function/operator/test.f.js +81 -0
- package/fs/types/monoid/module.f.d.ts +7 -0
- package/fs/types/number/module.f.d.ts +6 -0
- package/fs/types/number/module.f.js +6 -0
- package/fs/types/object/module.f.js +7 -0
- package/fs/types/prime_field/module.f.d.ts +8 -0
- package/fs/types/range_map/module.f.js +3 -18
- package/fs/types/result/module.f.d.ts +4 -0
- package/fs/types/result/module.f.js +4 -0
- package/fs/types/result/test.f.d.ts +2 -4
- package/fs/types/result/test.f.js +24 -16
- package/fs/types/rtti/common/module.f.d.ts +10 -1
- package/fs/types/rtti/common/module.f.js +7 -2
- package/fs/types/rtti/parse/module.f.js +35 -46
- package/fs/types/rtti/validate/module.f.js +9 -12
- package/fs/types/sorted_list/module.f.d.ts +1 -2
- package/fs/types/sorted_list/module.f.js +8 -21
- package/fs/types/sorted_set/module.f.d.ts +1 -3
- package/fs/types/ts/module.f.d.ts +7 -0
- package/fs/types/ts/test.f.d.ts +18 -0
- package/fs/types/ts/test.f.js +111 -0
- package/fs/types/uint8array/module.f.js +7 -1
- package/fs/types/uint8array/test.f.d.ts +1 -0
- package/fs/types/uint8array/test.f.js +5 -1
- package/package.json +3 -2
- package/fs/io/virtual/module.f.d.ts +0 -8
- package/fs/io/virtual/module.f.js +0 -43
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { empty, isVec, uint, vec8 } from "../../bit_vec/module.f.js";
|
|
2
2
|
import { pure } from "../module.f.js";
|
|
3
|
-
import { fetch, mkdir, now, readdir, readFile, rm, writeFile } from "./module.f.js";
|
|
3
|
+
import { fetch, mkdir, now, readdir, readFile, rm, sandbox, writeFile } from "./module.f.js";
|
|
4
4
|
import { emptyState, virtual } from "./virtual/module.f.js";
|
|
5
5
|
export default {
|
|
6
6
|
map: () => {
|
|
@@ -64,11 +64,11 @@ export default {
|
|
|
64
64
|
throw result;
|
|
65
65
|
}
|
|
66
66
|
const tmp = state.root.tmp;
|
|
67
|
-
if (tmp
|
|
67
|
+
if (typeof tmp !== 'object') {
|
|
68
68
|
throw state.root;
|
|
69
69
|
}
|
|
70
70
|
const cache = tmp.cache;
|
|
71
|
-
if (cache
|
|
71
|
+
if (typeof cache !== 'object') {
|
|
72
72
|
throw tmp;
|
|
73
73
|
}
|
|
74
74
|
},
|
|
@@ -294,7 +294,7 @@ export default {
|
|
|
294
294
|
throw result;
|
|
295
295
|
}
|
|
296
296
|
const tmp = state.root.tmp;
|
|
297
|
-
if (tmp
|
|
297
|
+
if (typeof tmp !== 'object') {
|
|
298
298
|
throw state.root;
|
|
299
299
|
}
|
|
300
300
|
if (tmp.cache !== undefined) {
|
|
@@ -327,9 +327,36 @@ export default {
|
|
|
327
327
|
},
|
|
328
328
|
},
|
|
329
329
|
now: () => {
|
|
330
|
-
const [_, result] = virtual({ ...emptyState, epochNs:
|
|
331
|
-
if (result !==
|
|
330
|
+
const [_, result] = virtual({ ...emptyState, epochNs: 1_000_000 })(now());
|
|
331
|
+
if (result !== 1_000_000) {
|
|
332
332
|
throw result;
|
|
333
333
|
}
|
|
334
334
|
},
|
|
335
|
+
sandbox: {
|
|
336
|
+
// Virtual `sandbox` is now a pass-through: the function is expected
|
|
337
|
+
// to return a `SandboxResult` directly. Fixtures dictate the result
|
|
338
|
+
// (and `duration`) instead of the runner measuring.
|
|
339
|
+
ok: () => {
|
|
340
|
+
const [_, { result, duration }] = virtual(emptyState)(sandbox(() => ({ result: ['ok', 42], duration: 0 })));
|
|
341
|
+
if (result[0] !== 'ok') {
|
|
342
|
+
throw result;
|
|
343
|
+
}
|
|
344
|
+
if (result[1] !== 42) {
|
|
345
|
+
throw result[1];
|
|
346
|
+
}
|
|
347
|
+
if (duration !== 0) {
|
|
348
|
+
throw duration;
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
error: () => {
|
|
352
|
+
const err = new Error('fail');
|
|
353
|
+
const [_, { result }] = virtual(emptyState)(sandbox(() => ({ result: ['error', err], duration: 0 })));
|
|
354
|
+
if (result[0] !== 'error') {
|
|
355
|
+
throw result;
|
|
356
|
+
}
|
|
357
|
+
if (result[1] !== err) {
|
|
358
|
+
throw result[1];
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
},
|
|
335
362
|
};
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { type Vec } from '../../../bit_vec/module.f.ts';
|
|
2
2
|
import { type RunInstance } from '../../mock/module.f.ts';
|
|
3
|
-
import type { NodeOp } from '../module.f.ts';
|
|
3
|
+
import type { Module, NodeOp } from '../module.f.ts';
|
|
4
|
+
/**
|
|
5
|
+
* In-memory JS module entry. When `import_` is called on the path, the
|
|
6
|
+
* function is invoked and its return value is the module value (with a
|
|
7
|
+
* `default` export and optional named exports). Using a function (not a
|
|
8
|
+
* plain value) lets the entry be distinguished from `Vec`/`Dir` at runtime
|
|
9
|
+
* via `typeof === 'function'`, and lets the fixture compute the module on
|
|
10
|
+
* each import for closures/state.
|
|
11
|
+
*/
|
|
12
|
+
export type JsModule = () => Module;
|
|
4
13
|
export type Dir = {
|
|
5
|
-
readonly [name in string]?: Dir | Vec;
|
|
14
|
+
readonly [name in string]?: Dir | Vec | JsModule;
|
|
6
15
|
};
|
|
7
16
|
export type State = {
|
|
8
17
|
stdout: string;
|
|
@@ -11,7 +20,7 @@ export type State = {
|
|
|
11
20
|
internet: {
|
|
12
21
|
readonly [url: string]: Vec;
|
|
13
22
|
};
|
|
14
|
-
epochNs:
|
|
23
|
+
epochNs: number;
|
|
15
24
|
};
|
|
16
25
|
export declare const emptyState: State;
|
|
17
26
|
export declare const virtual: RunInstance<NodeOp, State>;
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import { todo } from "../../../../dev/module.f.js";
|
|
6
|
+
import { assert, todo } from "../../../../dev/module.f.js";
|
|
7
7
|
import { parse } from "../../../../path/module.f.js";
|
|
8
|
+
import { utf8ToString } from "../../../../text/module.f.js";
|
|
8
9
|
import { isVec } from "../../../bit_vec/module.f.js";
|
|
9
10
|
import { error, ok } from "../../../result/module.f.js";
|
|
10
11
|
import { run } from "../../mock/module.f.js";
|
|
@@ -13,7 +14,7 @@ export const emptyState = {
|
|
|
13
14
|
stderr: '',
|
|
14
15
|
root: {},
|
|
15
16
|
internet: {},
|
|
16
|
-
epochNs:
|
|
17
|
+
epochNs: 0,
|
|
17
18
|
};
|
|
18
19
|
const operation = (op) => {
|
|
19
20
|
const f = (dir, path) => {
|
|
@@ -22,7 +23,7 @@ const operation = (op) => {
|
|
|
22
23
|
}
|
|
23
24
|
const [first, ...rest] = path;
|
|
24
25
|
const subDir = dir[first];
|
|
25
|
-
if (subDir
|
|
26
|
+
if (typeof subDir !== 'object') {
|
|
26
27
|
return op(dir, path);
|
|
27
28
|
}
|
|
28
29
|
const [newSubDir, r] = f(subDir, rest);
|
|
@@ -54,11 +55,24 @@ const readFile = readOperation((dir, path) => {
|
|
|
54
55
|
return readFileError;
|
|
55
56
|
}
|
|
56
57
|
const file = dir[path[0]];
|
|
58
|
+
if (typeof file === 'function') {
|
|
59
|
+
throw new Error(`'${path[0]}' is a JsModule; readFile not supported`);
|
|
60
|
+
}
|
|
57
61
|
if (!isVec(file)) {
|
|
58
62
|
return error(`'${path[0]}' is not a file`);
|
|
59
63
|
}
|
|
60
64
|
return ok(file);
|
|
61
65
|
});
|
|
66
|
+
const import_ = readOperation((dir, path) => {
|
|
67
|
+
if (path.length !== 1) {
|
|
68
|
+
return error('no such file');
|
|
69
|
+
}
|
|
70
|
+
const entry = dir[path[0]];
|
|
71
|
+
if (typeof entry !== 'function') {
|
|
72
|
+
return error(`'${path[0]}' is not a JsModule`);
|
|
73
|
+
}
|
|
74
|
+
return ok(entry());
|
|
75
|
+
});
|
|
62
76
|
const writeFileError = error('invalid file');
|
|
63
77
|
const writeFile = (payload) => operation((dir, path) => {
|
|
64
78
|
if (path.length !== 1) {
|
|
@@ -85,7 +99,7 @@ const readdir = (base, recursive) => readOperation((dir, path) => {
|
|
|
85
99
|
if (content === undefined) {
|
|
86
100
|
continue;
|
|
87
101
|
}
|
|
88
|
-
const isFile =
|
|
102
|
+
const isFile = typeof content !== 'object';
|
|
89
103
|
result = [...result, { name, parentPath, isFile }];
|
|
90
104
|
if (!isFile && recursive) {
|
|
91
105
|
result = [...result, ...f(`${parentPath}/${name}`, content)];
|
|
@@ -113,13 +127,12 @@ const rm = operation((dir, path) => {
|
|
|
113
127
|
if (entry === undefined) {
|
|
114
128
|
return [dir, error('no such file')];
|
|
115
129
|
}
|
|
116
|
-
if (
|
|
130
|
+
if (typeof entry === 'object') {
|
|
117
131
|
return [dir, error('is a directory')];
|
|
118
132
|
}
|
|
119
133
|
const { [name]: _, ...rest } = dir;
|
|
120
134
|
return [rest, okVoid];
|
|
121
135
|
});
|
|
122
|
-
const console = (name) => (state, payload) => [{ ...state, [name]: `${state[name]}${payload}\n` }, undefined];
|
|
123
136
|
const map = {
|
|
124
137
|
all: (state, ...a) => {
|
|
125
138
|
let e = [];
|
|
@@ -130,8 +143,6 @@ const map = {
|
|
|
130
143
|
}
|
|
131
144
|
return [state, e];
|
|
132
145
|
},
|
|
133
|
-
error: console('stderr'),
|
|
134
|
-
log: console('stdout'),
|
|
135
146
|
fetch: (state, url) => {
|
|
136
147
|
const result = state.internet[url];
|
|
137
148
|
return result === undefined ? [state, error('not found')] : [state, ok(result)];
|
|
@@ -141,12 +152,24 @@ const map = {
|
|
|
141
152
|
readdir: (state, path, { recursive }) => readdir(path, recursive === true)(state, path),
|
|
142
153
|
writeFile: (state, path, payload) => writeFile(payload)(state, path),
|
|
143
154
|
access,
|
|
144
|
-
import:
|
|
155
|
+
import: import_,
|
|
145
156
|
rm,
|
|
146
157
|
exec: todo,
|
|
147
158
|
createServer: todo,
|
|
148
159
|
listen: todo,
|
|
149
160
|
forever: todo,
|
|
150
161
|
now: (state) => [state, state.epochNs],
|
|
162
|
+
// Virtual sandbox is a pass-through: the fixture's test function is
|
|
163
|
+
// expected to return a `SandboxResult` directly (encoding pass/fail and a
|
|
164
|
+
// chosen duration), so the handler invokes it without try/catch or clock
|
|
165
|
+
// reads. This makes test outcomes deterministic — fixtures dictate the
|
|
166
|
+
// result instead of the runner measuring real execution. A genuine
|
|
167
|
+
// exception in a fixture propagates loudly as a bug in the fixture.
|
|
168
|
+
// See: issues/156-tf-virtual-tests.md
|
|
169
|
+
sandbox: (state, f) => [state, f()],
|
|
170
|
+
write: (state, stream, data) => {
|
|
171
|
+
const s = utf8ToString(data);
|
|
172
|
+
return [{ ...state, [stream]: `${state[stream]}${s}` }, undefined];
|
|
173
|
+
},
|
|
151
174
|
};
|
|
152
175
|
export const virtual = run(map);
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { Index3, Index5, Array2 } from '../../array/module.f.ts';
|
|
7
7
|
export type Sign = -1 | 0 | 1;
|
|
8
8
|
export type Compare<T> = (_: T) => Sign;
|
|
9
|
+
export type Cmp<T> = (a: T) => Compare<T>;
|
|
9
10
|
export declare const index3: <T>(cmp: Compare<T>) => (value: T) => Index3;
|
|
10
11
|
export declare const index5: <T>(cmp: Compare<T>) => (v2: Array2<T>) => Index5;
|
|
11
12
|
export type Cmp1 = boolean | string | number | bigint;
|
|
@@ -23,3 +24,14 @@ export type Cmp2<A, B> = [
|
|
|
23
24
|
B
|
|
24
25
|
] extends [bigint, bigint] ? bigint : never;
|
|
25
26
|
export declare const cmp: <A extends Cmp1>(a: A) => <B extends Cmp2<A, B>>(b: B) => Sign;
|
|
27
|
+
/**
|
|
28
|
+
* Binary search over `[0, len)`. `probe(mid)` returns the sign of the search
|
|
29
|
+
* key relative to the element at `mid` (`-1` before, `0` at, `1` after). On a
|
|
30
|
+
* hit it returns the matching index; on a miss it returns the converged lower
|
|
31
|
+
* bound `b` (the insertion point), which may equal `len`.
|
|
32
|
+
*
|
|
33
|
+
* `probe` must be monotonic over `[0, len)`: scanning indices left to right its
|
|
34
|
+
* result is non-increasing — a run of `1`s, then `0`s, then `-1`s. A
|
|
35
|
+
* non-monotonic probe yields an undefined position.
|
|
36
|
+
*/
|
|
37
|
+
export declare const bsearch: (len: number) => (probe: (mid: number) => Sign) => number;
|
|
@@ -4,3 +4,36 @@ export const index5 = cmp => ([v0, v1]) => {
|
|
|
4
4
|
return (_0 <= 0 ? _0 + 1 : cmp(v1) + 3);
|
|
5
5
|
};
|
|
6
6
|
export const cmp = (a) => (b) => a < b ? -1 : a > b ? 1 : 0;
|
|
7
|
+
/**
|
|
8
|
+
* Binary search over `[0, len)`. `probe(mid)` returns the sign of the search
|
|
9
|
+
* key relative to the element at `mid` (`-1` before, `0` at, `1` after). On a
|
|
10
|
+
* hit it returns the matching index; on a miss it returns the converged lower
|
|
11
|
+
* bound `b` (the insertion point), which may equal `len`.
|
|
12
|
+
*
|
|
13
|
+
* `probe` must be monotonic over `[0, len)`: scanning indices left to right its
|
|
14
|
+
* result is non-increasing — a run of `1`s, then `0`s, then `-1`s. A
|
|
15
|
+
* non-monotonic probe yields an undefined position.
|
|
16
|
+
*/
|
|
17
|
+
export const bsearch = (len) => (probe) => {
|
|
18
|
+
let b = 0;
|
|
19
|
+
let e = len - 1;
|
|
20
|
+
while (true) {
|
|
21
|
+
if (e < b) {
|
|
22
|
+
return b;
|
|
23
|
+
}
|
|
24
|
+
const mid = b + (e - b >> 1);
|
|
25
|
+
switch (probe(mid)) {
|
|
26
|
+
case -1: {
|
|
27
|
+
e = mid - 1;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
case 0: {
|
|
31
|
+
return mid;
|
|
32
|
+
}
|
|
33
|
+
case 1: {
|
|
34
|
+
b = mid + 1;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const joinTest: () => void;
|
|
2
|
+
export declare const concatTest: () => void;
|
|
3
|
+
export declare const logicalNotTest: () => void;
|
|
4
|
+
export declare const strictEqualTest: () => void;
|
|
5
|
+
export declare const additionTest: () => void;
|
|
6
|
+
export declare const minTest: () => void;
|
|
7
|
+
export declare const maxTest: () => void;
|
|
8
|
+
export declare const incrementTest: () => void;
|
|
9
|
+
export declare const foldToScanTest: () => void;
|
|
10
|
+
export declare const reduceToScanTest: () => void;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { join, concat, logicalNot, strictEqual, addition, min, max, increment, foldToScan, reduceToScan, } from "./module.f.js";
|
|
2
|
+
export const joinTest = () => {
|
|
3
|
+
const result = join(', ')('world')('hello');
|
|
4
|
+
if (result !== 'hello, world') {
|
|
5
|
+
throw result;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
export const concatTest = () => {
|
|
9
|
+
const result = concat('world')('hello');
|
|
10
|
+
if (result !== 'helloworld') {
|
|
11
|
+
throw result;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export const logicalNotTest = () => {
|
|
15
|
+
if (logicalNot(true) !== false) {
|
|
16
|
+
throw 'expected false';
|
|
17
|
+
}
|
|
18
|
+
if (logicalNot(false) !== true) {
|
|
19
|
+
throw 'expected true';
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
export const strictEqualTest = () => {
|
|
23
|
+
if (!strictEqual(1)(1)) {
|
|
24
|
+
throw 'expected true';
|
|
25
|
+
}
|
|
26
|
+
if (strictEqual(1)(2)) {
|
|
27
|
+
throw 'expected false';
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export const additionTest = () => {
|
|
31
|
+
const result = addition(3)(4);
|
|
32
|
+
if (result !== 7) {
|
|
33
|
+
throw result;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
export const minTest = () => {
|
|
37
|
+
if (min(3)(5) !== 3) {
|
|
38
|
+
throw 'min(3)(5)';
|
|
39
|
+
}
|
|
40
|
+
if (min(7)(2) !== 2) {
|
|
41
|
+
throw 'min(7)(2)';
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
export const maxTest = () => {
|
|
45
|
+
if (max(3)(5) !== 5) {
|
|
46
|
+
throw 'max(3)(5)';
|
|
47
|
+
}
|
|
48
|
+
if (max(7)(2) !== 7) {
|
|
49
|
+
throw 'max(7)(2)';
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
export const incrementTest = () => {
|
|
53
|
+
if (increment(4) !== 5) {
|
|
54
|
+
throw 'increment(4)';
|
|
55
|
+
}
|
|
56
|
+
if (increment(0) !== 1) {
|
|
57
|
+
throw 'increment(0)';
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
export const foldToScanTest = () => {
|
|
61
|
+
const scan = foldToScan(addition)(0);
|
|
62
|
+
const [v1, scan2] = scan(3);
|
|
63
|
+
if (v1 !== 3) {
|
|
64
|
+
throw v1;
|
|
65
|
+
}
|
|
66
|
+
const [v2] = scan2(4);
|
|
67
|
+
if (v2 !== 7) {
|
|
68
|
+
throw v2;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
export const reduceToScanTest = () => {
|
|
72
|
+
const scan = reduceToScan(addition);
|
|
73
|
+
const [v0, scan2] = scan(10);
|
|
74
|
+
if (v0 !== 10) {
|
|
75
|
+
throw v0;
|
|
76
|
+
}
|
|
77
|
+
const [v1] = scan2(5);
|
|
78
|
+
if (v1 !== 15) {
|
|
79
|
+
throw v1;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monoids: the `Monoid<T>` algebraic structure (identity plus associative
|
|
3
|
+
* binary operation) and `repeat`, which applies the operation `n` times using
|
|
4
|
+
* exponentiation by squaring.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
1
8
|
import type { Fold, Reduce } from '../function/operator/module.f.ts';
|
|
2
9
|
/**
|
|
3
10
|
* Represents a monoid, an algebraic structure with a binary operation
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Numeric list reductions (`sum`, `min`, `max`), comparison via `cmp`, and
|
|
3
|
+
* `countOnes` for 32-bit population count using SWAR.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
1
7
|
import { type List } from '../list/module.f.ts';
|
|
2
8
|
import { type Sign } from '../function/compare/module.f.ts';
|
|
3
9
|
export declare const sum: (input: List<number>) => number;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Numeric list reductions (`sum`, `min`, `max`), comparison via `cmp`, and
|
|
3
|
+
* `countOnes` for 32-bit population count using SWAR.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
1
7
|
import { reduce } from "../list/module.f.js";
|
|
2
8
|
import { addition, min as minOp, max as maxOp } from "../function/operator/module.f.js";
|
|
3
9
|
import { cmp as uCmp } from "../function/compare/module.f.js";
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-object helpers and types: `Map<T>`/`Entry<T>` shapes, safe property
|
|
3
|
+
* lookup via `at`, conversions between entries and `OrderedMap`, and the
|
|
4
|
+
* `OneKey`/`SingleProperty`/`NotUnion` utility types.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
1
8
|
import { isArray } from "../array/module.f.js";
|
|
2
9
|
import { iterable } from "../list/module.f.js";
|
|
3
10
|
import { entries as mapEntries, fromEntries as mapFromEntries } from "../ordered_map/module.f.js";
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prime field arithmetic over `bigint`: `prime_field(p)` builds a `PrimeField`
|
|
3
|
+
* with negation, addition, subtraction, multiplication, division via modular
|
|
4
|
+
* inverse, and exponentiation; `sqrt` returns a square-root function when
|
|
5
|
+
* `p % 4 === 3`.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
1
9
|
import type { Unary, Reduce } from '../bigint/module.f.ts';
|
|
2
10
|
/**
|
|
3
11
|
* A type representing a prime field and its associated operations.
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
import { genericMerge } from "../sorted_list/module.f.js";
|
|
38
38
|
import { next } from "../list/module.f.js";
|
|
39
39
|
import { cmp } from "../number/module.f.js";
|
|
40
|
+
import { bsearch } from "../function/compare/module.f.js";
|
|
40
41
|
const reduceOp = ({ union, equal }) => state => ([aItem, aMax]) => ([bItem, bMax]) => {
|
|
41
42
|
const sign = cmp(aMax)(bMax);
|
|
42
43
|
const min = sign === 1 ? bMax : aMax;
|
|
@@ -59,24 +60,8 @@ const tailReduce = equal => state => tail => {
|
|
|
59
60
|
};
|
|
60
61
|
export const merge = op => genericMerge({ reduceOp: reduceOp(op), tailReduce: tailReduce(op.equal) })(null);
|
|
61
62
|
export const get = def => value => rm => {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
let e = len - 1;
|
|
65
|
-
while (true) {
|
|
66
|
-
if (b >= len) {
|
|
67
|
-
return def;
|
|
68
|
-
}
|
|
69
|
-
if (e - b < 0) {
|
|
70
|
-
return rm[b][0];
|
|
71
|
-
}
|
|
72
|
-
const mid = b + (e - b >> 1);
|
|
73
|
-
if (value <= rm[mid][1]) {
|
|
74
|
-
e = mid - 1;
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
b = mid + 1;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
63
|
+
const pos = bsearch(rm.length)(mid => value <= rm[mid][1] ? -1 : 1);
|
|
64
|
+
return pos < rm.length ? rm[pos][0] : def;
|
|
80
65
|
};
|
|
81
66
|
export const fromRange = def => ([a, b]) => v => [[def, a - 1], [v, b]];
|
|
82
67
|
/**
|
|
@@ -51,3 +51,7 @@ export declare const error: <E>(e: E) => Error<E>;
|
|
|
51
51
|
* @returns The value if the result is successful. Otherwise, throws the error.
|
|
52
52
|
*/
|
|
53
53
|
export declare const unwrap: <T, E>([kind, v]: Result<T, E>) => T;
|
|
54
|
+
/**
|
|
55
|
+
* Swaps the `ok` and `error` cases of a result.
|
|
56
|
+
*/
|
|
57
|
+
export declare const invert: <T, E>([k, v]: Result<T, E>) => Result<E, T>;
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
import { error, ok, unwrap } from "./module.f.js";
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import { error, ok, unwrap, invert } from "./module.f.js";
|
|
2
|
+
export const example = () => {
|
|
3
|
+
const success = ok(42);
|
|
4
|
+
const failure = error('Something went wrong');
|
|
5
|
+
if (unwrap(success) !== 42) {
|
|
6
|
+
throw 'error';
|
|
7
|
+
}
|
|
8
|
+
const [kind, v] = failure;
|
|
9
|
+
if (kind !== 'error') {
|
|
10
|
+
throw 'error';
|
|
11
|
+
}
|
|
12
|
+
// `v` is inferred as `string` here
|
|
13
|
+
if (v !== 'Something went wrong') {
|
|
14
|
+
throw 'error';
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export const invertTest = () => {
|
|
18
|
+
const [k0, v0] = invert(ok(42));
|
|
19
|
+
if (k0 !== 'error' || v0 !== 42) {
|
|
20
|
+
throw [k0, v0];
|
|
21
|
+
}
|
|
22
|
+
const [k1, v1] = invert(error('oops'));
|
|
23
|
+
if (k1 !== 'ok' || v1 !== 'oops') {
|
|
24
|
+
throw [k1, v1];
|
|
17
25
|
}
|
|
18
26
|
};
|
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
* @module
|
|
24
24
|
*/
|
|
25
25
|
import type { Primitive, Unknown } from '../../../djs/module.f.ts';
|
|
26
|
-
import { type Info0, type Primitive0, type Struct, type Tuple, type Type } from '../module.f.ts';
|
|
26
|
+
import { type Info0, type Primitive0, type Struct, type Tag1, type Tuple, type Type } from '../module.f.ts';
|
|
27
27
|
import { type Error, type Result as CommonResult } from '../../result/module.f.ts';
|
|
28
28
|
import type { Ts } from '../ts/module.f.ts';
|
|
29
|
+
import { type ReadonlyRecord } from '../../object/module.f.ts';
|
|
29
30
|
/** A path to a sub-value within the validated structure. Each step is an object key or stringified array index. */
|
|
30
31
|
export type Path = readonly string[];
|
|
31
32
|
/** Detailed validation failure: the offending `path` plus a short `message`. */
|
|
@@ -65,6 +66,14 @@ export type Visitor<R> = {
|
|
|
65
66
|
readonly primitive0: (tag: Primitive0) => R;
|
|
66
67
|
readonly unknown: () => R;
|
|
67
68
|
};
|
|
69
|
+
/** Type guard narrowing `Unknown` to a specific container type `C`. */
|
|
70
|
+
export type IsContainer<C extends Unknown> = (value: Unknown) => value is C;
|
|
71
|
+
/** Maps a `Tag1` to its runtime container type. */
|
|
72
|
+
export type Container<K extends Tag1> = K extends 'array' ? ReadonlyArray<Unknown> : ReadonlyRecord<string, Unknown>;
|
|
73
|
+
/** `IsContainer` guard for arrays, shared by `validate` and `parse`. */
|
|
74
|
+
export declare const isArray: IsContainer<ReadonlyArray<Unknown>>;
|
|
75
|
+
/** `IsContainer` guard for records/structs, shared by `validate` and `parse`. */
|
|
76
|
+
export declare const isObject: IsContainer<ReadonlyRecord<string, Unknown>>;
|
|
68
77
|
/**
|
|
69
78
|
* Visits a schema `Type` by dispatching to the matching handler in `v`.
|
|
70
79
|
*
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {} from "../module.f.js";
|
|
2
2
|
import { error, ok } from "../../result/module.f.js";
|
|
3
|
-
import { isArray } from "../../array/module.f.js";
|
|
3
|
+
import { isArray as commonIsArray } from "../../array/module.f.js";
|
|
4
|
+
import { isObject as commonIsObject } from "../../object/module.f.js";
|
|
4
5
|
/** Builds an error result with empty path and the given message. */
|
|
5
6
|
export const verror = (message) => error({ path: [], message });
|
|
6
7
|
/** Prepends `key` to the error's path, used to build the path bottom-up. */
|
|
@@ -18,8 +19,12 @@ export const constPrimitiveValidate = (rtti) => value => Object.is(rtti, value)
|
|
|
18
19
|
? ok(value)
|
|
19
20
|
: verror('unexpected value');
|
|
20
21
|
const visitConst = (v) => (c) => typeof c === 'object' && c !== null
|
|
21
|
-
? (
|
|
22
|
+
? (commonIsArray(c) ? v.tuple(c) : v.struct(c))
|
|
22
23
|
: v.constPrimitive(c);
|
|
24
|
+
/** `IsContainer` guard for arrays, shared by `validate` and `parse`. */
|
|
25
|
+
export const isArray = value => commonIsArray(value);
|
|
26
|
+
/** `IsContainer` guard for records/structs, shared by `validate` and `parse`. */
|
|
27
|
+
export const isObject = value => commonIsObject(value);
|
|
23
28
|
/**
|
|
24
29
|
* Visits a schema `Type` by dispatching to the matching handler in `v`.
|
|
25
30
|
*
|