functionalscript 0.9.1 → 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.
Files changed (53) hide show
  1. package/README.md +3 -3
  2. package/bnf/module.f.d.ts +6 -2
  3. package/bnf/module.f.js +8 -9
  4. package/cas/module.f.d.ts +14 -13
  5. package/cas/module.f.js +78 -60
  6. package/ci/module.f.d.ts +3 -2
  7. package/ci/module.f.js +6 -6
  8. package/ci/module.js +3 -3
  9. package/dev/module.f.d.ts +1 -1
  10. package/dev/module.f.js +13 -6
  11. package/dev/version/module.f.d.ts +2 -11
  12. package/dev/version/module.f.js +17 -15
  13. package/dev/version/test.f.d.ts +3 -1
  14. package/dev/version/test.f.js +26 -11
  15. package/djs/parser-new/module.f.d.ts +3 -0
  16. package/djs/parser-new/module.f.js +150 -0
  17. package/djs/parser-new/test.f.d.ts +5 -0
  18. package/djs/parser-new/test.f.js +201 -0
  19. package/djs/serializer/module.f.js +6 -6
  20. package/fjs/module.f.d.ts +1 -1
  21. package/fjs/module.f.js +3 -2
  22. package/fsc/module.f.js +1 -1
  23. package/io/module.d.ts +4 -0
  24. package/io/module.f.d.ts +10 -4
  25. package/io/module.f.js +21 -0
  26. package/io/module.js +7 -1
  27. package/json/module.f.js +3 -3
  28. package/package.json +3 -2
  29. package/path/module.f.d.ts +1 -0
  30. package/path/module.f.js +6 -3
  31. package/text/utf16/module.f.js +1 -1
  32. package/types/bit_vec/module.f.d.ts +1 -0
  33. package/types/bit_vec/module.f.js +1 -0
  34. package/types/effect/mock/module.f.d.ts +5 -0
  35. package/types/effect/mock/module.f.js +14 -0
  36. package/types/effect/module.d.ts +2 -0
  37. package/types/effect/module.f.d.ts +23 -0
  38. package/types/effect/module.f.js +14 -0
  39. package/types/effect/module.js +11 -0
  40. package/types/effect/node/module.f.d.ts +52 -0
  41. package/types/effect/node/module.f.js +7 -0
  42. package/types/effect/node/test.f.d.ts +27 -0
  43. package/types/effect/node/test.f.js +259 -0
  44. package/types/effect/node/virtual/module.f.d.ts +13 -0
  45. package/types/effect/node/virtual/module.f.js +98 -0
  46. package/types/function/module.f.d.ts +1 -1
  47. package/types/function/module.f.js +1 -1
  48. package/types/function/test.f.js +1 -1
  49. package/types/list/module.f.js +4 -4
  50. package/website/module.d.ts +1 -0
  51. package/website/module.f.d.ts +3 -0
  52. package/website/module.f.js +9 -0
  53. package/website/module.js +3 -0
