functionalscript 0.0.156 → 0.0.163
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/array/index.js +55 -1
- package/async/{index.js → iterable/index.js} +26 -11
- package/async/{test.js → iterable/test.js} +0 -0
- package/btree/index.js +34 -23
- package/dev/index.js +4 -0
- package/func/index.js +12 -0
- package/index.js +0 -6
- package/iterable/index.js +19 -16
- package/iterable/test.js +14 -14
- package/map/index.js +3 -3
- package/map/test.js +4 -6
- package/map-reduce/index.js +13 -7
- package/module-manager/index.js +41 -29
- package/module-manager/node/test.js +0 -1
- package/module-manager/test.js +22 -19
- package/option/index.js +12 -0
- package/package.json +1 -1
- package/test.js +3 -5
- package/lib/index.js +0 -124
- package/lib/test.js +0 -5
package/array/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
const option = require('../option')
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template T
|
|
5
|
+
* @typedef {readonly T[]} Array
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
/**
|
|
2
9
|
* @template T
|
|
3
10
|
* @typedef {readonly [T]} Array1
|
|
@@ -33,4 +40,51 @@
|
|
|
33
40
|
|
|
34
41
|
/** @typedef {0|1|2|3|4} Index5 */
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
/** @type {<T>(_: Array<T>) => Array<T>} */
|
|
44
|
+
const uncheckTail = a => a.slice(1)
|
|
45
|
+
|
|
46
|
+
/** @type {<T>(_: Array<T>) => Array<T>} */
|
|
47
|
+
const uncheckHead = a => a.slice(0, -1)
|
|
48
|
+
|
|
49
|
+
/** @type {<T>(_: Array<T>) => T|undefined} */
|
|
50
|
+
const first = a => a[0]
|
|
51
|
+
|
|
52
|
+
/** @type {<T>(_: Array<T>) => T|undefined} */
|
|
53
|
+
const last = a => a[a.length - 1]
|
|
54
|
+
|
|
55
|
+
/** @type {<T>(_: Array<T>) => Array<T>|undefined} */
|
|
56
|
+
const tail = a => a.length === 0 ? undefined : uncheckTail(a)
|
|
57
|
+
|
|
58
|
+
/** @type {<T>(_: Array<T>) => readonly [T, Array<T>]|undefined} */
|
|
59
|
+
const splitFirst = a => {
|
|
60
|
+
/** @typedef {typeof a[0]} T*/
|
|
61
|
+
/** @type {(_: T) => readonly [T, Array<T>]} */
|
|
62
|
+
const split = first => [first, uncheckTail(a)]
|
|
63
|
+
return option.map(split)(a[0])
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @type {<T>(_: Array<T>) => Array<T>|undefined} */
|
|
67
|
+
const head = a => a.length === 0 ? undefined : uncheckHead(a)
|
|
68
|
+
|
|
69
|
+
/** @type {<T>(_: Array<T>) => readonly [Array<T>, T]|undefined} */
|
|
70
|
+
const splitLast = a => {
|
|
71
|
+
/** @typedef {typeof a[0]} T*/
|
|
72
|
+
/** @type {(_: T) => readonly [Array<T>, T]} */
|
|
73
|
+
const split = x => [uncheckHead(a), x]
|
|
74
|
+
return option.map(split)(last(a))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
/** @readnly */
|
|
79
|
+
first,
|
|
80
|
+
/** @readonly */
|
|
81
|
+
last,
|
|
82
|
+
/** @readonly */
|
|
83
|
+
head,
|
|
84
|
+
/** @readonly */
|
|
85
|
+
tail,
|
|
86
|
+
/** @readonly */
|
|
87
|
+
splitFirst,
|
|
88
|
+
/** @readonly */
|
|
89
|
+
splitLast,
|
|
90
|
+
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { todo } = require('../../dev')
|
|
2
|
+
const { pipe } = require('../../func')
|
|
3
|
+
const mapReduce = require('../../map-reduce')
|
|
2
4
|
|
|
3
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* @template T
|
|
7
|
+
* @typedef {Promise<T>|T} PromiseOrValue
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** @type {<T, R>(f: (value: T) => PromiseOrValue<R>) => (c: AsyncIterable<T>) => AsyncIterable<R>} */
|
|
4
11
|
const map = f => c => ({
|
|
5
12
|
async *[Symbol.asyncIterator]() {
|
|
6
13
|
for await (const i of c) {
|
|
@@ -30,24 +37,24 @@ const filter = f => c => ({
|
|
|
30
37
|
})
|
|
31
38
|
|
|
32
39
|
/** @type {<T, R>(f: (value: T) => AsyncIterable<R>) => (c: AsyncIterable<T>) => AsyncIterable<R>} */
|
|
33
|
-
const flatMap = f => pipe(map(
|
|
40
|
+
const flatMap = f => pipe(map(f))(flatten)
|
|
34
41
|
|
|
35
42
|
/**
|
|
36
43
|
* @template A
|
|
37
44
|
* @template T
|
|
38
|
-
* @typedef {(accumulator: A) => (value: T) =>
|
|
45
|
+
* @typedef {(accumulator: A) => (value: T) => PromiseOrValue<A>} Merge
|
|
39
46
|
*/
|
|
40
47
|
|
|
41
|
-
/** @type {<A, T>(f:
|
|
42
|
-
const reduce =
|
|
48
|
+
/** @type {<A, T>(f: Merge<A, T>) => (init: A) => (c: AsyncIterable<T>) => Promise<A>} */
|
|
49
|
+
const reduce = merge => init => async c => {
|
|
43
50
|
let result = init
|
|
44
51
|
for await (const i of c) {
|
|
45
|
-
result = await
|
|
52
|
+
result = await merge(result)(i)
|
|
46
53
|
}
|
|
47
54
|
return result
|
|
48
55
|
}
|
|
49
56
|
|
|
50
|
-
/** @type {<A, T>(f:
|
|
57
|
+
/** @type {<A, T>(f: Merge<A, T>) => (init: A) => (c: AsyncIterable<T>) => AsyncIterable<A>} */
|
|
51
58
|
const exclusiveScan = reduceFn => init => c => ({
|
|
52
59
|
async *[Symbol.asyncIterator]() {
|
|
53
60
|
let result = init
|
|
@@ -58,7 +65,7 @@ const exclusiveScan = reduceFn => init => c => ({
|
|
|
58
65
|
}
|
|
59
66
|
})
|
|
60
67
|
|
|
61
|
-
/** @type {<A, T>(f:
|
|
68
|
+
/** @type {<A, T>(f: Merge<A, T>) => (init: A) => (c: AsyncIterable<T>) => AsyncIterable<A>} */
|
|
62
69
|
const inclusiveScan = reduceFn => init => {
|
|
63
70
|
const e = exclusiveScan(reduceFn)(init)
|
|
64
71
|
return c => ({
|
|
@@ -78,10 +85,16 @@ const cast = iterable => ({
|
|
|
78
85
|
}
|
|
79
86
|
})
|
|
80
87
|
|
|
81
|
-
/** @type {(
|
|
82
|
-
const
|
|
88
|
+
/** @type {<I, S, R>(op: mapReduce.Operation<I, S, R>) => (_: AsyncIterable<I>) => Promise<R>} */
|
|
89
|
+
const apply = ({ merge, init, result }) => async c => result(await reduce(merge)(init)(c))
|
|
90
|
+
|
|
91
|
+
const sum = apply(mapReduce.sum)
|
|
92
|
+
|
|
93
|
+
const join = pipe(mapReduce.join)(apply)
|
|
83
94
|
|
|
84
95
|
module.exports = {
|
|
96
|
+
/** @readonly */
|
|
97
|
+
apply,
|
|
85
98
|
/** @readonly */
|
|
86
99
|
cast,
|
|
87
100
|
/** @readonly */
|
|
@@ -95,6 +108,8 @@ module.exports = {
|
|
|
95
108
|
/** @readonly */
|
|
96
109
|
sum,
|
|
97
110
|
/** @readonly */
|
|
111
|
+
join,
|
|
112
|
+
/** @readonly */
|
|
98
113
|
exclusiveScan,
|
|
99
114
|
/** @readonly */
|
|
100
115
|
inclusiveScan,
|
|
File without changes
|
package/btree/index.js
CHANGED
|
@@ -55,27 +55,37 @@ const { index3, index5 } = require('../cmp')
|
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* @template T
|
|
58
|
-
* @typedef {Leaf1<T
|
|
58
|
+
* @typedef { Leaf1<T> | Leaf2<T> | Branch3<T> | Branch5<T>} TNode
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/** @typedef {{ readonly done: false }} NotFoundDone */
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @template T
|
|
65
|
+
* @typedef {{
|
|
66
|
+
* readonly done: true
|
|
67
|
+
* readonly value: T
|
|
68
|
+
* }} FoundDone
|
|
59
69
|
*/
|
|
60
70
|
|
|
61
71
|
/**
|
|
62
72
|
* @template T
|
|
63
|
-
* @typedef {
|
|
73
|
+
* @typedef { NotFoundDone | FoundDone<T> } Done
|
|
64
74
|
*/
|
|
65
75
|
|
|
66
76
|
/**
|
|
67
77
|
* @template T
|
|
68
|
-
* @typedef {{ replace: TNode<T> }} Replace
|
|
78
|
+
* @typedef {{ readonly replace: TNode<T> }} Replace
|
|
69
79
|
*/
|
|
70
80
|
|
|
71
81
|
/**
|
|
72
82
|
* @template T
|
|
73
|
-
* @typedef {{ overflow: Branch3<T> }} Overflow
|
|
83
|
+
* @typedef {{ readonly overflow: Branch3<T> }} Overflow
|
|
74
84
|
*/
|
|
75
85
|
|
|
76
86
|
/**
|
|
77
87
|
* @template T
|
|
78
|
-
* @typedef {Done<T> | Replace<T> | Overflow<T>} Result
|
|
88
|
+
* @typedef { Done<T> | Replace<T> | Overflow<T> } Result
|
|
79
89
|
*/
|
|
80
90
|
|
|
81
91
|
/** @typedef {<T>(_: Lazy<T>) => (_: Leaf1<T>) => Result<T>} InLeaf1 */
|
|
@@ -85,35 +95,35 @@ const { index3, index5 } = require('../cmp')
|
|
|
85
95
|
|
|
86
96
|
/**
|
|
87
97
|
* @typedef {{
|
|
88
|
-
* leaf1: InLeaf1
|
|
89
|
-
* leaf2_left: InLeaf2
|
|
90
|
-
* leaf2_right: InLeaf2
|
|
91
|
-
* branch3: InBranch3
|
|
92
|
-
* branch5_left: InBranch5
|
|
93
|
-
* branch5_right: InBranch5
|
|
98
|
+
* readonly leaf1: InLeaf1
|
|
99
|
+
* readonly leaf2_left: InLeaf2
|
|
100
|
+
* readonly leaf2_right: InLeaf2
|
|
101
|
+
* readonly branch3: InBranch3
|
|
102
|
+
* readonly branch5_left: InBranch5
|
|
103
|
+
* readonly branch5_right: InBranch5
|
|
94
104
|
* }} Found
|
|
95
105
|
*/
|
|
96
106
|
|
|
97
107
|
/**
|
|
98
108
|
* @typedef {{
|
|
99
|
-
* leaf1_left: InLeaf1
|
|
100
|
-
* leaf1_right: InLeaf1
|
|
101
|
-
* leaf2_left: InLeaf2
|
|
102
|
-
* leaf2_middle: InLeaf2
|
|
103
|
-
* leaf2_right: InLeaf2
|
|
109
|
+
* readonly leaf1_left: InLeaf1
|
|
110
|
+
* readonly leaf1_right: InLeaf1
|
|
111
|
+
* readonly leaf2_left: InLeaf2
|
|
112
|
+
* readonly leaf2_middle: InLeaf2
|
|
113
|
+
* readonly leaf2_right: InLeaf2
|
|
104
114
|
* }} NotFound
|
|
105
115
|
*/
|
|
106
116
|
|
|
107
117
|
/**
|
|
108
118
|
* @typedef {{
|
|
109
|
-
* found: Found
|
|
110
|
-
* notFound: NotFound
|
|
119
|
+
* readonly found: Found
|
|
120
|
+
* readonly notFound: NotFound
|
|
111
121
|
* }} Visitor
|
|
112
122
|
*/
|
|
113
123
|
|
|
114
124
|
/**
|
|
115
125
|
* @template T
|
|
116
|
-
* @typedef {readonly [TNode<T>, T, TNode<T>, T, TNode<T>, T, TNode<T>]} Branch7
|
|
126
|
+
* @typedef { readonly [TNode<T>, T, TNode<T>, T, TNode<T>, T, TNode<T>] } Branch7
|
|
117
127
|
*/
|
|
118
128
|
|
|
119
129
|
/** @type {<T>(n: Branch7<T>) => Branch3<T>} */
|
|
@@ -221,7 +231,7 @@ const visit = ({ found, notFound }) => cmp => {
|
|
|
221
231
|
}
|
|
222
232
|
}
|
|
223
233
|
|
|
224
|
-
/** @type {<T>(_: T) => Done<T>} */
|
|
234
|
+
/** @type { <T>(_: T) => Done<T> } */
|
|
225
235
|
const found = value => ({ done: true, value })
|
|
226
236
|
|
|
227
237
|
/** @type {Found} */
|
|
@@ -233,7 +243,7 @@ const foundGet = {
|
|
|
233
243
|
branch5_left: () => ([, value]) => found(value),
|
|
234
244
|
branch5_right: () => ([, , , value]) => found(value),
|
|
235
245
|
}
|
|
236
|
-
/** @type {() => () =>
|
|
246
|
+
/** @type { () => () => NotFoundDone } */
|
|
237
247
|
const notFound = () => () => ({ done: false })
|
|
238
248
|
|
|
239
249
|
/** @type {NotFound} */
|
|
@@ -245,7 +255,7 @@ const notFoundGet = {
|
|
|
245
255
|
leaf2_right: notFound,
|
|
246
256
|
}
|
|
247
257
|
|
|
248
|
-
/** @type {<T>(_: TNode<T>) => Replace<T>} */
|
|
258
|
+
/** @type { <T>(_: TNode<T>) => Replace<T> } */
|
|
249
259
|
const replace = node => ({ replace: node })
|
|
250
260
|
|
|
251
261
|
/** @type {Found} */
|
|
@@ -288,6 +298,7 @@ const getOrInsertVisitor = {
|
|
|
288
298
|
notFound: notFoundInsert,
|
|
289
299
|
}
|
|
290
300
|
|
|
301
|
+
/** @type {Visitor} */
|
|
291
302
|
const replaceVisitor = {
|
|
292
303
|
found: foundReplace,
|
|
293
304
|
notFound: notFoundGet,
|
|
@@ -324,7 +335,7 @@ module.exports = {
|
|
|
324
335
|
values,
|
|
325
336
|
/**
|
|
326
337
|
* @readonly
|
|
327
|
-
* @type {<T>(cmp: Cmp<T>) => (node: TNode<T>) => T|undefined}
|
|
338
|
+
* @type { <T>(cmp: Cmp<T>) => (node: TNode<T>) => T|undefined }
|
|
328
339
|
*/
|
|
329
340
|
getVisitor: cmp => node => {
|
|
330
341
|
const result = visit(getVisitor)(cmp)(() => { throw '' })(node)
|
package/dev/index.js
ADDED
package/func/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** @type {<I, X>(_: (_: I) => X) => <O>(_: (_: X) => O) => (_: I) => O} */
|
|
2
|
+
const pipe = g => f => x => f(g(x))
|
|
3
|
+
|
|
4
|
+
/** @type {<T>(value: T) => T} */
|
|
5
|
+
const id = value => value
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
/** @readonly */
|
|
9
|
+
id,
|
|
10
|
+
/** @readonly */
|
|
11
|
+
pipe,
|
|
12
|
+
}
|
package/index.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const lib = require('./lib')
|
|
4
|
-
|
|
5
|
-
const todo = () => lib.panic('not implemented')
|
|
6
|
-
|
|
7
1
|
/** @type {<F>(c: string, found: (before: string, after: string) => F, notFound: (c: string, source: string) => F) => (source: string) => F} */
|
|
8
2
|
const splitOne = (c, found, notFound) => source => {
|
|
9
3
|
const i = source.indexOf(c)
|
package/iterable/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const { pipe } = require('../
|
|
2
|
-
const lib = require('../lib')
|
|
1
|
+
const { pipe } = require('../func')
|
|
3
2
|
const mr = require('../map-reduce')
|
|
4
3
|
|
|
5
4
|
/** @type {<T, R>(merge: (_: R) => (_: T) => R) => (init: R) => (_: Iterable<T>) => R} */
|
|
@@ -12,7 +11,20 @@ const reduce = merge => init => c => {
|
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
/** @type {<I, S, R>(op: mr.Operation<I, S, R>) => (_: Iterable<I>) => R} */
|
|
15
|
-
const apply =
|
|
14
|
+
const apply = ({ merge, init, result }) => pipe(reduce(merge)(init))(result)
|
|
15
|
+
|
|
16
|
+
const sum = apply(mr.sum)
|
|
17
|
+
|
|
18
|
+
const join = pipe(mr.join)(apply)
|
|
19
|
+
|
|
20
|
+
/** @type {<T, R>(f: (value: T) => R) => (c: Iterable<T>) => Iterable<R>} */
|
|
21
|
+
const map = f => c => ({
|
|
22
|
+
*[Symbol.iterator]() {
|
|
23
|
+
for (const i of c) {
|
|
24
|
+
yield f(i)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
})
|
|
16
28
|
|
|
17
29
|
module.exports = {
|
|
18
30
|
/** @readonly */
|
|
@@ -22,22 +34,13 @@ module.exports = {
|
|
|
22
34
|
reduce,
|
|
23
35
|
|
|
24
36
|
/** @readonly */
|
|
25
|
-
join
|
|
37
|
+
join,
|
|
26
38
|
|
|
27
39
|
/** @readonly */
|
|
28
|
-
sum
|
|
40
|
+
sum,
|
|
29
41
|
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
* @type {<T, R>(f: (value: T) => R) => (c: Iterable<T>) => Iterable<R>}
|
|
33
|
-
*/
|
|
34
|
-
map: f => c => ({
|
|
35
|
-
*[Symbol.iterator]() {
|
|
36
|
-
for (const i of c) {
|
|
37
|
-
yield f(i)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}),
|
|
42
|
+
/** @readonly */
|
|
43
|
+
map,
|
|
41
44
|
|
|
42
45
|
/**
|
|
43
46
|
* @readonly
|
package/iterable/test.js
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
const i = require('.')
|
|
2
|
-
const
|
|
2
|
+
const { pipe } = require('../func')
|
|
3
3
|
|
|
4
4
|
{
|
|
5
5
|
const r = i.sum([120, 300, 42])
|
|
6
|
-
|
|
6
|
+
if (r !== 462) { throw 'error' }
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
{
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
if (i.sum([1, 2]) !== 3) { throw 'error' }
|
|
11
|
+
if (i.sum([1, 2]) !== 3) { throw 'error' }
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
{
|
|
15
15
|
const x = Array.from(i.map(a => a ** 2)([1, 2, 3]))
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
if (x.length !== 3) { throw 'error' }
|
|
17
|
+
if (x[0] !== 1) { throw 'error' }
|
|
18
|
+
if (x[1] !== 4) { throw 'error' }
|
|
19
|
+
if (x[2] !== 9) { throw 'error' }
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
if (i.join('/')([]) !== '') { throw 'error' }
|
|
24
|
+
if (i.join('/')(['a']) !== 'a') { throw 'error' }
|
|
25
|
+
if (i.join('/')(['a', 'b']) !== 'a/b') { throw 'error'}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
{
|
|
29
|
-
|
|
29
|
+
if (i.find(x => x === 'c')(['a', 'b', 'c']) !== 'c') { throw 'error' }
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
{
|
|
33
33
|
/** @type {(_: string) => string|undefined} */
|
|
34
34
|
const file = _ => 'x'
|
|
35
35
|
/** @type {(_: string) => string|undefined} */
|
|
36
|
-
const x = p =>
|
|
36
|
+
const x = p => pipe
|
|
37
37
|
(i.map(x => file(x())))
|
|
38
38
|
(i.find(x => x !== undefined))
|
|
39
39
|
([() => p, () => `${p}.js`, () => `${p}/index.js`])
|
|
40
|
-
|
|
40
|
+
if (x('index.js') !== 'x') { throw 'error' }
|
|
41
41
|
}
|
package/map/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const option = require("../option")
|
|
2
2
|
const { getVisitor, setVisitor, values } = require("../btree")
|
|
3
3
|
|
|
4
4
|
/** @typedef {import("../cmp").Sign} Sign */
|
|
@@ -38,7 +38,7 @@ const cmp = a => ([b]) => a < b ? -1 : a === b ? 0 : 1
|
|
|
38
38
|
|
|
39
39
|
/** @type {<T>(node: TNode<Entry<T>>) => Map<T>} */
|
|
40
40
|
const create = root => ({
|
|
41
|
-
get: name =>
|
|
41
|
+
get: name => option.map(([,value]) => value)(getVisitor(cmp(name))(root)),
|
|
42
42
|
set: name => value => {
|
|
43
43
|
const result = setVisitor(cmp(name))(() => [name, value])(root)
|
|
44
44
|
if ('replace' in result) { return create(result.replace) }
|
|
@@ -53,7 +53,7 @@ const create = root => ({
|
|
|
53
53
|
* @type {{
|
|
54
54
|
* readonly get: (name: string) => undefined
|
|
55
55
|
* readonly set: (name: string) => <T>(value: T) => Map<T>
|
|
56
|
-
* readonly entries: () => []
|
|
56
|
+
* readonly entries: () => readonly []
|
|
57
57
|
* readonly root: undefined
|
|
58
58
|
* }}
|
|
59
59
|
*/
|
package/map/test.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { empty } = require('.')
|
|
2
|
-
const lib = require('../lib')
|
|
3
2
|
|
|
4
3
|
{
|
|
5
4
|
let m = empty.set('a')(1)
|
|
@@ -42,14 +41,13 @@ const lib = require('../lib')
|
|
|
42
41
|
|
|
43
42
|
{
|
|
44
43
|
const m = empty.set('x')(12).set('y')(44)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
if (m.get('x') !== 12) { throw 'error' }
|
|
45
|
+
if (m.get('y') !== 44) { throw 'error' }
|
|
46
|
+
if (m.get('a') !== undefined) { throw 'error' }
|
|
48
47
|
const entries = Array.from(m.entries())
|
|
49
|
-
|
|
48
|
+
if (entries.length !== 2) { throw 'error' }
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
|
|
53
51
|
{
|
|
54
52
|
/** @type {import('.').Map<number>} */
|
|
55
53
|
let m = empty
|
package/map-reduce/index.js
CHANGED
|
@@ -1,34 +1,40 @@
|
|
|
1
|
-
const { pipe } = require('../
|
|
1
|
+
const { pipe, id } = require('../func')
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template S
|
|
5
|
+
* @template I
|
|
6
|
+
* @typedef {(state: S) => (value: I) => S} Merge
|
|
7
|
+
*/
|
|
2
8
|
|
|
3
9
|
/**
|
|
4
10
|
* @template I
|
|
5
11
|
* @template S
|
|
6
12
|
* @template O
|
|
7
13
|
* @typedef {{
|
|
8
|
-
* readonly
|
|
14
|
+
* readonly merge: Merge<S, I>
|
|
9
15
|
* readonly result: (state: S) => O
|
|
10
16
|
* readonly init: S
|
|
11
17
|
* }} Operation
|
|
12
18
|
*/
|
|
13
19
|
|
|
14
20
|
/** @type {<I, T>(mapFn: (value: I) => T) => <S, O>(op: Operation<T, S, O>) => Operation<I, S, O>} */
|
|
15
|
-
const map = mapFn => ({
|
|
16
|
-
|
|
21
|
+
const map = mapFn => ({ merge, result, init}) => ({
|
|
22
|
+
merge: pipe(merge)(pipe(mapFn)),
|
|
17
23
|
result,
|
|
18
24
|
init,
|
|
19
25
|
})
|
|
20
26
|
|
|
21
27
|
/** @type {(separator: string) => Operation<string, string|undefined, string>} */
|
|
22
28
|
const join = separator => ({
|
|
23
|
-
|
|
29
|
+
merge: s => i => s === undefined ? i : `${s}${separator}${i}`,
|
|
24
30
|
init: undefined,
|
|
25
31
|
result: s => s === undefined ? '' : s
|
|
26
32
|
})
|
|
27
33
|
|
|
28
34
|
/** @type {Operation<number, number, number>} */
|
|
29
35
|
const sum = {
|
|
30
|
-
|
|
31
|
-
result:
|
|
36
|
+
merge: a => i => a + i,
|
|
37
|
+
result: id,
|
|
32
38
|
init: 0,
|
|
33
39
|
}
|
|
34
40
|
|
package/module-manager/index.js
CHANGED
|
@@ -1,86 +1,98 @@
|
|
|
1
|
-
const
|
|
1
|
+
const array = require('../array')
|
|
2
|
+
const { pipe } = require('../func')
|
|
3
|
+
const option = require('../option')
|
|
4
|
+
const { head, last, splitLast, splitFirst } = array
|
|
2
5
|
const iter = require('../iterable')
|
|
3
6
|
const mr = require('../map-reduce')
|
|
4
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @template T
|
|
10
|
+
* @typedef {array.Array<T>} Array
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** @typedef {Array<string>} Path */
|
|
14
|
+
|
|
5
15
|
/** @typedef {(_: string) => string|undefined} ReadFile */
|
|
6
16
|
|
|
7
17
|
/**
|
|
8
18
|
* @typedef {{
|
|
9
|
-
* id: string
|
|
10
|
-
* dependencies: Dependencies
|
|
11
|
-
* file: ReadFile
|
|
19
|
+
* readonly id: Array<string>
|
|
20
|
+
* readonly dependencies: Dependencies
|
|
21
|
+
* readonly file: ReadFile
|
|
12
22
|
* }} Package
|
|
13
23
|
*/
|
|
14
24
|
|
|
15
25
|
/**
|
|
16
26
|
* @typedef {{
|
|
17
|
-
* pack: Package,
|
|
18
|
-
* local: string
|
|
27
|
+
* readonly pack: Package,
|
|
28
|
+
* readonly local: Array<string>,
|
|
19
29
|
* }} Location
|
|
20
30
|
*/
|
|
21
31
|
|
|
22
32
|
/**
|
|
23
33
|
* @typedef {{
|
|
24
|
-
* fileName: string
|
|
25
|
-
* location: Location
|
|
26
|
-
* source: string
|
|
34
|
+
* readonly fileName: string
|
|
35
|
+
* readonly location: Location
|
|
36
|
+
* readonly source: string
|
|
27
37
|
* }} Module
|
|
28
38
|
*/
|
|
29
39
|
|
|
30
40
|
/** @typedef {(_: string) => undefined|Package|Dependencies} Dependencies */
|
|
31
41
|
|
|
32
|
-
/** @type {mr.Operation<string, undefined|
|
|
42
|
+
/** @type {mr.Operation<string, undefined|Path, undefined|Path>} */
|
|
33
43
|
const pathNormReduce = {
|
|
34
|
-
|
|
44
|
+
merge: path => item =>
|
|
35
45
|
path === undefined ?
|
|
36
46
|
undefined :
|
|
37
47
|
['', '.'].includes(item) ?
|
|
38
48
|
path :
|
|
39
49
|
item === '..' ?
|
|
40
|
-
|
|
50
|
+
head(path) :
|
|
41
51
|
[...path, item],
|
|
42
52
|
init: [],
|
|
43
53
|
result: s => s,
|
|
44
54
|
}
|
|
45
55
|
|
|
46
|
-
/** @type {(_: string
|
|
56
|
+
/** @type {(_: Array<string>) => boolean} */
|
|
47
57
|
const isRelative = localId => ['.', '..'].includes(localId[0])
|
|
48
58
|
|
|
49
59
|
const pathNorm = iter.apply(pathNormReduce)
|
|
50
60
|
|
|
51
|
-
/** @type {(_: Package) => (_:
|
|
61
|
+
/** @type {(_: Package) => (_: Path) => Module|undefined} */
|
|
52
62
|
const internal = pack => {
|
|
53
|
-
/** @type {(_:
|
|
63
|
+
/** @type {(_: Path) => (_: string) => Module|undefined} */
|
|
54
64
|
const readFile = local => fileName => {
|
|
55
65
|
const source = pack.file([...local, fileName].join('/'))
|
|
56
66
|
return source === undefined ? undefined : { fileName, location: { pack, local }, source}
|
|
57
67
|
}
|
|
58
68
|
return path => {
|
|
59
|
-
/** @type {(_:
|
|
69
|
+
/** @type {(_: Path) => Module|undefined} */
|
|
60
70
|
const read = local => {
|
|
61
|
-
/** @type {(_: [
|
|
62
|
-
const tryFiles = ([head,
|
|
71
|
+
/** @type {(_: readonly[Path, string]) => Module|undefined} */
|
|
72
|
+
const tryFiles = ([head, file]) => {
|
|
63
73
|
/** @type {(_: string) => Module|undefined} */
|
|
64
|
-
const one = ext => readFile(head)(
|
|
65
|
-
return ['.', '..', '', undefined].includes(
|
|
74
|
+
const one = ext => readFile(head)(file + ext)
|
|
75
|
+
return ['.', '..', '', undefined].includes(last(path)) ? undefined : one('') ?? one('.js')
|
|
66
76
|
}
|
|
67
|
-
return
|
|
77
|
+
return option.map(tryFiles)(splitLast(local)) ?? readFile(local)('index.js')
|
|
68
78
|
}
|
|
69
|
-
return
|
|
79
|
+
return option.map(read)(pathNorm(path))
|
|
70
80
|
}
|
|
71
81
|
}
|
|
72
82
|
|
|
73
|
-
/** @type {(_: Package|Dependencies|undefined) => (_:
|
|
83
|
+
/** @type {(_: Package|Dependencies|undefined) => (_: Path) => Module|undefined} */
|
|
74
84
|
const externalOrInternal = p =>
|
|
75
85
|
p === undefined ? () => undefined : (typeof p === 'function' ? external(p) : internal(p))
|
|
76
86
|
|
|
77
|
-
/** @type {(_: Dependencies) => (_:
|
|
87
|
+
/** @type {(_: Dependencies) => (_: Path) => Module|undefined} */
|
|
78
88
|
const external = packages => {
|
|
79
|
-
/** @type {(_: [string,
|
|
89
|
+
/** @type {(_: readonly [string, Path]) => Module|undefined} */
|
|
80
90
|
const defined = ([first, tail]) => externalOrInternal(packages(first))(tail)
|
|
81
|
-
/** @type {(_:
|
|
82
|
-
const
|
|
83
|
-
return
|
|
91
|
+
/** @type {(_: Path) => readonly [string, Path]|undefined} */
|
|
92
|
+
const sf = splitFirst
|
|
93
|
+
return pipe
|
|
94
|
+
(sf)
|
|
95
|
+
(option.map(defined))
|
|
84
96
|
}
|
|
85
97
|
|
|
86
98
|
/** @type {(_: Location) => (_: string) => Module|undefined} */
|
|
@@ -101,4 +113,4 @@ module.exports = {
|
|
|
101
113
|
getModule,
|
|
102
114
|
/** @readonly */
|
|
103
115
|
moduleId,
|
|
104
|
-
}
|
|
116
|
+
}
|
package/module-manager/test.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
const i = require('.')
|
|
2
2
|
|
|
3
|
-
const lib = require('../lib')
|
|
4
|
-
|
|
5
3
|
require('./node/test')
|
|
6
4
|
|
|
7
5
|
/** @type {<T>(_: T | undefined) => T} */
|
|
8
|
-
const cast = x =>
|
|
6
|
+
const cast = x => {
|
|
7
|
+
if (x === undefined) { throw 'x' }
|
|
8
|
+
return x
|
|
9
|
+
}
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
if (i.isRelative('a/b/c'.split('/'))) { throw 'error '}
|
|
12
|
+
if (!i.isRelative('./a/b/c'.split('/'))) { throw 'error ' }
|
|
13
|
+
if (cast(i.pathNorm('a/../b'.split('/'))).join('/') !== 'b') { throw 'error ' }
|
|
14
|
+
if (cast(i.pathNorm('a/../b/../c'.split('/'))).join('/') !== 'c') { throw 'error ' }
|
|
15
|
+
if (cast(i.pathNorm('./a/../b/c/..//d/'.split('/'))).join('/') !== 'b/d') { throw 'error ' }
|
|
15
16
|
|
|
16
17
|
{
|
|
17
18
|
/** @type {i.Package} */
|
|
@@ -35,7 +36,8 @@ lib.panic_if('pathNorm')(cast(i.pathNorm('./a/../b/c/..//d/'.split('/'))).join('
|
|
|
35
36
|
'index.js': 'b/c ./index.js',
|
|
36
37
|
'x/index.js': 'b/c ./x/index.js',
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
if (['.js', '', 'undefined.js'].includes(path)) { throw '.js' }
|
|
40
|
+
return f[path]
|
|
39
41
|
},
|
|
40
42
|
id: ['c']
|
|
41
43
|
}
|
|
@@ -59,7 +61,8 @@ lib.panic_if('pathNorm')(cast(i.pathNorm('./a/../b/c/..//d/'.split('/'))).join('
|
|
|
59
61
|
'a/index.js': './a/index.js',
|
|
60
62
|
'a/index.js.js': './a/index.js.js',
|
|
61
63
|
}
|
|
62
|
-
|
|
64
|
+
if (['.js', '', 'undefined.js'].includes(path)) { throw '.js' }
|
|
65
|
+
return f[path]
|
|
63
66
|
},
|
|
64
67
|
id: ['']
|
|
65
68
|
}
|
|
@@ -72,8 +75,8 @@ lib.panic_if('pathNorm')(cast(i.pathNorm('./a/../b/c/..//d/'.split('/'))).join('
|
|
|
72
75
|
}
|
|
73
76
|
{
|
|
74
77
|
const g = i.getModule({pack, local: []})
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
if (g('') !== undefined) { throw 'error' }
|
|
79
|
+
if (g('..') !== undefined) { throw 'error' }
|
|
77
80
|
expect(g('.'))({ fileName: 'index.js', location: { pack, local: []}, source: './index.js'})
|
|
78
81
|
expect(g('./index'))({ fileName: 'index.js', location: { pack, local: []}, source: './index.js'})
|
|
79
82
|
expect(g('./index.js'))({ fileName: 'index.js', location: { pack, local: []}, source: './index.js'})
|
|
@@ -81,10 +84,10 @@ lib.panic_if('pathNorm')(cast(i.pathNorm('./a/../b/c/..//d/'.split('/'))).join('
|
|
|
81
84
|
expect(g('./a'))({ fileName: 'index.js', location: { pack, local: ['a']}, source: './a/index.js'})
|
|
82
85
|
expect(g('./a/index'))({ fileName: 'index.js', location: { pack, local: ['a']}, source: './a/index.js'})
|
|
83
86
|
expect(g('./a/index.js'))({ fileName: 'index.js.js', location: { pack, local: ['a']}, source: './a/index.js'})
|
|
84
|
-
|
|
87
|
+
if (g('./x') !== undefined) { throw 'error' }
|
|
85
88
|
expect(g('a'))({ fileName: 'index.js', location: { pack: a, local: []}, source: 'a ./index.js'})
|
|
86
89
|
expect(g('a/index'))({ fileName: 'index.js', location: { pack: a, local: []}, source: 'a ./index.js'})
|
|
87
|
-
|
|
90
|
+
if (g('b') !== undefined) { throw 'error' }
|
|
88
91
|
expect(g('b/c'))({ fileName: 'index.js', location: { pack: c, local: []}, source: 'b/c ./index.js'})
|
|
89
92
|
expect(g('b/c/index'))({ fileName: 'index.js', location: { pack: c, local: []}, source: 'b/c ./index.js'})
|
|
90
93
|
expect(g('b/c/index.js'))({ fileName: 'index.js', location: { pack: c, local: []}, source: 'b/c ./index.js'})
|
|
@@ -93,21 +96,21 @@ lib.panic_if('pathNorm')(cast(i.pathNorm('./a/../b/c/..//d/'.split('/'))).join('
|
|
|
93
96
|
}
|
|
94
97
|
{
|
|
95
98
|
const g = i.getModule({pack, local: ['index']})
|
|
96
|
-
|
|
99
|
+
if (g('') !== undefined) { throw 'error' }
|
|
97
100
|
expect(g('..'))({ fileName: 'index.js', location: { pack, local: []}, source: './index.js'})
|
|
98
101
|
expect(g('.'))({ fileName: 'index.js', location: { pack, local: ['index']}, source: './index/index.js'})
|
|
99
102
|
expect(g('./index'))({ fileName: 'index.js', location: { pack, local: ['index']}, source: './index/index.js'})
|
|
100
103
|
expect(g('./index.js'))({ fileName: 'index.js', location: { pack, local: ['index']}, source: './index/index.js'})
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
if (g('./index/') !== undefined) { throw 'error' }
|
|
105
|
+
if (g('./a') !== undefined) { throw 'error' }
|
|
103
106
|
expect(g('../a'))({ fileName: 'index.js', location: { pack, local: ['a']}, source: './a/index.js'})
|
|
104
107
|
expect(g('../a/index'))({ fileName: 'index.js', location: { pack, local: ['a']}, source: './a/index.js'})
|
|
105
108
|
expect(g('../a/index.js'))({ fileName: 'index.js', location: { pack, local: ['a']}, source: './a/index.js'})
|
|
106
109
|
expect(g('../a/index.js.js'))({ fileName: 'index.js.js', location: { pack, local: ['a']}, source: './a/index.js.js'})
|
|
107
|
-
|
|
110
|
+
if (g('./x') !== undefined) { throw 'error' }
|
|
108
111
|
expect(g('a'))({ fileName: 'index.js', location: { pack: a, local: []}, source: 'a ./index.js'})
|
|
109
112
|
expect(g('a/index'))({ fileName: 'index.js', location: { pack: a, local: []}, source: 'a ./index.js'})
|
|
110
|
-
|
|
113
|
+
if (g('b') !== undefined) { throw 'error' }
|
|
111
114
|
expect(g('b/c'))({ fileName: 'index.js', location: { pack: c, local: []}, source: 'b/c ./index.js'})
|
|
112
115
|
expect(g('b/c/index'))({ fileName: 'index.js', location: { pack: c, local: []}, source: 'b/c ./index.js'})
|
|
113
116
|
expect(g('b/c/index.js'))({ fileName: 'index.js', location: { pack: c, local: []}, source: 'b/c ./index.js'})
|
package/option/index.js
ADDED
package/package.json
CHANGED
package/test.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
const lib = require('./lib')
|
|
2
1
|
const i = require('./')
|
|
3
2
|
|
|
4
|
-
require('./async/test')
|
|
3
|
+
require('./async/iterable/test')
|
|
5
4
|
require('./module-manager/test')
|
|
6
|
-
require('./lib/test')
|
|
7
5
|
|
|
8
6
|
/** @type {() => never} */
|
|
9
|
-
const assert = () =>
|
|
7
|
+
const assert = () => { throw 'assert' }
|
|
10
8
|
|
|
11
9
|
/** @type {(_: boolean) => void} */
|
|
12
|
-
const assert_if = c =>
|
|
10
|
+
const assert_if = c => { if (c) { throw 'assert_if' } }
|
|
13
11
|
|
|
14
12
|
{
|
|
15
13
|
i.parseModuleUrl('')(
|
package/lib/index.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @template T
|
|
5
|
-
* @typedef {T|undefined} Option
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @template T
|
|
10
|
-
* @typedef {() => NotEmptySequence<T>|undefined} Sequence
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @template T
|
|
15
|
-
* @typedef {{ first: T, tail: Sequence<T>}} NotEmptySequence
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @template T
|
|
20
|
-
* @typedef {() => Continuation<T>} Continue
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @template T
|
|
25
|
-
* @typedef {[T]|Continue<T>} Continuation
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
/** @type {(_: string) => never} */
|
|
29
|
-
const panic = message => { throw message }
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @template T
|
|
33
|
-
* @template R
|
|
34
|
-
* @typedef {{
|
|
35
|
-
* merge: (_: R) => (_: T) => R
|
|
36
|
-
* init: R
|
|
37
|
-
* }} Reduce
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
|
-
/** @type {<I, X>(_: (_: I) => X) => <O>(_: (_: X) => O) => (_: I) => O} */
|
|
41
|
-
const pipe = g => f => x => f(g(x))
|
|
42
|
-
|
|
43
|
-
/** @type {<T, R>(_: (_: T) => R) => (_: T|undefined) => R|undefined} */
|
|
44
|
-
const optionMap = f => x => x === undefined ? undefined : f(x)
|
|
45
|
-
|
|
46
|
-
/** @type {<T>(_: T[]) => T[]} */
|
|
47
|
-
const uncheckTail = a => a.slice(1)
|
|
48
|
-
|
|
49
|
-
/** @type {<T>(_: T[]) => T[]} */
|
|
50
|
-
const uncheckHead = a => a.slice(0, -1)
|
|
51
|
-
|
|
52
|
-
/** @type {<T>(_: T[]) => T|undefined} */
|
|
53
|
-
const last = a => a[a.length - 1]
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @template I
|
|
57
|
-
* @typedef {{
|
|
58
|
-
* readonly i: <O>(f: (input: I) => O) => Chain<O>
|
|
59
|
-
* readonly result: () => I
|
|
60
|
-
* }} Chain
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
/** @type {<I>(value: I) => Chain<I>} */
|
|
64
|
-
const chain = value => ({
|
|
65
|
-
i: f => chain(f(value)),
|
|
66
|
-
result: () => value
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @template I
|
|
71
|
-
* @template T
|
|
72
|
-
* @typedef {{
|
|
73
|
-
* readonly x: <O>(f: (v: T) => O) => Pipe<I, O>
|
|
74
|
-
* readonly f: (input: I) => T
|
|
75
|
-
* }} Pipe
|
|
76
|
-
*/
|
|
77
|
-
|
|
78
|
-
module.exports = {
|
|
79
|
-
|
|
80
|
-
panic,
|
|
81
|
-
|
|
82
|
-
todo: () => panic('not implemented'),
|
|
83
|
-
|
|
84
|
-
/** @type {(_: string) => (_: boolean) => void} */
|
|
85
|
-
panic_if: message => condition => condition ? panic(message) : undefined,
|
|
86
|
-
|
|
87
|
-
/** @type {<T>(_: Continuation<T>) => T} */
|
|
88
|
-
trampoline: continuation => {
|
|
89
|
-
while (true) {
|
|
90
|
-
if (typeof continuation !== 'function') {
|
|
91
|
-
return continuation[0]
|
|
92
|
-
}
|
|
93
|
-
continuation = continuation()
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
pipe,
|
|
98
|
-
|
|
99
|
-
last,
|
|
100
|
-
|
|
101
|
-
optionMap,
|
|
102
|
-
|
|
103
|
-
/** @type {<T>(_: T[]) => T[]|undefined} */
|
|
104
|
-
tail: a => a.length === 0 ? undefined : uncheckTail(a),
|
|
105
|
-
|
|
106
|
-
/** @type {<T>(_: T[]) => [T, T[]]|undefined} */
|
|
107
|
-
splitFirst: a => {
|
|
108
|
-
/** @typedef {typeof a[0]} T*/
|
|
109
|
-
/** @type {(_: T) => [T, T[]]} */
|
|
110
|
-
const split = first => [first, uncheckTail(a)]
|
|
111
|
-
return optionMap(split)(a[0])
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
/** @type {<T>(_: T[]) => T[]|undefined} */
|
|
115
|
-
head: a => a.length === 0 ? undefined : uncheckHead(a),
|
|
116
|
-
|
|
117
|
-
/** @type {<T>(_: T[]) => [T[], T]|undefined} */
|
|
118
|
-
splitLast: a => {
|
|
119
|
-
/** @typedef {typeof a[0]} T*/
|
|
120
|
-
/** @type {(_: T) => [T[], T]} */
|
|
121
|
-
const split = x => [uncheckHead(a), x]
|
|
122
|
-
return optionMap(split)(last(a))
|
|
123
|
-
},
|
|
124
|
-
}
|