functionalscript 0.0.284 → 0.0.288

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.284",
3
+ "version": "0.0.288",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -54,6 +54,18 @@ const seq = require('../list')
54
54
 
55
55
  /** @typedef {0|1|2|3|4} Index5 */
56
56
 
57
+ /**
58
+ * @template T
59
+ * @typedef {T extends Array1<infer _> ? Index1 :
60
+ * T extends Array2<infer _> ? Index2 :
61
+ * T extends Array3<infer _> ? Index3 :
62
+ * T extends Array4<infer _> ? Index4 :
63
+ * T extends Array5<infer _> ? Index5 :
64
+ * T extends readonly (infer _)[] ? number :
65
+ * never
66
+ * } KeyOf
67
+ */
68
+
57
69
  /** @type {<T>(_: readonly T[]) => readonly T[]} */
58
70
  const uncheckTail = a => a.slice(1)
59
71
 
@@ -1,41 +1,31 @@
1
1
  const _ = require('..')
2
- const { todo } = require('../../../dev')
3
2
  const list = require('../../list')
4
3
  const cmp = require('../../function/compare')
4
+ const array = require('../../array')
5
5
 
6
6
  /**
7
7
  * @template T
8
- * @typedef {readonly[1, _.Leaf1<T>|_.Branch3<T>]} Found1
8
+ * @typedef {readonly[cmp.Index3, _.Leaf1<T>]} FirstLeaf1
9
9
  */
10
10
 
11
11
  /**
12
12
  * @template T
13
- * @typedef {readonly[1|3, _.Leaf2<T> | _.Branch5<T>]} Found2
13
+ * @typedef {readonly[1, _.Branch3<T>]} FirstBranch3
14
14
  */
15
15
 
16
16
  /**
17
17
  * @template T
18
- * @typedef {readonly[0|2, _.Leaf1<T>]} NotFound1
18
+ * @typedef {readonly[cmp.Index5, _.Leaf2<T>]} FirstLeaf2
19
19
  */
20
20
 
21
21
  /**
22
22
  * @template T
23
- * @typedef {readonly[0|2|4, _.Leaf2<T>]} NotFound2
23
+ * @typedef {readonly[1|3, _.Branch5<T>]} FirstBranch5
24
24
  */
25
25
 
26
26
  /**
27
27
  * @template T
28
- * @typedef {Found1<T> | Found2<T>} Found
29
- */
30
-
31
- /**
32
- * @template T
33
- * @typedef {NotFound1<T> | NotFound2<T>} NotFound
34
- */
35
-
36
- /**
37
- * @template T
38
- * @typedef {Found<T> | NotFound<T>} First
28
+ * @typedef {FirstLeaf1<T> | FirstBranch3<T> | FirstLeaf2<T> | FirstBranch5<T>} First
39
29
  */
40
30
 
41
31
  /**
@@ -53,6 +43,12 @@ const cmp = require('../../function/compare')
53
43
  * @typedef {PathItem3<T> | PathItem5<T>} PathItem
54
44
  */
55
45
 
46
+ /** @type {<T>(item: PathItem<T>) => _.Node<T>} */
47
+ const child = item => {
48
+ /** @typedef {typeof item extends PathItem<infer T> ? T : never} T */
49
+ return /** @type {_.Node<T>} */(item[1][item[0]])
50
+ }
51
+
56
52
  /**
57
53
  * @template T
58
54
  * @typedef {list.List<PathItem<T>>} Path
@@ -60,8 +56,49 @@ const cmp = require('../../function/compare')
60
56
 
61
57
  /**
62
58
  * @template T
63
- * @typedef {readonly[First<T>, Path<T>]} Result<T>
59
+ * @typedef {{
60
+ * readonly first: First<T>,
61
+ * readonly tail: Path<T>
62
+ * }} Result<T>
64
63
  */
65
64
 
66
65
  /** @type {<T>(c: cmp.Compare<T>) => (node: _.Node<T>) => Result<T>} */
