functionalscript 0.32.4 → 0.33.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/bnf/data/proof.f.d.ts +3 -0
- package/fs/bnf/data/proof.f.js +7 -0
- package/fs/cas/mcp/module.f.js +3 -1
- package/fs/cas/mcp/proof.f.js +16 -11
- package/fs/cas/module.f.d.ts +5 -19
- package/fs/cas/module.f.js +42 -54
- package/fs/cas/proof.f.js +15 -24
- package/fs/ci/config/module.f.d.ts +6 -6
- package/fs/ci/config/module.f.js +6 -6
- package/fs/ci/proof.f.js +8 -6
- package/fs/cli/proof.f.js +2 -12
- package/fs/djs/parser/module.f.d.ts +0 -5
- package/fs/djs/proof.f.js +5 -6
- package/fs/djs/serializer/module.f.d.ts +1 -3
- package/fs/djs/tokenizer-new/module.f.js +2 -1
- package/fs/djs/tokenizer-new/proof.f.d.ts +1 -0
- package/fs/djs/tokenizer-new/proof.f.js +101 -67
- package/fs/djs/transpiler/proof.f.js +10 -10
- package/fs/effects/node/proof.f.js +36 -36
- package/fs/effects/node/virtual/module.f.d.ts +16 -2
- package/fs/effects/node/virtual/module.f.js +72 -20
- package/fs/effects/node/virtual/proof.f.d.ts +4 -0
- package/fs/effects/node/virtual/proof.f.js +47 -14
- package/fs/emergent_testing/proof.f.js +3 -11
- package/fs/fjs/module.f.js +3 -3
- package/fs/fjs/proof.f.js +2 -11
- package/fs/js/tokenizer/module.f.d.ts +5 -0
- package/fs/js/tokenizer/module.f.js +13 -0
- package/fs/json/serializer/module.f.js +0 -1
- package/fs/text/sgr/proof.f.js +2 -11
- package/fs/types/bigint/module.f.d.ts +8 -15
- package/fs/types/bigint/module.f.js +9 -22
- package/fs/types/bigint/proof.f.d.ts +0 -2
- package/fs/types/bigint/proof.f.js +6 -16
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { todo } from "../../../asserts/module.f.js";
|
|
7
7
|
import { join, parse } from "../../../path/module.f.js";
|
|
8
8
|
import { utf8ToString } from "../../../text/module.f.js";
|
|
9
|
-
import {
|
|
9
|
+
import { empty, length, maxLengthBytes, msb, vec } from "../../../types/bit_vec/module.f.js";
|
|
10
10
|
import { error, ok } from "../../../types/result/module.f.js";
|
|
11
11
|
import { run } from "../../mock/module.f.js";
|
|
12
12
|
import { asBase, asNominal } from "../../memory/module.f.js";
|
|
@@ -28,7 +28,7 @@ const operation = (op) => {
|
|
|
28
28
|
}
|
|
29
29
|
const [first, ...rest] = path;
|
|
30
30
|
const subDir = dir[first];
|
|
31
|
-
if (typeof subDir !== 'object') {
|
|
31
|
+
if (typeof subDir !== 'object' || Array.isArray(subDir)) {
|
|
32
32
|
return op(dir, path);
|
|
33
33
|
}
|
|
34
34
|
const [newSubDir, r] = f(subDir, rest);
|
|
@@ -67,11 +67,23 @@ const readFile = readOperation((dir, path) => {
|
|
|
67
67
|
if (file === undefined) {
|
|
68
68
|
return enoent;
|
|
69
69
|
}
|
|
70
|
-
|
|
71
|
-
if (!isVec(file)) {
|
|
70
|
+
if (!Array.isArray(file)) {
|
|
72
71
|
return error(`'${path[0]}' is not a file`);
|
|
73
72
|
}
|
|
74
|
-
|
|
73
|
+
const chunks = file;
|
|
74
|
+
const capBits = maxLengthBytes * 8n;
|
|
75
|
+
let result = empty;
|
|
76
|
+
for (const chunk of chunks) {
|
|
77
|
+
const chunkLen = length(chunk);
|
|
78
|
+
if (chunkLen === 0n) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (length(result) + chunkLen > capBits) {
|
|
82
|
+
return error(`File size exceeds maximum allowed size of ${maxLengthBytes} bytes`);
|
|
83
|
+
}
|
|
84
|
+
result = msb.concat(result)(chunk);
|
|
85
|
+
}
|
|
86
|
+
return ok(result);
|
|
75
87
|
});
|
|
76
88
|
const import_ = readOperation((dir, path) => {
|
|
77
89
|
if (path.length !== 1) {
|
|
@@ -90,11 +102,10 @@ const writeFile = (payload) => operation((dir, path) => {
|
|
|
90
102
|
}
|
|
91
103
|
const [name] = path;
|
|
92
104
|
const file = dir[name];
|
|
93
|
-
|
|
94
|
-
if (file !== undefined && !isVec(file)) {
|
|
105
|
+
if (file !== undefined && !Array.isArray(file)) {
|
|
95
106
|
return [dir, writeFileError];
|
|
96
107
|
}
|
|
97
|
-
dir = { ...dir, [name]: payload };
|
|
108
|
+
dir = { ...dir, [name]: [payload] };
|
|
98
109
|
return [dir, okVoid];
|
|
99
110
|
});
|
|
100
111
|
const invalidPath = error('invalid path');
|
|
@@ -109,7 +120,7 @@ const readdir = (base, recursive) => readOperation((dir, path) => {
|
|
|
109
120
|
if (content === undefined) {
|
|
110
121
|
continue;
|
|
111
122
|
}
|
|
112
|
-
const isFile = typeof content !== 'object';
|
|
123
|
+
const isFile = Array.isArray(content) || typeof content !== 'object';
|
|
113
124
|
result = [...result, { name, parentPath, isFile }];
|
|
114
125
|
if (!isFile && recursive) {
|
|
115
126
|
result = [...result, ...f(join(parentPath, name), content)];
|
|
@@ -137,7 +148,7 @@ const rm = operation((dir, path) => {
|
|
|
137
148
|
if (entry === undefined) {
|
|
138
149
|
return [dir, error('no such file')];
|
|
139
150
|
}
|
|
140
|
-
if (typeof entry === 'object') {
|
|
151
|
+
if (!Array.isArray(entry) && typeof entry === 'object') {
|
|
141
152
|
return [dir, error('is a directory')];
|
|
142
153
|
}
|
|
143
154
|
const { [name]: _, ...rest } = dir;
|
|
@@ -158,7 +169,7 @@ const extractEntity = (dir, path) => {
|
|
|
158
169
|
}
|
|
159
170
|
const [first, ...rest] = path;
|
|
160
171
|
const sub = dir[first];
|
|
161
|
-
if (sub === undefined ||
|
|
172
|
+
if (sub === undefined || Array.isArray(sub) || typeof sub === 'function') {
|
|
162
173
|
return [dir, enoent];
|
|
163
174
|
}
|
|
164
175
|
const [newSub, result] = extractEntity(sub, rest);
|
|
@@ -175,8 +186,8 @@ const insertEntityAt = (dir, path, entity) => {
|
|
|
175
186
|
const [name] = path;
|
|
176
187
|
const existing = dir[name];
|
|
177
188
|
if (existing !== undefined) {
|
|
178
|
-
const entityIsDir = typeof entity === 'object';
|
|
179
|
-
const existingIsDir = typeof existing === 'object';
|
|
189
|
+
const entityIsDir = !Array.isArray(entity) && typeof entity === 'object';
|
|
190
|
+
const existingIsDir = !Array.isArray(existing) && typeof existing === 'object';
|
|
180
191
|
if (entityIsDir && !existingIsDir) {
|
|
181
192
|
return [dir, error(`cannot overwrite file '${name}' with a directory`)];
|
|
182
193
|
}
|
|
@@ -198,7 +209,7 @@ const insertEntityAt = (dir, path, entity) => {
|
|
|
198
209
|
if (sub === undefined) {
|
|
199
210
|
return [dir, enoent];
|
|
200
211
|
}
|
|
201
|
-
if (
|
|
212
|
+
if (Array.isArray(sub) || typeof sub === 'function') {
|
|
202
213
|
return [dir, error('not a directory')];
|
|
203
214
|
}
|
|
204
215
|
const [newSub, result] = insertEntityAt(sub, rest, entity);
|
|
@@ -238,7 +249,7 @@ const readBytesOp = (path, offset, size) => readOperation((dir, p) => {
|
|
|
238
249
|
if (file === undefined) {
|
|
239
250
|
return enoent;
|
|
240
251
|
}
|
|
241
|
-
if (!
|
|
252
|
+
if (!Array.isArray(file)) {
|
|
242
253
|
return error(`'${p[0]}' is not a file`);
|
|
243
254
|
}
|
|
244
255
|
if (!Number.isInteger(offset)) {
|
|
@@ -256,11 +267,28 @@ const readBytesOp = (path, offset, size) => readOperation((dir, p) => {
|
|
|
256
267
|
if (BigInt(size) > maxLengthBytes) {
|
|
257
268
|
return error(`Chunk size ${size} exceeds maximum allowed size of ${maxLengthBytes} bytes`);
|
|
258
269
|
}
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
270
|
+
const chunks = file;
|
|
271
|
+
let toSkip = BigInt(offset) * 8n;
|
|
272
|
+
let toRead = BigInt(size) * 8n;
|
|
273
|
+
let result = empty;
|
|
274
|
+
for (const chunk of chunks) {
|
|
275
|
+
if (toRead === 0n) {
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
const chunkBits = length(chunk);
|
|
279
|
+
if (toSkip >= chunkBits) {
|
|
280
|
+
toSkip -= chunkBits;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
const skipInChunk = toSkip;
|
|
284
|
+
const availableBits = chunkBits - skipInChunk;
|
|
285
|
+
const takeBits = availableBits <= toRead ? availableBits : toRead;
|
|
286
|
+
const taken = vec(takeBits)(msb.front(takeBits)(msb.removeFront(skipInChunk)(chunk)));
|
|
287
|
+
result = msb.concat(result)(taken);
|
|
288
|
+
toSkip = 0n;
|
|
289
|
+
toRead -= takeBits;
|
|
290
|
+
}
|
|
291
|
+
return ok(result);
|
|
264
292
|
})(path);
|
|
265
293
|
const map = {
|
|
266
294
|
all: (...a) => state => {
|
|
@@ -330,3 +358,27 @@ const map = {
|
|
|
330
358
|
},
|
|
331
359
|
};
|
|
332
360
|
export const virtual = run(map);
|
|
361
|
+
const testContext = { test: todo };
|
|
362
|
+
/**
|
|
363
|
+
* Safe, inert defaults for every {@link NodeProgramOptions} field, intended for
|
|
364
|
+
* proof files that need to call a program without owning the full literal.
|
|
365
|
+
*
|
|
366
|
+
* Proofs spread-override only what their test cares about:
|
|
367
|
+
*
|
|
368
|
+
* ```ts
|
|
369
|
+
* const opts: NodeProgramOptions = { ...defaultNodeProgramOptions, args }
|
|
370
|
+
* ```
|
|
371
|
+
*
|
|
372
|
+
* Future additions to `NodeProgramOptions` only need a default added here,
|
|
373
|
+
* keeping unrelated proof files from churning.
|
|
374
|
+
*/
|
|
375
|
+
export const defaultNodeProgramOptions = {
|
|
376
|
+
args: [],
|
|
377
|
+
env: {},
|
|
378
|
+
home: '.',
|
|
379
|
+
std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
|
|
380
|
+
testContext,
|
|
381
|
+
bunTestContext: testContext,
|
|
382
|
+
playwrightTestContext: testContext,
|
|
383
|
+
engine: 'node',
|
|
384
|
+
};
|
|
@@ -19,9 +19,13 @@ export declare const proof: {
|
|
|
19
19
|
renameOntoOwnAncestor: () => void;
|
|
20
20
|
renameNonEmptyDirOverEmptyDir: () => void;
|
|
21
21
|
renameEmptyDirOverNonEmptyDir: () => void;
|
|
22
|
+
renameFileOntoDirectory: () => void;
|
|
23
|
+
readFileTooLarge: () => void;
|
|
22
24
|
readBytesNegativeSize: () => void;
|
|
23
25
|
readBytesZeroSize: () => void;
|
|
24
26
|
readBytesNegativeOffset: () => void;
|
|
25
27
|
readBytesFractionalSize: () => void;
|
|
26
28
|
readBytesFractionalOffset: () => void;
|
|
29
|
+
readBytesAcrossChunkBoundary: () => void;
|
|
30
|
+
largeFileReadBytes: () => void;
|
|
27
31
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { assertEq } from "../../../asserts/module.f.js";
|
|
2
2
|
import { awaitIfPromise, fetch, rm, writeFile, readFile, readdir, import_, rename, readBytes } from "../module.f.js";
|
|
3
|
-
import { vec8 } from "../../../types/bit_vec/module.f.js";
|
|
3
|
+
import { maxLengthBytes, vec, vec8 } from "../../../types/bit_vec/module.f.js";
|
|
4
4
|
import { emptyState, virtual } from "./module.f.js";
|
|
5
5
|
export const proof = {
|
|
6
6
|
rm: {
|
|
7
7
|
success: () => {
|
|
8
|
-
const root = { 'a.txt': vec8(0x42n) };
|
|
8
|
+
const root = { 'a.txt': [vec8(0x42n)] };
|
|
9
9
|
const [, result] = virtual({ ...emptyState, root })(rm('a.txt'));
|
|
10
10
|
assertEq(result[0], 'ok');
|
|
11
11
|
},
|
|
@@ -27,7 +27,7 @@ export const proof = {
|
|
|
27
27
|
assertEq(result[0], 'error');
|
|
28
28
|
},
|
|
29
29
|
readdirRecursive: () => {
|
|
30
|
-
const file = vec8(0x42n);
|
|
30
|
+
const file = [vec8(0x42n)];
|
|
31
31
|
const sub = { 'file.txt': file };
|
|
32
32
|
const outer = { 'sub': sub };
|
|
33
33
|
const root = { 'mydir': outer };
|
|
@@ -65,7 +65,7 @@ export const proof = {
|
|
|
65
65
|
},
|
|
66
66
|
importNonModule: () => {
|
|
67
67
|
// import_ on a Vec (not a JsModule) covers typeof entry !== 'function' branch
|
|
68
|
-
const root = { 'module.f.ts': vec8(0x42n) };
|
|
68
|
+
const root = { 'module.f.ts': [vec8(0x42n)] };
|
|
69
69
|
const [, result] = virtual({ ...emptyState, root })(import_('module.f.ts'));
|
|
70
70
|
assertEq(result[0], 'error');
|
|
71
71
|
},
|
|
@@ -78,62 +78,95 @@ export const proof = {
|
|
|
78
78
|
},
|
|
79
79
|
renameSamePath: () => {
|
|
80
80
|
// rename('a', 'a') should succeed as a no-op, not reject
|
|
81
|
-
const root = { 'a': vec8(0x42n) };
|
|
81
|
+
const root = { 'a': [vec8(0x42n)] };
|
|
82
82
|
const [, result] = virtual({ ...emptyState, root })(rename('a', 'a'));
|
|
83
83
|
assertEq(result[0], 'ok');
|
|
84
84
|
},
|
|
85
85
|
renameIntoOwnSubtree: () => {
|
|
86
86
|
// rename('a', 'a/b') should fail (dst inside src's subtree)
|
|
87
|
-
const root = { 'a': { 'b': vec8(0x42n) } };
|
|
87
|
+
const root = { 'a': { 'b': [vec8(0x42n)] } };
|
|
88
88
|
const [, result] = virtual({ ...emptyState, root })(rename('a', 'a/b'));
|
|
89
89
|
assertEq(result[0], 'error');
|
|
90
90
|
},
|
|
91
91
|
renameOntoOwnAncestor: () => {
|
|
92
92
|
// rename('a/b', 'a') should fail (src inside dst's subtree)
|
|
93
|
-
const root = { 'a': { 'b': vec8(0x42n) } };
|
|
93
|
+
const root = { 'a': { 'b': [vec8(0x42n)] } };
|
|
94
94
|
const [, result] = virtual({ ...emptyState, root })(rename('a/b', 'a'));
|
|
95
95
|
assertEq(result[0], 'error');
|
|
96
96
|
},
|
|
97
97
|
renameNonEmptyDirOverEmptyDir: () => {
|
|
98
98
|
// rename a directory onto an empty directory should succeed
|
|
99
|
-
const root = { 'src': { 'file': vec8(0x42n) }, 'dst': {} };
|
|
99
|
+
const root = { 'src': { 'file': [vec8(0x42n)] }, 'dst': {} };
|
|
100
100
|
const [, result] = virtual({ ...emptyState, root })(rename('src', 'dst'));
|
|
101
101
|
assertEq(result[0], 'ok');
|
|
102
102
|
},
|
|
103
103
|
renameEmptyDirOverNonEmptyDir: () => {
|
|
104
104
|
// rename an empty directory onto a non-empty directory should fail
|
|
105
|
-
const root = { 'src': {}, 'dst': { 'file': vec8(0x42n) } };
|
|
105
|
+
const root = { 'src': {}, 'dst': { 'file': [vec8(0x42n)] } };
|
|
106
106
|
const [, result] = virtual({ ...emptyState, root })(rename('src', 'dst'));
|
|
107
107
|
assertEq(result[0], 'error');
|
|
108
108
|
},
|
|
109
|
+
renameFileOntoDirectory: () => {
|
|
110
|
+
// rename a file to a path that is already an existing directory should fail
|
|
111
|
+
const root = { 'myfile': [vec8(0x42n)], 'mydir': {} };
|
|
112
|
+
const [, result] = virtual({ ...emptyState, root })(rename('myfile', 'mydir'));
|
|
113
|
+
assertEq(result[0], 'error');
|
|
114
|
+
},
|
|
115
|
+
readFileTooLarge: () => {
|
|
116
|
+
// a file stored as two max-size chunks exceeds the limit; readFile must return an error
|
|
117
|
+
const chunk0 = vec(maxLengthBytes * 8n)(0n);
|
|
118
|
+
const chunk1 = vec(1n)(1n);
|
|
119
|
+
const root = { 'big': [chunk0, chunk1] };
|
|
120
|
+
const [, result] = virtual({ ...emptyState, root })(readFile('big'));
|
|
121
|
+
assertEq(result[0], 'error');
|
|
122
|
+
},
|
|
109
123
|
readBytesNegativeSize: () => {
|
|
110
124
|
// readBytes with negative size should fail
|
|
111
|
-
const root = { 'file': vec8(0x42n) };
|
|
125
|
+
const root = { 'file': [vec8(0x42n)] };
|
|
112
126
|
const [, result] = virtual({ ...emptyState, root })(readBytes('file', 0, -1));
|
|
113
127
|
assertEq(result[0], 'error');
|
|
114
128
|
},
|
|
115
129
|
readBytesZeroSize: () => {
|
|
116
130
|
// readBytes with zero size should succeed and return empty vec
|
|
117
|
-
const root = { 'file': vec8(0x42n) };
|
|
131
|
+
const root = { 'file': [vec8(0x42n)] };
|
|
118
132
|
const [, result] = virtual({ ...emptyState, root })(readBytes('file', 0, 0));
|
|
119
133
|
assertEq(result[0], 'ok');
|
|
120
134
|
},
|
|
121
135
|
readBytesNegativeOffset: () => {
|
|
122
136
|
// readBytes with negative offset should fail
|
|
123
|
-
const root = { 'file': vec8(0x42n) };
|
|
137
|
+
const root = { 'file': [vec8(0x42n)] };
|
|
124
138
|
const [, result] = virtual({ ...emptyState, root })(readBytes('file', -1, 1));
|
|
125
139
|
assertEq(result[0], 'error');
|
|
126
140
|
},
|
|
127
141
|
readBytesFractionalSize: () => {
|
|
128
142
|
// readBytes with fractional size should fail rather than throw RangeError
|
|
129
|
-
const root = { 'file': vec8(0x42n) };
|
|
143
|
+
const root = { 'file': [vec8(0x42n)] };
|
|
130
144
|
const [, result] = virtual({ ...emptyState, root })(readBytes('file', 0, 1.5));
|
|
131
145
|
assertEq(result[0], 'error');
|
|
132
146
|
},
|
|
133
147
|
readBytesFractionalOffset: () => {
|
|
134
148
|
// readBytes with fractional offset should fail rather than throw RangeError
|
|
135
|
-
const root = { 'file': vec8(0x42n) };
|
|
149
|
+
const root = { 'file': [vec8(0x42n)] };
|
|
136
150
|
const [, result] = virtual({ ...emptyState, root })(readBytes('file', 0.5, 1));
|
|
137
151
|
assertEq(result[0], 'error');
|
|
138
152
|
},
|
|
153
|
+
readBytesAcrossChunkBoundary: () => {
|
|
154
|
+
// Two 128 KiB chunks; read 2 bytes spanning the boundary (last byte of chunk 0, first of chunk 1).
|
|
155
|
+
const chunkSize = Number(maxLengthBytes);
|
|
156
|
+
const chunk0 = vec(maxLengthBytes * 8n)(0xaan);
|
|
157
|
+
const chunk1 = vec(maxLengthBytes * 8n)(0xbbn);
|
|
158
|
+
const root = { 'big': [chunk0, chunk1] };
|
|
159
|
+
const [, result] = virtual({ ...emptyState, root })(readBytes('big', chunkSize - 1, 2));
|
|
160
|
+
assertEq(result[0], 'ok');
|
|
161
|
+
},
|
|
162
|
+
largeFileReadBytes: () => {
|
|
163
|
+
// A file stored as two 128 KiB chunks is larger than maxLengthBytes.
|
|
164
|
+
// readBytes within the second chunk (offset = 128 KiB, size = 1) should succeed.
|
|
165
|
+
const chunkSize = Number(maxLengthBytes);
|
|
166
|
+
const chunk0 = vec(maxLengthBytes * 8n)(0n);
|
|
167
|
+
const chunk1 = vec(maxLengthBytes * 8n)(0xffn);
|
|
168
|
+
const root = { 'large': [chunk0, chunk1] };
|
|
169
|
+
const [, result] = virtual({ ...emptyState, root })(readBytes('large', chunkSize, 1));
|
|
170
|
+
assertEq(result[0], 'ok');
|
|
171
|
+
},
|
|
139
172
|
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { pure } from "../effects/module.f.js";
|
|
2
1
|
import { log } from "../effects/node/module.f.js";
|
|
3
|
-
import { emptyState } from "../effects/node/virtual/module.f.js";
|
|
2
|
+
import { defaultNodeProgramOptions, emptyState } from "../effects/node/virtual/module.f.js";
|
|
4
3
|
import { virtual } from "../effects/node/virtual/module.f.js";
|
|
5
|
-
import { assert, assertEq
|
|
4
|
+
import { assert, assertEq } from "../asserts/module.f.js";
|
|
6
5
|
import { testAll, defaultReporter, fmtPath, fmtTerm, fmtImport, ghEscape, isInteger, isIdentifier, registerModule, parseTestSet, defaultTest, } from "./module.f.js";
|
|
7
6
|
import { run as mockRun } from "../effects/mock/module.f.js";
|
|
8
7
|
import { shouldLoad } from "../dev/module.f.js";
|
|
@@ -13,16 +12,9 @@ const makeReporter = () => ({
|
|
|
13
12
|
summary: (pass, fail, time) => writeEvent(['summary', pass, fail, time]),
|
|
14
13
|
test: defaultTest,
|
|
15
14
|
});
|
|
16
|
-
const noopTestContext = { test: todo };
|
|
17
15
|
const options = (initCwd, github = false) => ({
|
|
18
|
-
|
|
16
|
+
...defaultNodeProgramOptions,
|
|
19
17
|
env: { INIT_CWD: initCwd, ...(github ? { GITHUB_ACTIONS: 'true' } : {}) },
|
|
20
|
-
home: '.',
|
|
21
|
-
std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
|
|
22
|
-
testContext: noopTestContext,
|
|
23
|
-
bunTestContext: noopTestContext,
|
|
24
|
-
playwrightTestContext: noopTestContext,
|
|
25
|
-
engine: 'node',
|
|
26
18
|
});
|
|
27
19
|
const ok0 = () => ({ result: ['ok', undefined], duration: 0 });
|
|
28
20
|
const fail0 = () => ({ result: ['error', 'oops'], duration: 0 });
|
package/fs/fjs/module.f.js
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { compile } from "../djs/module.f.js";
|
|
7
7
|
import { main as testMain } from "../emergent_testing/module.f.js";
|
|
8
|
-
import { commands as casCommands } from "../cas/module.f.js";
|
|
8
|
+
import { commands as casCommands, fileCas } from "../cas/module.f.js";
|
|
9
9
|
import { main as ciMain } from "../ci/module.f.js";
|
|
10
10
|
import { import_ } from "../effects/node/module.f.js";
|
|
11
11
|
import { dispatch } from "../cli/module.f.js";
|
|
12
12
|
import { casMcpServer } from "../cas/mcp/module.f.js";
|
|
13
|
-
import {
|
|
13
|
+
import { toPath } from "../cas/module.f.js";
|
|
14
14
|
import { sha256 } from "../crypto/sha2/module.f.js";
|
|
15
15
|
import { join } from "../path/module.f.js";
|
|
16
16
|
import { pure } from "../effects/module.f.js";
|
|
@@ -34,7 +34,7 @@ const commands = [
|
|
|
34
34
|
names: ['mcp', 'm'],
|
|
35
35
|
description: 'Run an MCP server over stdio exposing the CAS as tools',
|
|
36
36
|
handler: ({ home }) => {
|
|
37
|
-
const c =
|
|
37
|
+
const c = fileCas(sha256)(home);
|
|
38
38
|
return casMcpServer(c, home, hash => join(home, toPath(hash))).step(() => pure(0));
|
|
39
39
|
},
|
|
40
40
|
},
|
package/fs/fjs/proof.f.js
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import { assert, assertEq } from "../asserts/module.f.js";
|
|
2
2
|
import { pure } from "../effects/module.f.js";
|
|
3
|
-
import { emptyState, virtual } from "../effects/node/virtual/module.f.js";
|
|
3
|
+
import { defaultNodeProgramOptions, emptyState, virtual } from "../effects/node/virtual/module.f.js";
|
|
4
4
|
import { main } from "./module.f.js";
|
|
5
|
-
const makeOptions = (args) => ({
|
|
6
|
-
args,
|
|
7
|
-
env: {},
|
|
8
|
-
home: '.',
|
|
9
|
-
std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
|
|
10
|
-
testContext: { test: async () => { } },
|
|
11
|
-
bunTestContext: { test: async () => { } },
|
|
12
|
-
playwrightTestContext: { test: async () => { } },
|
|
13
|
-
engine: 'node',
|
|
14
|
-
});
|
|
5
|
+
const makeOptions = (args) => ({ ...defaultNodeProgramOptions, args });
|
|
15
6
|
const run = (root) => (args) => virtual({ ...emptyState, root })(main(makeOptions(args)));
|
|
16
7
|
const appMain = ({ args }) => pure(args.length);
|
|
17
8
|
export const proof = {
|
|
@@ -95,4 +95,9 @@ export type JsTokenWithMetadata = {
|
|
|
95
95
|
type ErrorMessage = '" are missing' | 'unescaped character' | 'invalid hex value' | 'unexpected character' | 'invalid number' | 'invalid token' | '*\/ expected' | 'unterminated string literal' | 'eof';
|
|
96
96
|
export declare const isKeywordToken: (token: JsToken) => boolean;
|
|
97
97
|
export declare const tokenize: (input: List<number>) => (path: string) => List<JsTokenWithMetadata>;
|
|
98
|
+
export declare const proof: {
|
|
99
|
+
throw: {
|
|
100
|
+
unionConflict: () => void;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
98
103
|
export {};
|
|
@@ -27,6 +27,7 @@ leftSquareBracket, reverseSolidus, rightSquareBracket, lowLine,
|
|
|
27
27
|
latinSmallLetterRange, latinSmallLetterA, latinSmallLetterB, latinSmallLetterE, latinSmallLetterF, latinSmallLetterN, latinSmallLetterR, latinSmallLetterT, latinSmallLetterU,
|
|
28
28
|
//
|
|
29
29
|
leftCurlyBracket, rightCurlyBracket, dollarSign } from "../../text/ascii/module.f.js";
|
|
30
|
+
import { todo } from "../../asserts/module.f.js";
|
|
30
31
|
const { fromCharCode } = String;
|
|
31
32
|
const rangeOneNine = range('19');
|
|
32
33
|
const rangeSetNewLine = [
|
|
@@ -519,3 +520,15 @@ export const tokenize = input => path => {
|
|
|
519
520
|
const scan = scanTokenize({ state: { kind: 'initial' }, metadata: { path, line: 1, column: 1 } });
|
|
520
521
|
return flat(scan(flat([input /*satisfies List<CharCodeOrEof>*/, [null]])));
|
|
521
522
|
};
|
|
523
|
+
export const proof = {
|
|
524
|
+
throw: {
|
|
525
|
+
// union throws when two distinct non-default handlers are merged for the same range;
|
|
526
|
+
// this path is unreachable through the public API (no overlapping ranges in practice).
|
|
527
|
+
unionConflict: () => {
|
|
528
|
+
const def = (_) => todo;
|
|
529
|
+
const a = (_) => todo;
|
|
530
|
+
const b = (_) => todo;
|
|
531
|
+
union(def)(a)(b);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
};
|
package/fs/text/sgr/proof.f.js
CHANGED
|
@@ -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') {
|
|
@@ -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
|
-
*
|
|
159
|
+
* Converts a bit count to a byte count, rounding up — divides by `8`.
|
|
160
160
|
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
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
|
|
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
|
-
*
|
|
237
|
+
* Converts a bit count to a byte count, rounding up — divides by `8`.
|
|
238
238
|
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
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
|
|
243
|
-
const m = mask(e);
|
|
244
|
-
return v => (v + m) >> e;
|
|
245
|
-
};
|
|
243
|
+
export const divUp8 = divUp(8n);
|
|
246
244
|
/**
|
|
247
|
-
* Rounds a
|
|
245
|
+
* Rounds a bit count up to the nearest whole byte — the nearest multiple of `8`.
|
|
248
246
|
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
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 =
|
|
250
|
+
export const roundUp8 = roundUp(8n);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sum, abs, serialize, log2, bitLength, mask, combination, factorial, xor, multiple, product, divUp, roundUp,
|
|
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);
|