@@ -0,0 +1,201 @@
1
+ import { descentParser } from "../../bnf/data/module.f.js";
2
+ import { stringToCodePointList } from "../../text/utf16/module.f.js";
3
+ import { map, toArray } from "../../types/list/module.f.js";
4
+ import { jsGrammar } from "./module.f.js";
5
+ const mapCodePoint = (cp) => [cp, undefined];
6
+ const descentParserCpOnly = (m, name, cp) => {
7
+ const cpm = toArray(map(mapCodePoint)(cp));
8
+ return m(name, cpm);
9
+ };
10
+ export default {
11
+ isValid: [() => {
12
+ const m = descentParser(jsGrammar());
13
+ const expect = (s, expected) => {
14
+ const cp = toArray(stringToCodePointList(s));
15
+ const mr = descentParserCpOnly(m, '', cp);
16
+ const success = mr[1] && mr[2] === cp.length;
17
+ if (success !== expected) {
18
+ throw mr;
19
+ }
20
+ };
21
+ expect(' true ', true);
22
+ expect(' tr2ue ', true);
23
+ expect(' 2true ', true);
24
+ expect(' true" ', false);
25
+ expect(' "Hello" ', true);
26
+ expect(' "Hello ', false);
27
+ expect(' "Hello\\n\\r\\"" ', true);
28
+ expect(' 56.7e+5 ', true);
29
+ expect(' -56.7e+5 ', true);
30
+ expect(' h-56.7e+5 ', true);
31
+ expect(' -56.7e+5 3', true);
32
+ expect(' [] ', true);
33
+ expect(' {} ', true);
34
+ expect(' [[[]]] ', true);
35
+ expect(' [1] ', true);
36
+ expect(' [ 12, false, "a"] ', true);
37
+ expect(' [ 12, false2, "a"] ', true);
38
+ expect(' { "q": [ 12, false, [{"b" : "c"}], "a"] } ', true);
39
+ expect(' { "q": [ 12, false, [{}], "a"] } ', true);
40
+ expect(' { "q": [ 12, false, [}], "a"] } ', true);
41
+ expect(' [{ "q": [ 12, false, [{}], "a"] }] ', true);
42
+ expect(' [{ "q": [ 12, false, [}], "a"] }] ', true);
43
+ expect('. + ++ +=', true);
44
+ expect('//12\n', true);
45
+ expect('/*12*/', true);
46
+ expect('/* 1*2 */', true);
47
+ }
48
+ ],
49
+ parser: [
50
+ () => {
51
+ const m = descentParser(jsGrammar());
52
+ const cp = toArray(stringToCodePointList('tr'));
53
+ const mr = descentParserCpOnly(m, '', cp);
54
+ const seq = mr[0].sequence[0];
55
+ if (seq instanceof Array)
56
+ throw JSON.stringify(mr);
57
+ if (seq.tag !== 'id')
58
+ throw JSON.stringify(mr);
59
+ },
60
+ () => {
61
+ const m = descentParser(jsGrammar());
62
+ const cp = toArray(stringToCodePointList('"tr"'));
63
+ const mr = descentParserCpOnly(m, '', cp);
64
+ const seq = mr[0].sequence[0];
65
+ if (seq instanceof Array)
66
+ throw JSON.stringify(mr);
67
+ if (seq.tag !== 'string')
68
+ throw JSON.stringify(mr);
69
+ },
70
+ () => {
71
+ const m = descentParser(jsGrammar());
72
+ const cp = toArray(stringToCodePointList('56.7e+5'));
73
+ const mr = descentParserCpOnly(m, '', cp);
74
+ const seq = mr[0].sequence[0];
75
+ if (seq instanceof Array)
76
+ throw JSON.stringify(mr);
77
+ if (seq.tag !== 'number')
78
+ throw JSON.stringify(mr);
79
+ },
80
+ () => {
81
+ const m = descentParser(jsGrammar());
82
+ const cp = toArray(stringToCodePointList('56n'));
83
+ const mr = descentParserCpOnly(m, '', cp);
84
+ const seq = mr[0].sequence[0];
85
+ if (seq instanceof Array)
86
+ throw JSON.stringify(mr);
87
+ if (seq.tag !== 'number')
88
+ throw JSON.stringify(mr);
89
+ },
90
+ () => {
91
+ const m = descentParser(jsGrammar());
92
+ const cp = toArray(stringToCodePointList('*'));
93
+ const mr = descentParserCpOnly(m, '', cp);
94
+ const seq = mr[0].sequence[0];
95
+ if (seq instanceof Array)
96
+ throw JSON.stringify(mr);
97
+ if (seq.tag !== '*')
98
+ throw JSON.stringify(mr);
99
+ },
100
+ () => {
101
+ const m = descentParser(jsGrammar());
102
+ const cp = toArray(stringToCodePointList('**'));
103
+ const mr = descentParserCpOnly(m, '', cp);
104
+ const seq = mr[0].sequence[0];
105
+ if (seq instanceof Array)
106
+ throw JSON.stringify(mr);
107
+ if (seq.tag !== '**')
108
+ throw JSON.stringify(mr);
109
+ },
110
+ () => {
111
+ const m = descentParser(jsGrammar());
112
+ const cp = toArray(stringToCodePointList('=>'));
113
+ const mr = descentParserCpOnly(m, '', cp);
114
+ const seq = mr[0].sequence[0];
115
+ if (seq instanceof Array)
116
+ throw JSON.stringify(mr);
117
+ if (seq.tag !== '=>')
118
+ throw JSON.stringify(mr);
119
+ },
120
+ () => {
121
+ const m = descentParser(jsGrammar());
122
+ const cp = toArray(stringToCodePointList('=='));
123
+ const mr = descentParserCpOnly(m, '', cp);
124
+ const seq = mr[0].sequence[0];
125
+ if (seq instanceof Array)
126
+ throw JSON.stringify(mr);
127
+ if (seq.tag !== '==')
128
+ throw JSON.stringify(mr);
129
+ },
130
+ () => {
131
+ const m = descentParser(jsGrammar());
132
+ const cp = toArray(stringToCodePointList('==='));
133
+ const mr = descentParserCpOnly(m, '', cp);
134
+ const seq = mr[0].sequence[0];
135
+ if (seq instanceof Array)
136
+ throw JSON.stringify(mr);
137
+ if (seq.tag !== '===')
138
+ throw JSON.stringify(mr);
139
+ },
140
+ () => {
141
+ const m = descentParser(jsGrammar());
142
+ const cp = toArray(stringToCodePointList('='));
143
+ const mr = descentParserCpOnly(m, '', cp);
144
+ const seq = mr[0].sequence[0];
145
+ if (seq instanceof Array)
146
+ throw JSON.stringify(mr);
147
+ if (seq.tag !== '=')
148
+ throw JSON.stringify(mr);
149
+ },
150
+ () => {
151
+ const m = descentParser(jsGrammar());
152
+ const cp = toArray(stringToCodePointList(' '));
153
+ const mr = descentParserCpOnly(m, '', cp);
154
+ const seq = mr[0].sequence[0];
155
+ if (seq instanceof Array)
156
+ throw JSON.stringify(mr);
157
+ if (seq.tag !== ' ')
158
+ throw JSON.stringify(mr);
159
+ },
160
+ () => {
161
+ const m = descentParser(jsGrammar());
162
+ const cp = toArray(stringToCodePointList('\n'));
163
+ const mr = descentParserCpOnly(m, '', cp);
164
+ const seq = mr[0].sequence[0];
165
+ if (seq instanceof Array)
166
+ throw JSON.stringify(mr);
167
+ if (seq.tag !== '\n')
168
+ throw JSON.stringify(mr);
169
+ },
170
+ () => {
171
+ const m = descentParser(jsGrammar());
172
+ const cp = toArray(stringToCodePointList('/\n'));
173
+ const mr = descentParserCpOnly(m, '', cp);
174
+ const seq = mr[0].sequence[0];
175
+ if (seq instanceof Array)
176
+ throw JSON.stringify(mr);
177
+ if (seq.tag !== '/')
178
+ throw JSON.stringify(mr);
179
+ },
180
+ () => {
181
+ const m = descentParser(jsGrammar());
182
+ const cp = toArray(stringToCodePointList('//\n'));
183
+ const mr = descentParserCpOnly(m, '', cp);
184
+ const seq = mr[0].sequence[0];
185
+ if (seq instanceof Array)
186
+ throw JSON.stringify(mr);
187
+ if (seq.tag !== 'comment')
188
+ throw JSON.stringify(mr);
189
+ },
190
+ () => {
191
+ const m = descentParser(jsGrammar());
192
+ const cp = toArray(stringToCodePointList('/*1*/'));
193
+ const mr = descentParserCpOnly(m, '', cp);
194
+ const seq = mr[0].sequence[0];
195
+ if (seq instanceof Array)
196
+ throw JSON.stringify(mr);
197
+ if (seq.tag !== 'comment')
198
+ throw JSON.stringify(mr);
199
+ }
200
+ ]
201
+ };
@@ -53,9 +53,9 @@ export const serializeWithoutConst = sort => {
53
53
  ]);
