functionalscript 0.8.2 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/bnf/data/module.f.d.ts +10 -1
- package/bnf/data/module.f.js +58 -19
- package/bnf/data/test.f.d.ts +2 -0
- package/bnf/data/test.f.js +244 -3
- package/bnf/module.f.d.ts +6 -2
- package/bnf/module.f.js +8 -9
- package/cas/module.f.d.ts +18 -0
- package/cas/module.f.js +95 -0
- package/cas/test.f.d.ts +2 -0
- package/cas/test.f.js +1 -0
- package/ci/module.f.d.ts +3 -2
- package/ci/module.f.js +11 -9
- package/ci/module.js +3 -3
- package/crypto/sha2/module.f.js +0 -1
- package/dev/module.f.d.ts +1 -1
- package/dev/module.f.js +14 -6
- package/dev/version/module.f.d.ts +2 -11
- package/dev/version/module.f.js +17 -14
- package/dev/version/test.f.d.ts +3 -1
- package/dev/version/test.f.js +26 -10
- package/djs/module.f.d.ts +1 -1
- package/djs/module.f.js +4 -4
- package/djs/parser-new/module.f.d.ts +3 -0
- package/djs/parser-new/module.f.js +150 -0
- package/djs/parser-new/test.f.d.ts +5 -0
- package/djs/parser-new/test.f.js +201 -0
- package/djs/serializer/module.f.js +6 -6
- package/djs/transpiler/module.f.js +3 -2
- package/djs/transpiler/test.f.js +12 -11
- package/fjs/module.f.d.ts +2 -0
- package/fjs/module.f.js +25 -0
- package/{dev/tf → fjs}/module.js +1 -1
- package/fsc/module.f.js +1 -1
- package/io/module.d.ts +4 -0
- package/io/module.f.d.ts +14 -13
- package/io/module.f.js +21 -0
- package/io/module.js +7 -1
- package/io/virtual/module.f.d.ts +1 -1
- package/io/virtual/module.f.js +3 -3
- package/js/tokenizer/module.f.d.ts +1 -1
- package/js/tokenizer/module.f.js +0 -1
- package/json/module.f.js +3 -3
- package/nanvm-lib/tests/test.f.d.ts +1 -1
- package/nanvm-lib/tests/test.f.js +114 -104
- package/package.json +6 -7
- package/path/module.f.d.ts +1 -0
- package/path/module.f.js +6 -3
- package/text/utf16/module.f.js +1 -1
- package/types/bit_vec/module.f.d.ts +1 -0
- package/types/bit_vec/module.f.js +1 -0
- package/types/btree/find/module.f.d.ts +7 -8
- package/types/btree/set/module.f.js +21 -0
- package/types/cbase32/module.f.d.ts +6 -0
- package/types/cbase32/module.f.js +71 -0
- package/types/cbase32/test.f.d.ts +7 -0
- package/types/cbase32/test.f.js +74 -0
- package/types/effect/mock/module.f.d.ts +5 -0
- package/types/effect/mock/module.f.js +14 -0
- package/types/effect/module.d.ts +2 -0
- package/types/effect/module.f.d.ts +23 -0
- package/types/effect/module.f.js +14 -0
- package/types/effect/module.js +11 -0
- package/types/effect/node/module.f.d.ts +52 -0
- package/types/effect/node/module.f.js +7 -0
- package/types/effect/node/test.f.d.ts +27 -0
- package/types/effect/node/test.f.js +259 -0
- package/types/effect/node/virtual/module.f.d.ts +13 -0
- package/types/effect/node/virtual/module.f.js +98 -0
- package/types/function/module.f.d.ts +1 -1
- package/types/function/module.f.js +1 -1
- package/types/function/test.f.js +1 -1
- package/types/list/module.f.d.ts +1 -0
- package/types/list/module.f.js +6 -6
- package/types/nullable/module.f.d.ts +2 -0
- package/types/nullable/module.f.js +1 -0
- package/types/nullable/test.f.d.ts +1 -1
- package/types/nullable/test.f.js +23 -11
- package/types/option/module.f.d.ts +9 -0
- package/types/option/module.f.js +6 -0
- package/types/uint8array/module.f.d.ts +11 -0
- package/types/uint8array/module.f.js +21 -0
- package/types/uint8array/test.f.d.ts +12 -0
- package/types/uint8array/test.f.js +58 -0
- package/website/module.d.ts +1 -0
- package/website/module.f.d.ts +3 -0
- package/website/module.f.js +9 -0
- package/website/module.js +3 -0
- package/fsc/module.d.ts +0 -2
- package/fsc/module.js +0 -4
- /package/{dev/tf → fjs}/module.d.ts +0 -0
|
@@ -185,3 +185,4 @@ export declare const listToVec: ({ concat }: BitOrder) => (list: List<Vec>) => V
|
|
|
185
185
|
* Repeats a vector to create a padded block of the desired length.
|
|
186
186
|
*/
|
|
187
187
|
export declare const repeat: Fold<bigint, Vec>;
|
|
188
|
+
export declare const isVec: <T>(v: Vec | T) => v is Vec;
|
|
@@ -202,3 +202,4 @@ export const listToVec = ({ concat }) => fold(flip(concat))(empty);
|
|
|
202
202
|
* Repeats a vector to create a padded block of the desired length.
|
|
203
203
|
*/
|
|
204
204
|
export const repeat = mRepeat({ identity: empty, operation: lsb.concat });
|
|
205
|
+
export const isVec = (v) => typeof v === 'bigint';
|
|
@@ -2,13 +2,13 @@ import type { Leaf1, Leaf2, Branch3, Branch5, TNode } from '../types/module.f.ts
|
|
|
2
2
|
import type { List } from '../../list/module.f.ts';
|
|
3
3
|
import { type Compare } from '../../function/compare/module.f.ts';
|
|
4
4
|
import type { Index3, Index5 } from "../../array/module.f.ts";
|
|
5
|
-
type FirstLeaf1<T> = readonly [Index3, Leaf1<T>];
|
|
6
|
-
type FirstBranch3<T> = readonly [1, Branch3<T>];
|
|
7
|
-
type FirstLeaf2<T> = readonly [Index5, Leaf2<T>];
|
|
8
|
-
type FirstBranch5<T> = readonly [1 | 3, Branch5<T>];
|
|
9
|
-
type First<T> = FirstLeaf1<T> | FirstBranch3<T> | FirstLeaf2<T> | FirstBranch5<T>;
|
|
10
|
-
type PathItem3<T> = readonly [0 | 2, Branch3<T>];
|
|
11
|
-
type PathItem5<T> = readonly [0 | 2 | 4, Branch5<T>];
|
|
5
|
+
export type FirstLeaf1<T> = readonly [Index3, Leaf1<T>];
|
|
6
|
+
export type FirstBranch3<T> = readonly [1, Branch3<T>];
|
|
7
|
+
export type FirstLeaf2<T> = readonly [Index5, Leaf2<T>];
|
|
8
|
+
export type FirstBranch5<T> = readonly [1 | 3, Branch5<T>];
|
|
9
|
+
export type First<T> = FirstLeaf1<T> | FirstBranch3<T> | FirstLeaf2<T> | FirstBranch5<T>;
|
|
10
|
+
export type PathItem3<T> = readonly [0 | 2, Branch3<T>];
|
|
11
|
+
export type PathItem5<T> = readonly [0 | 2 | 4, Branch5<T>];
|
|
12
12
|
export type PathItem<T> = PathItem3<T> | PathItem5<T>;
|
|
13
13
|
export type Path<T> = List<PathItem<T>>;
|
|
14
14
|
export type Result<T> = {
|
|
@@ -18,4 +18,3 @@ export type Result<T> = {
|
|
|
18
18
|
export declare const find: <T>(c: Compare<T>) => (node: TNode<T>) => Result<T>;
|
|
19
19
|
export declare const isFound: <T>([i]: First<T>) => boolean;
|
|
20
20
|
export declare const value: <T>([i, r]: First<T>) => T | null;
|
|
21
|
-
export {};
|
|
@@ -30,7 +30,20 @@ const reduceOp = ([i, x]) => a => {
|
|
|
30
30
|
};
|
|
31
31
|
const reduceBranch = fold(reduceOp);
|
|
32
32
|
const nodeSet = (c) => (g) => (node) => {
|
|
33
|
+
// export type Result<T> = {
|
|
34
|
+
// readonly first: First<T>,
|
|
35
|
+
// readonly tail: Path<T>
|
|
36
|
+
//}
|
|
33
37
|
const { first, tail } = find(c)(node);
|
|
38
|
+
// export type Index2 = 0 | 1
|
|
39
|
+
// export type Index3 = Index2 | 2 // 0 | 1 | 2
|
|
40
|
+
// export type Index4 = Index3 | 3 // 0 | 1 | 2 | 3
|
|
41
|
+
// export type Index5 = Index4 | 4 // 0 | 1 | 2 | 3 | 4
|
|
42
|
+
// type FirstLeaf1<T> = readonly[Index3, Leaf1<T>]
|
|
43
|
+
// type FirstBranch3<T> = readonly[1, Branch3<T>]
|
|
44
|
+
// type FirstLeaf2<T> = readonly[Index5, Leaf2<T>]
|
|
45
|
+
// type FirstBranch5<T> = readonly[1|3, Branch5<T>]
|
|
46
|
+
// export type First<T> = FirstLeaf1<T> | FirstBranch3<T> | FirstLeaf2<T> | FirstBranch5<T>
|
|
34
47
|
const [i, x] = first;
|
|
35
48
|
const f = () => {
|
|
36
49
|
switch (i) {
|
|
@@ -66,6 +79,8 @@ const nodeSet = (c) => (g) => (node) => {
|
|
|
66
79
|
case 2: {
|
|
67
80
|
// insert
|
|
68
81
|
const value = g(null);
|
|
82
|
+
// TODO: remove after TSGO fix the regression.
|
|
83
|
+
const _xl = x.length;
|
|
69
84
|
switch (x.length) {
|
|
70
85
|
case 1: {
|
|
71
86
|
return [[x[0], value]];
|
|
@@ -74,9 +89,13 @@ const nodeSet = (c) => (g) => (node) => {
|
|
|
74
89
|
return [[x[0]], value, [x[1]]];
|
|
75
90
|
}
|
|
76
91
|
}
|
|
92
|
+
// TODO: remove after TSGO fix the regression.
|
|
93
|
+
throw 'unreachable';
|
|
77
94
|
}
|
|
78
95
|
case 3: {
|
|
79
96
|
// replace
|
|
97
|
+
// TODO: remove after TSGO fix the regression.
|
|
98
|
+
const _xl = x.length;
|
|
80
99
|
switch (x.length) {
|
|
81
100
|
case 2: {
|
|
82
101
|
return [[x[0], g(x[1])]];
|
|
@@ -85,6 +104,8 @@ const nodeSet = (c) => (g) => (node) => {
|
|
|
85
104
|
return [[x[0], x[1], x[2], g(x[3]), x[4]]];
|
|
86
105
|
}
|
|
87
106
|
}
|
|
107
|
+
// TODO: remove after TSGO fix the regression.
|
|
108
|
+
throw 'unreachable';
|
|
88
109
|
}
|
|
89
110
|
case 4: {
|
|
90
111
|
// insert
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Vec } from "../bit_vec/module.f.ts";
|
|
2
|
+
import type { Nullable } from "../nullable/module.f.ts";
|
|
3
|
+
export declare const vec5xToCBase32: (v: Vec) => string;
|
|
4
|
+
export declare const vecToCBase32: (v: Vec) => string;
|
|
5
|
+
export declare const cBase32ToVec5x: (s: string) => Nullable<Vec>;
|
|
6
|
+
export declare const cBase32ToVec: (s: string) => Nullable<Vec>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { msb, lsb, length, vec, empty } from "../bit_vec/module.f.js";
|
|
2
|
+
// 0123456789abcdef
|
|
3
|
+
const m = '0123456789abcdefghjkmnpqrstvwxyz';
|
|
4
|
+
const { popFront, concat } = msb;
|
|
5
|
+
const popBack1 = lsb.popFront(1n);
|
|
6
|
+
const popFront5 = popFront(5n);
|
|
7
|
+
export const vec5xToCBase32 = (v) => {
|
|
8
|
+
let result = '';
|
|
9
|
+
while (true) {
|
|
10
|
+
const len = length(v);
|
|
11
|
+
if (len === 0n) {
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
const [r, rest] = popFront5(v);
|
|
15
|
+
result += m[Number(r)];
|
|
16
|
+
v = rest;
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
};
|
|
20
|
+
export const vecToCBase32 = (v) => {
|
|
21
|
+
const len = length(v);
|
|
22
|
+
const extraLen = 5n - len % 5n;
|
|
23
|
+
const last = 1n << (extraLen - 1n);
|
|
24
|
+
const padded = concat(v)(vec(extraLen)(last));
|
|
25
|
+
return vec5xToCBase32(padded);
|
|
26
|
+
};
|
|
27
|
+
const vec5 = vec(5n);
|
|
28
|
+
const normalizeChar = (c) => {
|
|
29
|
+
const lower = c.toLowerCase();
|
|
30
|
+
switch (lower) {
|
|
31
|
+
case 'i': {
|
|
32
|
+
return '1';
|
|
33
|
+
}
|
|
34
|
+
case 'l': {
|
|
35
|
+
return '1';
|
|
36
|
+
}
|
|
37
|
+
case 'o': {
|
|
38
|
+
return '0';
|
|
39
|
+
}
|
|
40
|
+
default: {
|
|
41
|
+
return lower;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const toCrockfordIndex = (c) => m.indexOf(normalizeChar(c));
|
|
46
|
+
export const cBase32ToVec5x = (s) => {
|
|
47
|
+
let result = empty;
|
|
48
|
+
for (const c of s) {
|
|
49
|
+
const index = toCrockfordIndex(c);
|
|
50
|
+
if (index < 0) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const v = vec5(BigInt(index));
|
|
54
|
+
result = concat(result)(v);
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
export const cBase32ToVec = (s) => {
|
|
59
|
+
let v = cBase32ToVec5x(s);
|
|
60
|
+
if (v === null || v === empty) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
// TODO: replace with a function that computes trailing zeros.
|
|
64
|
+
while (true) {
|
|
65
|
+
const [last, v0] = popBack1(v);
|
|
66
|
+
v = v0;
|
|
67
|
+
if (last === 1n) {
|
|
68
|
+
return v;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { empty, vec } from "../bit_vec/module.f.js";
|
|
2
|
+
import { cBase32ToVec, cBase32ToVec5x, vec5xToCBase32, vecToCBase32 } from "./module.f.js";
|
|
3
|
+
const check5x = (s, v) => {
|
|
4
|
+
const sr = vec5xToCBase32(v);
|
|
5
|
+
if (sr !== s) {
|
|
6
|
+
throw [sr, s];
|
|
7
|
+
}
|
|
8
|
+
const vr = cBase32ToVec5x(s);
|
|
9
|
+
if (vr !== v) {
|
|
10
|
+
throw [vr, v];
|
|
11
|
+
}
|
|
12
|
+
//
|
|
13
|
+
check(`${s}g`, v);
|
|
14
|
+
};
|
|
15
|
+
const check = (s, v) => {
|
|
16
|
+
const sr = vecToCBase32(v);
|
|
17
|
+
if (sr !== s) {
|
|
18
|
+
throw [sr, s];
|
|
19
|
+
}
|
|
20
|
+
const vr = cBase32ToVec(s);
|
|
21
|
+
if (vr !== v) {
|
|
22
|
+
throw [vr, v];
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
export default {
|
|
26
|
+
roundtrip5x: () => {
|
|
27
|
+
check5x("", empty);
|
|
28
|
+
check5x("0", vec(5n)(0n));
|
|
29
|
+
check5x("1", vec(5n)(1n));
|
|
30
|
+
check5x("7", vec(5n)(7n));
|
|
31
|
+
check5x("a", vec(5n)(10n));
|
|
32
|
+
check5x("b", vec(5n)(11n));
|
|
33
|
+
check5x("f", vec(5n)(15n));
|
|
34
|
+
check5x("gh", vec(10n)(529n));
|
|
35
|
+
check5x("jk", vec(10n)(595n));
|
|
36
|
+
check5x("mnpq", vec(20n)(677591n));
|
|
37
|
+
check5x("rstvwxyz", vec(40n)(852378941407n));
|
|
38
|
+
},
|
|
39
|
+
roundtrip: () => {
|
|
40
|
+
check("g", empty);
|
|
41
|
+
check("8", vec(1n)(0n));
|
|
42
|
+
check("r", vec(1n)(1n));
|
|
43
|
+
check("4", vec(2n)(0n));
|
|
44
|
+
check("c", vec(2n)(1n));
|
|
45
|
+
check("2", vec(3n)(0n));
|
|
46
|
+
check("1", vec(4n)(0n));
|
|
47
|
+
check("2g", vec(5n)(2n));
|
|
48
|
+
check("01", vec(9n)(0n));
|
|
49
|
+
},
|
|
50
|
+
unalignedBits: () => {
|
|
51
|
+
const v = vec(1n)(1n);
|
|
52
|
+
const cr = vec5xToCBase32(v);
|
|
53
|
+
if (cr !== "g") {
|
|
54
|
+
throw ['g', cr];
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
caseInsensitive: () => {
|
|
58
|
+
if (cBase32ToVec5x("A") !== cBase32ToVec5x("a")) {
|
|
59
|
+
throw 'case-insensitive expected';
|
|
60
|
+
}
|
|
61
|
+
if (cBase32ToVec5x("I") !== cBase32ToVec5x("1")) {
|
|
62
|
+
throw 'i maps to 1';
|
|
63
|
+
}
|
|
64
|
+
if (cBase32ToVec5x("l") !== cBase32ToVec5x("1")) {
|
|
65
|
+
throw 'l maps to 1';
|
|
66
|
+
}
|
|
67
|
+
if (cBase32ToVec5x("o") !== cBase32ToVec5x("0")) {
|
|
68
|
+
throw 'o maps to 0';
|
|
69
|
+
}
|
|
70
|
+
if (cBase32ToVec5x("u") !== null) {
|
|
71
|
+
throw 'should error on invalid character';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Effect, Operations } from "../module.f.ts";
|
|
2
|
+
export type MemOperationMap<O extends Operations, S> = {
|
|
3
|
+
readonly [K in keyof O]: (state: S, payload: O[K][0]) => readonly [S, O[K][1]];
|
|
4
|
+
};
|
|
5
|
+
export declare const run: <O extends Operations, S>(o: MemOperationMap<O, S>) => (state: S) => <O1 extends O, T>(effect: Effect<O1, T>) => readonly [S, T];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const run = (o) => (state) => (effect) => {
|
|
2
|
+
let s = state;
|
|
3
|
+
let e = effect;
|
|
4
|
+
while (true) {
|
|
5
|
+
if ('pure' in e) {
|
|
6
|
+
return [s, e.pure];
|
|
7
|
+
}
|
|
8
|
+
const [cmd, payload, cont] = e.do;
|
|
9
|
+
const operation = o[cmd];
|
|
10
|
+
const [ns, m] = operation(s, payload);
|
|
11
|
+
s = ns;
|
|
12
|
+
e = cont(m);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type Operations = {
|
|
2
|
+
readonly [command in string]: readonly [input: unknown, output: unknown];
|
|
3
|
+
};
|
|
4
|
+
export type Effect<O extends Operations, T> = Pure<O, T> | Do<O, T>;
|
|
5
|
+
export type Map<O extends Operations, T> = {
|
|
6
|
+
readonly pipe: <O1 extends Operations, R>(f: (_: T) => Effect<O1, R>) => Effect<O | O1, R>;
|
|
7
|
+
readonly map: <O1 extends Operations, R>(f: (_: T) => R) => Effect<O | O1, R>;
|
|
8
|
+
};
|
|
9
|
+
export type Pure<O extends Operations, T> = {
|
|
10
|
+
readonly pure: T;
|
|
11
|
+
} & Map<O, T>;
|
|
12
|
+
export declare const pure: <O extends Operations, T>(value: T) => Pure<O, T>;
|
|
13
|
+
export type One<O extends Operations, T, K extends keyof O & string> = readonly [K, O[K][0], (input: O[K][1]) => Effect<O, T>];
|
|
14
|
+
export type Do<O extends Operations, T> = {
|
|
15
|
+
readonly do: {
|
|
16
|
+
readonly [K in keyof O & string]: One<O, T, K>;
|
|
17
|
+
}[keyof O & string];
|
|
18
|
+
} & Map<O, T>;
|
|
19
|
+
export declare const do_: <O extends Operations, K extends keyof O & string>(cmd: K, payload: O[K][0]) => Do<O, O[K][1]>;
|
|
20
|
+
export type ToAsyncOperationMap<O extends Operations> = {
|
|
21
|
+
readonly [K in keyof O]: (payload: O[K][0]) => Promise<O[K][1]>;
|
|
22
|
+
};
|
|
23
|
+
export declare const all: <O extends Operations, T>(set: readonly Effect<O, T>[]) => Effect<O, readonly T[]>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const pure = (value) => ({
|
|
2
|
+
pure: value,
|
|
3
|
+
pipe: e => e(value),
|
|
4
|
+
map: f => pure(f(value))
|
|
5
|
+
});
|
|
6
|
+
const doFull = (cmd, payload, cont) => ({
|
|
7
|
+
do: [cmd, payload, cont],
|
|
8
|
+
pipe: e => doFull(cmd, payload, x => cont(x).pipe(e)),
|
|
9
|
+
map: f => doFull(cmd, payload, x => cont(x).map(f))
|
|
10
|
+
});
|
|
11
|
+
export const do_ = (cmd, payload) => doFull(cmd, payload, pure);
|
|
12
|
+
const empty = pure([]);
|
|
13
|
+
// TODO: replace with either a `Do` operation or as an addition to `Pure` and `Do`.
|
|
14
|
+
export const all = (set) => set.reduce((previous, current) => previous.pipe(previousResult => current.map(currentResult => [...previousResult, currentResult])), empty);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const asyncRun = (map) => async (effect) => {
|
|
2
|
+
while (true) {
|
|
3
|
+
if ('pure' in effect) {
|
|
4
|
+
return effect.pure;
|
|
5
|
+
}
|
|
6
|
+
const [command, payload, continuation] = effect.do;
|
|
7
|
+
const operation = map[command];
|
|
8
|
+
const result = await operation(payload);
|
|
9
|
+
effect = continuation(result);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Vec } from '../../bit_vec/module.f.ts';
|
|
2
|
+
import type { Result } from '../../result/module.f.ts';
|
|
3
|
+
import { type Do, type Effect, type ToAsyncOperationMap } from '../module.f.ts';
|
|
4
|
+
export type IoResult<T> = Result<T, unknown>;
|
|
5
|
+
export type MakeDirectoryOptions = {
|
|
6
|
+
readonly recursive: true;
|
|
7
|
+
};
|
|
8
|
+
export type MkdirParam = readonly [string, MakeDirectoryOptions?];
|
|
9
|
+
export type Mkdir = {
|
|
10
|
+
readonly mkdir: readonly [MkdirParam, IoResult<void>];
|
|
11
|
+
};
|
|
12
|
+
export declare const mkdir: (...p: MkdirParam) => Do<Mkdir, IoResult<void>>;
|
|
13
|
+
export type ReadFile = {
|
|
14
|
+
readonly readFile: readonly [string, IoResult<Vec>];
|
|
15
|
+
};
|
|
16
|
+
export declare const readFile: (path: string) => Do<ReadFile, IoResult<Vec>>;
|
|
17
|
+
/**
|
|
18
|
+
* Represents a directory entry (file or directory) in the filesystem
|
|
19
|
+
* @see https://nodejs.org/api/fs.html#class-fsdirent
|
|
20
|
+
*/
|
|
21
|
+
export type Dirent = {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly parentPath: string;
|
|
24
|
+
readonly isFile: boolean;
|
|
25
|
+
};
|
|
26
|
+
export type ReaddirOptions = {
|
|
27
|
+
readonly recursive?: true;
|
|
28
|
+
};
|
|
29
|
+
export type ReaddirParam = readonly [string, ReaddirOptions];
|
|
30
|
+
export type Readdir = {
|
|
31
|
+
readonly readdir: readonly [ReaddirParam, IoResult<readonly Dirent[]>];
|
|
32
|
+
};
|
|
33
|
+
export declare const readdir: (...p: ReaddirParam) => Do<Readdir, IoResult<readonly Dirent[]>>;
|
|
34
|
+
export type WriteFileParam = readonly [string, Vec];
|
|
35
|
+
export type WriteFile = {
|
|
36
|
+
readonly writeFile: readonly [WriteFileParam, IoResult<void>];
|
|
37
|
+
};
|
|
38
|
+
export declare const writeFile: (...p: WriteFileParam) => Do<WriteFile, IoResult<void>>;
|
|
39
|
+
export type Fs = Mkdir & ReadFile & Readdir & WriteFile;
|
|
40
|
+
export type Error = {
|
|
41
|
+
readonly error: readonly [string, void];
|
|
42
|
+
};
|
|
43
|
+
export declare const error: (msg: string) => Do<Error, void>;
|
|
44
|
+
export type Log = {
|
|
45
|
+
readonly log: readonly [string, void];
|
|
46
|
+
};
|
|
47
|
+
export declare const log: (msg: string) => Do<Log, void>;
|
|
48
|
+
export type Console = Log & Error;
|
|
49
|
+
export type NodeOperations = Console & Fs;
|
|
50
|
+
export type NodeEffect<T> = Effect<NodeOperations, T>;
|
|
51
|
+
export type NodeOperationMap = ToAsyncOperationMap<NodeOperations>;
|
|
52
|
+
export type NodeProgram = (argv: readonly string[]) => NodeEffect<number>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { do_ } from "../module.f.js";
|
|
2
|
+
export const mkdir = (...p) => do_('mkdir', p);
|
|
3
|
+
export const readFile = (path) => do_('readFile', path);
|
|
4
|
+
export const readdir = (...p) => do_('readdir', p);
|
|
5
|
+
export const writeFile = (...p) => do_('writeFile', p);
|
|
6
|
+
export const error = (msg) => do_('error', msg);
|
|
7
|
+
export const log = (msg) => do_('log', msg);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
map: () => void;
|
|
3
|
+
mkdir: {
|
|
4
|
+
one: () => void;
|
|
5
|
+
rec: () => void;
|
|
6
|
+
nonRec: () => void;
|
|
7
|
+
};
|
|
8
|
+
readFile: {
|
|
9
|
+
one: () => void;
|
|
10
|
+
nested: () => void;
|
|
11
|
+
noSuchFile: () => void;
|
|
12
|
+
nestedPath: () => void;
|
|
13
|
+
};
|
|
14
|
+
readdir: {
|
|
15
|
+
one: () => void;
|
|
16
|
+
nonRecursive: () => void;
|
|
17
|
+
nested: () => void;
|
|
18
|
+
noSuchDir: () => void;
|
|
19
|
+
};
|
|
20
|
+
writeFile: {
|
|
21
|
+
one: () => void;
|
|
22
|
+
overwrite: () => void;
|
|
23
|
+
nestedPath: () => void;
|
|
24
|
+
directory: () => void;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export default _default;
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { empty, isVec, uint, vec8 } from "../../bit_vec/module.f.js";
|
|
2
|
+
import { run } from "../mock/module.f.js";
|
|
3
|
+
import { mkdir, readdir, readFile, writeFile } from "./module.f.js";
|
|
4
|
+
import { emptyState, virtual } from "./virtual/module.f.js";
|
|
5
|
+
export default {
|
|
6
|
+
map: () => {
|
|
7
|
+
let e = readFile('hello').map(([k, v]) => {
|
|
8
|
+
if (k === 'error') {
|
|
9
|
+
throw v;
|
|
10
|
+
}
|
|
11
|
+
return uint(v) * 2n;
|
|
12
|
+
});
|
|
13
|
+
//
|
|
14
|
+
while (true) {
|
|
15
|
+
if ('pure' in e) {
|
|
16
|
+
const result = e.pure;
|
|
17
|
+
if (result !== 0x2an) {
|
|
18
|
+
throw result;
|
|
19
|
+
}
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const [cmd, p, cont] = e.do;
|
|
23
|
+
if (cmd !== 'readFile') {
|
|
24
|
+
throw cmd;
|
|
25
|
+
}
|
|
26
|
+
if (p !== 'hello') {
|
|
27
|
+
throw p;
|
|
28
|
+
}
|
|
29
|
+
e = cont(['ok', vec8(0x15n)]);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
mkdir: {
|
|
33
|
+
one: () => {
|
|
34
|
+
const v = run(virtual);
|
|
35
|
+
const [state, [t, result]] = v(emptyState)(mkdir('a'));
|
|
36
|
+
if (t === 'error') {
|
|
37
|
+
throw result;
|
|
38
|
+
}
|
|
39
|
+
const a = state.root.a;
|
|
40
|
+
if (a === undefined || isVec(a)) {
|
|
41
|
+
throw a;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
rec: () => {
|
|
45
|
+
const [state, [t, result]] = run(virtual)(emptyState)(mkdir('tmp/cache', { recursive: true }));
|
|
46
|
+
if (t !== 'ok') {
|
|
47
|
+
throw result;
|
|
48
|
+
}
|
|
49
|
+
const tmp = state.root.tmp;
|
|
50
|
+
if (tmp === undefined || isVec(tmp)) {
|
|
51
|
+
throw state.root;
|
|
52
|
+
}
|
|
53
|
+
const cache = tmp.cache;
|
|
54
|
+
if (cache === undefined || isVec(cache)) {
|
|
55
|
+
throw tmp;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
nonRec: () => {
|
|
59
|
+
const [state, [t, result]] = run(virtual)(emptyState)(mkdir('tmp/cache'));
|
|
60
|
+
if (t !== 'error') {
|
|
61
|
+
throw result;
|
|
62
|
+
}
|
|
63
|
+
if (state.root.tmp !== undefined) {
|
|
64
|
+
throw state.root.tmp;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
readFile: {
|
|
69
|
+
one: () => {
|
|
70
|
+
const v = run(virtual);
|
|
71
|
+
const initial = {
|
|
72
|
+
...emptyState,
|
|
73
|
+
root: {
|
|
74
|
+
hello: vec8(0x2an),
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
const [state, [t, result]] = v(initial)(readFile('hello'));
|
|
78
|
+
if (t === 'error') {
|
|
79
|
+
throw result;
|
|
80
|
+
}
|
|
81
|
+
if (!isVec(result)) {
|
|
82
|
+
throw result;
|
|
83
|
+
}
|
|
84
|
+
if (uint(result) !== 0x2an) {
|
|
85
|
+
throw result;
|
|
86
|
+
}
|
|
87
|
+
if (state.root.hello === undefined) {
|
|
88
|
+
throw state.root;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
nested: () => {
|
|
92
|
+
const [_, [tag, result]] = run(virtual)({
|
|
93
|
+
...emptyState,
|
|
94
|
+
root: { tmp: { cache: vec8(0x15n) } }
|
|
95
|
+
})(readFile('tmp/cache'));
|
|
96
|
+
if (tag === 'error') {
|
|
97
|
+
throw result;
|
|
98
|
+
}
|
|
99
|
+
if (uint(result) !== 0x15n) {
|
|
100
|
+
throw result;
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
noSuchFile: () => {
|
|
104
|
+
const [_, [t, result]] = run(virtual)(emptyState)(readFile('hello'));
|
|
105
|
+
if (t !== 'error') {
|
|
106
|
+
throw result;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
nestedPath: () => {
|
|
110
|
+
const [_, [t, result]] = run(virtual)(emptyState)(readFile('tmp/cache'));
|
|
111
|
+
if (t !== 'error') {
|
|
112
|
+
throw result;
|
|
113
|
+
}
|
|
114
|
+
if (result !== 'no such file') {
|
|
115
|
+
throw result;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
readdir: {
|
|
120
|
+
one: () => {
|
|
121
|
+
const [_, [t, result]] = run(virtual)({
|
|
122
|
+
...emptyState,
|
|
123
|
+
root: {
|
|
124
|
+
file: vec8(0x2an),
|
|
125
|
+
dir: {
|
|
126
|
+
a: empty
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
})(readdir('', { recursive: true }));
|
|
130
|
+
if (t !== 'ok') {
|
|
131
|
+
throw result;
|
|
132
|
+
}
|
|
133
|
+
const file = result.find(x => x.name === 'file');
|
|
134
|
+
if (file === undefined || file.parentPath !== '' || !file.isFile) {
|
|
135
|
+
throw `file: ${file}`;
|
|
136
|
+
}
|
|
137
|
+
const dirA = result.find(x => x.name === 'a');
|
|
138
|
+
if (dirA === undefined || dirA.parentPath !== '/dir') {
|
|
139
|
+
throw `dirA: ${dirA?.parentPath}`;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
nonRecursive: () => {
|
|
143
|
+
const [_, [t, result]] = run(virtual)({
|
|
144
|
+
...emptyState,
|
|
145
|
+
root: {
|
|
146
|
+
file: vec8(0x2an),
|
|
147
|
+
dir: {
|
|
148
|
+
a: empty
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
})(readdir('', {}));
|
|
152
|
+
if (t !== 'ok') {
|
|
153
|
+
throw result;
|
|
154
|
+
}
|
|
155
|
+
if (result.length !== 2) {
|
|
156
|
+
throw result;
|
|
157
|
+
}
|
|
158
|
+
const file = result.find(x => x.name === 'file');
|
|
159
|
+
if (file === undefined) {
|
|
160
|
+
throw file;
|
|
161
|
+
}
|
|
162
|
+
const dir = result.find(x => x.name === 'dir');
|
|
163
|
+
if (dir === undefined) {
|
|
164
|
+
throw dir;
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
nested: () => {
|
|
168
|
+
const [_, [t, result]] = run(virtual)({
|
|
169
|
+
...emptyState,
|
|
170
|
+
root: { tmp: { cache: vec8(0x15n) } }
|
|
171
|
+
})(readdir('tmp', { recursive: true }));
|
|
172
|
+
if (t !== 'ok') {
|
|
173
|
+
throw result;
|
|
174
|
+
}
|
|
175
|
+
if (result.length !== 1) {
|
|
176
|
+
throw result;
|
|
177
|
+
}
|
|
178
|
+
const [r0] = result;
|
|
179
|
+
if (r0.name !== 'cache') {
|
|
180
|
+
throw r0;
|
|
181
|
+
}
|
|
182
|
+
if (r0.parentPath !== 'tmp') {
|
|
183
|
+
throw r0;
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
noSuchDir: () => {
|
|
187
|
+
const [_, [t, result]] = run(virtual)(emptyState)(readdir('tmp', { recursive: true }));
|
|
188
|
+
if (t !== 'error') {
|
|
189
|
+
throw result;
|
|
190
|
+
}
|
|
191
|
+
if (result !== 'invalid path') {
|
|
192
|
+
throw result;
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
writeFile: {
|
|
197
|
+
one: () => {
|
|
198
|
+
const [state, [t, result]] = run(virtual)(emptyState)(writeFile('hello', vec8(0x2an)));
|
|
199
|
+
if (t !== 'ok') {
|
|
200
|
+
throw result;
|
|
201
|
+
}
|
|
202
|
+
const file = state.root.hello;
|
|
203
|
+
if (!isVec(file)) {
|
|
204
|
+
throw file;
|
|
205
|
+
}
|
|
206
|
+
if (uint(file) !== 0x2an) {
|
|
207
|
+
throw file;
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
overwrite: () => {
|
|
211
|
+
const [state, [t, result]] = run(virtual)({
|
|
212
|
+
...emptyState,
|
|
213
|
+
root: {
|
|
214
|
+
hello: vec8(0x15n),
|
|
215
|
+
},
|
|
216
|
+
})(writeFile('hello', vec8(0x2an)));
|
|
217
|
+
if (t !== 'ok') {
|
|
218
|
+
throw result;
|
|
219
|
+
}
|
|
220
|
+
const file = state.root.hello;
|
|
221
|
+
if (!isVec(file)) {
|
|
222
|
+
throw file;
|
|
223
|
+
}
|
|
224
|
+
if (uint(file) !== 0x2an) {
|
|
225
|
+
throw file;
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
nestedPath: () => {
|
|
229
|
+
const [state, [t, result]] = run(virtual)(emptyState)(writeFile('tmp/cache', vec8(0x2an)));
|
|
230
|
+
if (t !== 'error') {
|
|
231
|
+
throw result;
|
|
232
|
+
}
|
|
233
|
+
if (result !== 'invalid file') {
|
|
234
|
+
throw result;
|
|
235
|
+
}
|
|
236
|
+
if (state.root.tmp !== undefined) {
|
|
237
|
+
throw state.root;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
directory: () => {
|
|
241
|
+
const [state, [t, result]] = run(virtual)({
|
|
242
|
+
...emptyState,
|
|
243
|
+
root: {
|
|
244
|
+
tmp: {},
|
|
245
|
+
},
|
|
246
|
+
})(writeFile('tmp', vec8(0x2an)));
|
|
247
|
+
if (t !== 'error') {
|
|
248
|
+
throw result;
|
|
249
|
+
}
|
|
250
|
+
if (result !== 'invalid file') {
|
|
251
|
+
throw result;
|
|
252
|
+
}
|
|
253
|
+
const tmp = state.root.tmp;
|
|
254
|
+
if (tmp === undefined || isVec(tmp)) {
|
|
255
|
+
throw tmp;
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
};
|