67
- const find = c => node => todo()
66
+ const find = c => {
67
+ const i3 = cmp.index3(c)
68
+ const i5 = cmp.index5(c)
69
+ /** @typedef {typeof c extends cmp.Compare<infer T> ? T : never} T */
70
+ /** @type {(prior: Path<T>) => (node: _.Node<T>) => Result<T>} */
71
+ const f = tail => node => {
72
+ /** @type {(index: array.KeyOf<typeof node>) => Result<T>} */
73
+ const append = index => {
74
+ const first = /** @type {PathItem<T>} */([index, node])
75
+ return f({ first, tail })(child(first))
76
+ }
77
+ /** @type {(index: array.KeyOf<typeof node>) => Result<T>} */
78
+ const done = index => ({ first: /** @type {First<T>} */([index, node]), tail })
79
+ switch (node.length) {
80
+ case 1: { return done(i3(node[0])) }
81
+ case 2: { return done(i5(node)) }
82
+ case 3: {
83
+ const i = i3(node[1])
84
+ switch (i) {
85
+ case 0: case 2: { return append(i) }
86
+ case 1: { return done(i) }
87
+ }
88
+ }
89
+ case 5: {
90
+ const i = i5([node[1], node[3]])
91
+ switch (i) {
92
+ case 0: case 2: case 4: { return append(i) }
93
+ case 1: case 3: { return done(i) }
94
+ }
95
+ }
96
+ }
97
+ }
98
+ return f(undefined)
99
+ }
100
+
101
+ module.exports = {
102
+ /** @readonly */
103
+ find,
104
+ }
@@ -0,0 +1,119 @@
1
+ const _ = require('.')
2
+ const list = require('../../list')
3
+ const json = require('../../../json')
4
+ const { sort } = require('../../object')
5
+ const btree = require('..')
6
+ const { stringCmp } = require('../../function/compare')
7
+
8
+ const jsonStr = json.stringify(sort)
9
+
10
+ /** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string>} */
11
+ const set = node => value => {
12
+ const result = btree.setVisitor(stringCmp(value))(node)(() => value)
13
+ switch (result[0]) {
14
+ case 'replace': case 'overflow': { return result[1] }
15
+ default: { return node }
16
+ }
17
+ }
18
+
19
+ /** @type {(r: _.Result<json.Unknown>) => string} */
20
+ const str = r => jsonStr(list.toArray(list.map(x => x[0])(r)))
21
+
22
+ /** @type {(i: string) => (m: btree.Node<string>) => string} */
23
+ const find = i => m => str(_.find(stringCmp(i))(m))
24
+
25
+ {
26
+ /** @type {btree.Node<string>} */
27
+ let _map = ['1']
28
+ for (let i = 2; i <= 10; i++)
29
+ _map = set(_map)((i * i).toString())
30
+ {
31
+ const s = jsonStr(_map)
32
+ if (s !== '[[["1","100"],"16",["25","36"]],"4",[["49"],"64",["81","9"]]]') { throw s }
33
+ }
34
+ //
35
+ {
36
+ const r = find("0")(_map)
37
+ if (r !== '[0,0,0]') { throw r }
38
+ }
39
+ {
40
+ const r = find("1")(_map)
41
+ if (r !== '[1,0,0]') { throw r }
42
+ }
43
+ {
44
+ const r = find("10")(_map)
45
+ if (r !== '[2,0,0]') { throw r }
46
+ }
47
+ {
48
+ const r = find("100")(_map)
49
+ if (r !== '[3,0,0]') { throw r }
50
+ }
51
+ {
52
+ const r = find("12")(_map)
53
+ if (r !== '[4,0,0]') { throw r }
54
+ }
55
+ {
56
+ const r = find("16")(_map)
57
+ if (r !== '[1,0]') { throw r }
58
+ }
59
+ {
60
+ const r = find("17")(_map)
61
+ if (r !== '[0,2,0]') { throw r }
62
+ }
63
+ {
64
+ const r = find("25")(_map)
65
+ if (r !== '[1,2,0]') { throw r }
66
+ }
67
+ {
68
+ const r = find("26")(_map)
69
+ if (r !== '[2,2,0]') { throw r }
70
+ }
71
+ {
72
+ const r = find("36")(_map)
73
+ if (r !== '[3,2,0]') { throw r }
74
+ }
75
+ {
76
+ const r = find("37")(_map)
77
+ if (r !== '[4,2,0]') { throw r }
78
+ }
79
+ {
80
+ const r = find("4")(_map)
81
+ if (r !== '[1]') { throw r }
82
+ }
83
+ {
84
+ const r = find("41")(_map)
85
+ if (r !== '[0,0,2]') { throw r }
86
+ }
87
+ {
88
+ const r = find("49")(_map)
89
+ if (r !== '[1,0,2]') { throw r }
90
+ }
91
+ {
92
+ const r = find("5")(_map)
93
+ if (r !== '[2,0,2]') { throw r }
94
+ }
95
+ {
96
+ const r = find("64")(_map)
97
+ if (r !== '[1,2]') { throw r }
98
+ }
99
+ {
100
+ const r = find("65")(_map)
101
+ if (r !== '[0,2,2]') { throw r }
102
+ }
103
+ {
104
+ const r = find("81")(_map)
105
+ if (r !== '[1,2,2]') { throw r }
106
+ }
107
+ {
108
+ const r = find("85")(_map)
109
+ if (r !== '[2,2,2]') { throw r }
110
+ }
111
+ {
112
+ const r = find("9")(_map)
113
+ if (r !== '[3,2,2]') { throw r }
114
+ }
115
+ {
116
+ const r = find("91")(_map)
117
+ if (r !== '[4,2,2]') { throw r }
118
+ }
119
+ }
@@ -0,0 +1,93 @@
1
+ const _ = require('..')
2
+ const find = require('../find')
3
+ const cmp = require('../../function/compare')
4
+ const list = require('../../list')
5
+
6
+ /**
7
+ * @template T
8
+ * @typedef {_.Branch1<T> | _.Branch3<T>} Result
9
+ */
10
+
11
+ /** @type {<T>(b: _.Branch5<T> | _.Branch7<T>) => Result<T>} */
12
+ const b57 = b => b.length === 5 ? [b] : [[b[0], b[1], b[2]], b[3], [b[4], b[5], b[6]]]
13
+
14
+ /** @type {<T>(a: Result<T>) => (i: find.PathItem<T>) => Result<T>} */
15
+ const reduce = a => i => {
16
+ switch (i[0]) {
17
+ case 0: {
18
+ const x = i[1]
19
+ switch (x.length) {
20
+ case 3: { return [[...a, x[1], x[2]]] }
21
+ case 5: { return b57([...a, x[1], x[2], x[3], x[4]]) }
22
+ }
23
+ }
24
+ case 2: {
25
+ const x = i[1]
26
+ switch (x.length) {
27
+ case 3: { return [[x[0], x[1], ...a]] }
28
+ case 5: { return b57([x[0], x[1], ...a, x[3], x[4]]) }
29
+ }
30
+ }
31
+ case 4: {
32
+ const x = i[1]
33
+ return b57([x[0], x[1], x[2], x[3], ...a])
34
+ }
35
+ }
36
+ }
37
+
38
+ /** @type {<T>(c: cmp.Compare<T>) => (value: T) => (node: _.Node<T>) => _.Node<T>} */
39
+ const set = c => value => node => {
40
+ const { first, tail } = find.find(c)(node)
41
+ /** @typedef {typeof value} T */
42
+ /** @type {() => Result<T>} */
43
+ const f = () => {
44
+ switch (first[0]) {
45
+ case 0: {
46
+ // insert
47
+ const x = first[1]
48
+ switch (x.length) {
49
+ case 1: { return [[value, x[0]]] }
50
+ case 2: { return [[value], x[0], [x[1]]] }
51
+ }
52
+ }
53
+ case 1: {
54
+ // replace
55
+ const x = first[1];
56
+ switch (x.length) {
57
+ case 1: { return [[value]] }
58
+ case 2: { return [[value, x[1]]] }
59
+ case 3: { return [[x[0], value, x[2]]] }
60
+ case 5: { return [[x[0], value, x[2], x[3], x[4]]] }
61
+ }
62
+ }
63
+ case 2: {
64
+ // insert
65
+ const x = first[1];
66
+ switch (x.length) {
67
+ case 1: { return [[x[0], value]] }
68
+ case 2: { return [[x[0]], value, [x[1]]] }
69
+ }
70
+ }
71
+ case 3: {
72
+ // replace
73
+ const x = first[1];
74
+ switch (x.length) {
75
+ case 2: { return [[x[0], value]] }
76
+ case 5: { return [[x[0], x[1], x[2], value, x[4]]]}
77
+ }
78
+ }
79
+ case 4: {
80
+ // insert
81
+ const [v0, v1] = first[1];
82
+ return [[v0], v1, [value]]
83
+ }
84
+ }
85
+ }
86
+ const r = list.reduce(reduce)(f())(tail)
87
+ return r.length === 1 ? r[0] : r
88
+ }
89
+
90
+ module.exports = {
91
+ /** @readonly */
92
+ set,
93
+ }
@@ -0,0 +1,19 @@
1
+ const _ = require('.')
2
+ const btree = require('..')
3
+ const { stringCmp } = require('../../function/compare')
4
+ const json = require('../../../json')
5
+ const { sort } = require('../../object')
6
+
7
+ /** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string>} */
8
+ const set = node => value => _.set(stringCmp(value))(value)(node)
9
+
10
+ const jsonStr = json.stringify(sort)
11
+
12
+ {
13
+ /** @type {btree.Node<string>} */
14
+ let _map = ['1']
15
+ for (let i = 2; i <= 10; i++)
16
+ _map = set(_map)((i * i).toString())
17
+ const r = jsonStr(_map)
18
+ if (r !== '[[["1","100"],"16",["25","36"]],"4",[["49"],"64",["81","9"]]]') { throw r }
19
+ }
@@ -5,6 +5,9 @@ const { sort } = require('../object')
5
5
  const { stringCmp } = require('../function/compare')
6
6
  const list = require('../list')
7
7
 
8
+ require('./find/test')
9
+ require('./set/test')
10
+
8
11
  const jsonStr = json.stringify(sort)
9
12
 
10
13
  /** @type {(sequence: list.List<json.Unknown>) => string} */