54
54
  const mapPropertySerialize = map(propertySerialize);
55
55
  const objectSerialize = fn(entries)
56
- .then(sort)
57
- .then(mapPropertySerialize)
58
- .then(objectWrap)
56
+ .map(sort)
57
+ .map(mapPropertySerialize)
58
+ .map(objectWrap)
59
59
  .result;
60
60
  const f = value => {
61
61
  switch (typeof value) {
@@ -96,9 +96,9 @@ const serializeWithConst = sort => refs => root => {
96
96
  ]);
97
97
  const mapPropertySerialize = map(propertySerialize);
98
98
  const objectSerialize = fn(entries)
99
- .then(sort)
100
- .then(mapPropertySerialize)
101
- .then(objectWrap)
99
+ .map(sort)
100
+ .map(mapPropertySerialize)
101
+ .map(objectWrap)
102
102
  .result;
103
103
  const f = value => {
104
104
  if (value !== root) {
package/fjs/module.f.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import type { Io } from '../io/module.f.ts';
1
+ import { type Io } from '../io/module.f.ts';
2
2
  export declare const main: (io: Io) => Promise<number>;
package/fjs/module.f.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { fromIo } from "../io/module.f.js";
1
2
  import { compile } from "../djs/module.f.js";
2
3
  import { main as testMain } from "../dev/tf/module.f.js";
4
+ import { main as casMain } from "../cas/module.f.js";
3
5
  export const main = (io) => {
4
6
  const { error } = io.console;
5
7
  const [command, ...rest] = io.process.argv.slice(2);
@@ -12,8 +14,7 @@ export const main = (io) => {
12
14
  return compile(io)(rest);
13
15
  case 'cas':
14
16
  case 's':
15
- error('cas command is not implemented yet');
16
- return Promise.resolve(1);
17
+ return fromIo(io)(casMain(rest));
17
18
  case undefined:
18
19
  error('Error: command is required');
19
20
  return Promise.resolve(1);
package/fsc/module.f.js CHANGED
@@ -26,7 +26,7 @@ const reduce = (a) => {
26
26
  return toArray(listReduce(merge)(empty)(a));
27
27
  };
28
28
  const codePointRange = fromRange(def);
29
- const range = fn(asciiRange).then(codePointRange).result;
29
+ const range = fn(asciiRange).map(codePointRange).result;
30
30
  const rangeSet = (l) => (f) => {
31
31
  const codePointRange = fromRange(def);
32
32
  const g = r => codePointRange(asciiRange(r))(f);
package/io/module.d.ts CHANGED
@@ -1,4 +1,8 @@
1
1
  import { type Io, type Run } from './module.f.ts';
2
+ import type { NodeProgram } from '../types/effect/node/module.f.ts';
2
3
  export declare const io: Io;
3
4
  declare const runDefault: Run;
4
5
  export default runDefault;
6
+ export type NodeRun = (p: NodeProgram) => Promise<number>;
7
+ export declare const ioRun: (io: Io) => NodeRun;
8
+ export declare const nodeRun: NodeRun;
package/io/module.f.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import type { Result } from '../types/result/module.f.ts';
1
+ import type { NodeEffect } from '../types/effect/node/module.f.ts';
2
+ import { type Result } from '../types/result/module.f.ts';
2
3
  /**
3
4
  * Represents a directory entry (file or directory) in the filesystem
4
5
  * @see https://nodejs.org/api/fs.html#class-fsdirent
5
6
  */
6
7
  export type Dirent = {
7
8
  readonly name: string;
9
+ readonly parentPath: string;
8
10
  readonly isDirectory: () => boolean;
9
11
  readonly isFile: () => boolean;
10
12
  };
@@ -15,6 +17,11 @@ export type RmOptions = {
15
17
  export type MakeDirectoryOptions = {
16
18
  readonly recursive?: boolean;
17
19
  };
20
+ export type ReadDir = ((path: string, options: {
21
+ withFileTypes: true;
22
+ }) => Promise<Dirent[]>) & ((path: string, options: {
23
+ recursive?: true;
24
+ }) => Promise<readonly string[]>);
18
25
  /**
19
26
  * File system operations interface
20
27
  * @see https://nodejs.org/api/fs.html
@@ -27,9 +34,7 @@ export type Fs = {
27
34
  readonly promises: {
28
35
  readonly readFile: (path: string) => Promise<Uint8Array>;
29
36
  readonly writeFile: (path: string, data: Uint8Array) => Promise<void>;
30
- readonly readdir: (path: string, options: {
31
- withFileTypes: true;
32
- }) => Promise<Dirent[]>;
37
+ readonly readdir: ReadDir;
33
38
  readonly rm: (path: string, options?: RmOptions) => Promise<void>;
34
39
  readonly mkdir: (path: string, options?: MakeDirectoryOptions) => Promise<string | undefined>;
35
40
  readonly copyFile: (src: string, dest: string) => Promise<void>;
@@ -99,3 +104,4 @@ export type Run = (f: App) => Promise<never>;
99
104
  * Handles errors by exiting with code 1
100
105
  */
101
106
  export declare const run: (io: Io) => Run;
107
+ export declare const fromIo: ({ console: { error, log }, fs: { promises: { mkdir, readFile, readdir, writeFile } }, }: Io) => <T>(effect: NodeEffect<T>) => Promise<T>;
package/io/module.f.js CHANGED
@@ -1,3 +1,7 @@
1
+ import { normalize } from "../path/module.f.js";
2
+ import { asyncRun } from "../types/effect/module.js";
3
+ import { error, ok } from "../types/result/module.f.js";
4
+ import { fromVec, toVec } from "../types/uint8array/module.f.js";
1
5
  /**
2
6
  * Runs a function and exits the process with the returned code
3
7
  * Handles errors by exiting with code 1
@@ -14,3 +18,20 @@ export const run = (io) => {
14
18
  };
15
19
  return async (f) => io.process.exit(code(await io.asyncTryCatch(() => f(io))));
16
20
  };
21
+ const tc = async (f) => {
22
+ try {
23
+ return ok(await f());
24
+ }
25
+ catch (e) {
26
+ return error(e);
27
+ }
28
+ };
29
+ export const fromIo = ({ console: { error, log }, fs: { promises: { mkdir, readFile, readdir, writeFile } }, }) => asyncRun({
30
+ error: async (message) => error(message),
31
+ log: async (message) => log(message),
32
+ mkdir: param => tc(async () => { await mkdir(...param); }),
33
+ readFile: path => tc(async () => toVec(await readFile(path))),
34
+ readdir: ([path, r]) => tc(async () => (await readdir(path, { ...r, withFileTypes: true }))
35
+ .map(v => ({ name: v.name, parentPath: normalize(v.parentPath), isFile: v.isFile() }))),
36
+ writeFile: ([path, data]) => tc(() => writeFile(path, fromVec(data))),
37
+ });
package/io/module.js CHANGED
@@ -6,7 +6,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
6
6
  }
7
7
  return path;
8
8
  };
9
- import { run } from "./module.f.js";
9
+ import { fromIo, run } from "./module.f.js";
10
10
  import fs from 'node:fs';
11
11
  import process from "node:process";
12
12
  import { concat } from "../path/module.f.js";
@@ -41,3 +41,9 @@ export const io = {
41
41
  };
42
42
  const runDefault = run(io);
43
43
  export default runDefault;
44
+ export const ioRun = (io) => {
45
+ const r = fromIo(io);
46
+ const { argv } = io.process;
47
+ return p => r(p(argv));
48
+ };
49
+ export const nodeRun = ioRun(io);
package/json/module.f.js CHANGED
@@ -25,9 +25,9 @@ export const serialize = sort => {
25
25
  ]);
26
26
  const mapPropertySerialize = map(propertySerialize);
27
27
  const objectSerialize = fn(entries)
28
- .then(sort)
29
- .then(mapPropertySerialize)
30
- .then(objectWrap)
28
+ .map(sort)
29
+ .map(mapPropertySerialize)
30
+ .map(objectWrap)
31
31
  .result;
32
32
  const f = value => {
33
33
  switch (typeof value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "**/*.js",
@@ -15,7 +15,8 @@
15
15
  "fst": "node ./fjs/module.ts t",
16
16
  "fjs": "node ./fjs/module.ts",
17
17
  "ci-update": "node ./ci/module.ts",
18
- "update": "git clean -fdx && npm install && npm run index && npm run ci-update"
18
+ "update": "git clean -fdx && npm install && npm run index && npm run ci-update",
19
+ "website": "node --experimental-strip-types ./website/module.ts"
19
20
  },
20
21
  "engines": {
21
22
  "node": ">=20"
@@ -1,3 +1,4 @@
1
1
  import type { Reduce, Unary } from "../types/function/operator/module.f.ts";
2
+ export declare const parse: (path: string) => readonly string[];
2
3
  export declare const normalize: Unary<string, string>;
3
4
  export declare const concat: Reduce<string>;
package/path/module.f.js CHANGED
@@ -1,4 +1,4 @@
1
- import { fold, last, take, length, concat as listConcat } from "../types/list/module.f.js";
1
+ import { fold, last, take, length, concat as listConcat, toArray } from "../types/list/module.f.js";
2
2
  import { join } from "../types/string/module.f.js";
3
3
  import { concat as stringConcat } from "../types/string/module.f.js";
4
4
  const foldNormalizeOp = input => state => {
@@ -21,9 +21,12 @@ const foldNormalizeOp = input => state => {
21
21
  }
22
22
  }
23
23
  };
24
- export const normalize = path => {
24
+ export const parse = (path) => {
25
25
  const split = path.replaceAll('\\', '/').split('/');
26
- const foldResult = fold(foldNormalizeOp)([])(split);
26
+ return toArray(fold(foldNormalizeOp)([])(split));
27
+ };
28
+ export const normalize = path => {
29
+ const foldResult = parse(path);
27
30
  return join('/')(foldResult);
28
31
  };
29
32
  export const concat = a => b => {
@@ -332,7 +332,7 @@ export const stringToCodePointList = (input) => toCodePointList(stringToList(inp
332
332
  * ```
333
333
  */
334
334
  export const listToString = fn(map(String.fromCharCode))
335
- .then(reduce(concat)(''))
335
+ .map(reduce(concat)(''))
336
336
  .result;
337
337
  /**
338
338
  * Converts a list of Unicode code points (CodePoint) to a string.
@@ -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';
@@ -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,2 @@
1
+ import type { Effect, Operations, ToAsyncOperationMap } from "./module.f.ts";
2
+ export declare const asyncRun: <O extends Operations>(map: ToAsyncOperationMap<O>) => <T, E extends Effect<O, T>>(effect: Effect<O, T>) => Promise<T>;
@@ -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;