functionalscript 0.0.467 → 0.0.469
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/fsm/module.f.cjs +48 -5
- package/fsm/test.f.cjs +74 -0
- package/package.json +1 -1
- package/types/byte_set/module.f.cjs +2 -0
- package/types/range_map/module.f.cjs +7 -1
- package/types/sorted_list/module.f.cjs +31 -1
- package/types/sorted_list/test.f.cjs +18 -0
- package/types/sorted_set/module.f.cjs +7 -4
- package/types/sorted_set/test.f.cjs +18 -0
package/fsm/module.f.cjs
CHANGED
|
@@ -1,21 +1,64 @@
|
|
|
1
|
-
const { todo } = require('../dev/module.f.cjs')
|
|
2
1
|
const list = require('../types/list/module.f.cjs')
|
|
2
|
+
const { equal, isEmpty, fold, toArray, scan } = list
|
|
3
3
|
const byteSet = require('../types/byte_set/module.f.cjs')
|
|
4
|
+
const { toRangeMap } = byteSet
|
|
5
|
+
const sortedSet = require('../types/sorted_set/module.f.cjs')
|
|
6
|
+
const { intersect, union } = sortedSet
|
|
7
|
+
const rangeMap = require('../types/range_map/module.f.cjs')
|
|
8
|
+
const { merge } = rangeMap
|
|
9
|
+
const { unsafeCmp } = require('../types/function/compare/module.f.cjs')
|
|
10
|
+
const operator = require("../types/function/operator/module.f.cjs")
|
|
11
|
+
const { strictEqual } = operator
|
|
12
|
+
const { stringify } = require('../json/module.f.cjs')
|
|
13
|
+
const { identity } = require('../types/function/module.f.cjs')
|
|
4
14
|
|
|
5
15
|
/** @typedef {readonly[string, byteSet.ByteSet, string]} Rule */
|
|
6
16
|
|
|
7
17
|
/** @typedef {list.List<Rule>} Grammar */
|
|
8
18
|
|
|
9
|
-
/** @typedef {readonly string[]} ByteMap */
|
|
10
|
-
|
|
11
19
|
/**
|
|
12
20
|
* @typedef {{
|
|
13
|
-
* readonly[state in string]:
|
|
21
|
+
* readonly[state in string]: rangeMap.RangeMapArray<string>
|
|
14
22
|
* }} Dfa
|
|
15
23
|
*/
|
|
16
24
|
|
|
25
|
+
const stringifyIdentity = stringify(identity)
|
|
26
|
+
|
|
27
|
+
/** @type {rangeMap.Operators<sortedSet.SortedSet<string>>} */
|
|
28
|
+
const mergeOp = { union: union(unsafeCmp), equal: equal(strictEqual) }
|
|
29
|
+
|
|
30
|
+
/** @type {(s: string) => (set: sortedSet.SortedSet<string>) => boolean} */
|
|
31
|
+
const hasState = s => set => !isEmpty(intersect(unsafeCmp)([s])(set))
|
|
32
|
+
|
|
33
|
+
/** @type {(set: sortedSet.SortedSet<string>) => operator.Fold<Rule, rangeMap.RangeMap<sortedSet.SortedSet<string>>>} */
|
|
34
|
+
const foldOp = set => ([ruleIn, bs, ruleOut]) => rm => {
|
|
35
|
+
if (hasState(ruleIn)(set)) { return merge(mergeOp)(rm)(toRangeMap(bs)(ruleOut)) }
|
|
36
|
+
return rm
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** @type {operator.Scan<rangeMap.Entry<sortedSet.SortedSet<string>>, rangeMap.Entry<string>>} */
|
|
40
|
+
const stringifyOp = ([sortedSet, max]) => [[stringifyIdentity(sortedSet), max], stringifyOp]
|
|
41
|
+
|
|
42
|
+
const scanStringify = scan(stringifyOp)
|
|
43
|
+
|
|
44
|
+
/** @type {operator.Scan<rangeMap.Entry<sortedSet.SortedSet<string>>, sortedSet.SortedSet<string>>} */
|
|
45
|
+
const fetchOp = ([item, _]) => [item, fetchOp]
|
|
46
|
+
|
|
47
|
+
const scanFetch = scan(fetchOp)
|
|
48
|
+
|
|
49
|
+
/** @type {(grammar: Grammar) => operator.Fold<sortedSet.SortedSet<string>, Dfa>} */
|
|
50
|
+
const addEntry = grammar => set => dfa => {
|
|
51
|
+
const s = stringifyIdentity(set)
|
|
52
|
+
if (s in dfa) { return dfa }
|
|
53
|
+
const setMap = fold(foldOp(set))(undefined)(grammar)
|
|
54
|
+
const stringMap = toArray(scanStringify(setMap))
|
|
55
|
+
const newDfa = { ...dfa, [s]: stringMap }
|
|
56
|
+
const newStates = scanFetch(setMap)
|
|
57
|
+
return fold(addEntry(grammar))(newDfa)(newStates)
|
|
58
|
+
}
|
|
59
|
+
|
|
17
60
|
/** @type {(grammar: Grammar) => Dfa} */
|
|
18
|
-
const dfa = grammar =>
|
|
61
|
+
const dfa = grammar => addEntry(grammar)([''])({})
|
|
19
62
|
|
|
20
63
|
module.exports = {
|
|
21
64
|
/** @readonly */
|
package/fsm/test.f.cjs
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
1
1
|
const _ = require('./module.f.cjs')
|
|
2
|
+
const byteSet = require('../types/byte_set/module.f.cjs')
|
|
3
|
+
const { sort, fromEntries } = require('../types/object/module.f.cjs')
|
|
4
|
+
const json = require('../json/module.f.cjs')
|
|
5
|
+
const { identity } = require('../types/function/module.f.cjs')
|
|
6
|
+
|
|
7
|
+
/** @type {(c: string) => number} */
|
|
8
|
+
const toCharCode = c => c.charCodeAt(0)
|
|
2
9
|
|
|
3
10
|
module.exports = {
|
|
11
|
+
dfa: () => {
|
|
12
|
+
const lowercaseAlpha = byteSet.range([toCharCode('a'), toCharCode('z')])
|
|
13
|
+
const uppercaseAlpha = byteSet.range([toCharCode('A'), toCharCode('Z')])
|
|
14
|
+
const alpha = byteSet.union(lowercaseAlpha)(uppercaseAlpha)
|
|
15
|
+
const idSymbol = byteSet.union(byteSet.one(toCharCode('_')))(byteSet.one(toCharCode('$')))
|
|
16
|
+
const idBegin = byteSet.union(alpha)(idSymbol)
|
|
17
|
+
const digit = byteSet.range([toCharCode('0'), toCharCode('9')])
|
|
18
|
+
const idNext = byteSet.union(idBegin)(digit)
|
|
19
|
+
const dot = byteSet.one(toCharCode('.'))
|
|
20
|
+
|
|
21
|
+
/** @type {_.Grammar} */
|
|
22
|
+
const grammar = [
|
|
23
|
+
['', digit, 'int'],
|
|
24
|
+
['int', digit, 'int'],
|
|
25
|
+
['', digit, 'floatBegin'],
|
|
26
|
+
['floatBegin', digit, 'floatBegin'],
|
|
27
|
+
['floatBegin', dot, 'floatDot'],
|
|
28
|
+
['floatDot', digit, 'float'],
|
|
29
|
+
['float', digit, 'float'],
|
|
30
|
+
['', idBegin, 'id'],
|
|
31
|
+
['id', idNext, 'id']
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const dfa = _.dfa(grammar)
|
|
35
|
+
const entries = Object.entries(dfa)
|
|
36
|
+
const sortedEntries = sort(entries)
|
|
37
|
+
const obj = fromEntries(sortedEntries)
|
|
38
|
+
const result = json.stringify(identity)(obj)
|
|
39
|
+
|
|
40
|
+
const expectedObj = {
|
|
41
|
+
'[""]': [
|
|
42
|
+
[ '[]', 35 ],
|
|
43
|
+
[ '["id"]', 36 ],
|
|
44
|
+
[ '[]', 47 ],
|
|
45
|
+
[ '["floatBegin","int"]', 57 ],
|
|
46
|
+
[ '[]', 64 ],
|
|
47
|
+
[ '["id"]', 90 ],
|
|
48
|
+
[ '[]', 94 ],
|
|
49
|
+
[ '["id"]', 95 ],
|
|
50
|
+
[ '[]', 96 ],
|
|
51
|
+
[ '["id"]', 122 ]
|
|
52
|
+
],
|
|
53
|
+
'["float"]': [ [ '[]', 47 ], [ '["float"]', 57 ] ],
|
|
54
|
+
'["floatBegin","int"]': [
|
|
55
|
+
[ '[]', 45 ],
|
|
56
|
+
[ '["floatDot"]', 46 ],
|
|
57
|
+
[ '[]', 47 ],
|
|
58
|
+
[ '["floatBegin","int"]', 57 ]
|
|
59
|
+
],
|
|
60
|
+
'["floatDot"]': [ [ '[]', 47 ], [ '["float"]', 57 ] ],
|
|
61
|
+
'["id"]': [
|
|
62
|
+
[ '[]', 35 ],
|
|
63
|
+
[ '["id"]', 36 ],
|
|
64
|
+
[ '[]', 47 ],
|
|
65
|
+
[ '["id"]', 57 ],
|
|
66
|
+
[ '[]', 64 ],
|
|
67
|
+
[ '["id"]', 90 ],
|
|
68
|
+
[ '[]', 94 ],
|
|
69
|
+
[ '["id"]', 95 ],
|
|
70
|
+
[ '[]', 96 ],
|
|
71
|
+
[ '["id"]', 122 ]
|
|
72
|
+
],
|
|
73
|
+
'[]': []
|
|
74
|
+
};
|
|
75
|
+
const expectedResult = json.stringify(identity)(expectedObj)
|
|
4
76
|
|
|
77
|
+
if (result !== expectedResult) {throw result }
|
|
78
|
+
}
|
|
5
79
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const sortedList = require("../sorted_list/module.f.cjs")
|
|
2
2
|
const { genericMerge } = sortedList
|
|
3
3
|
const list = require("../list/module.f.cjs")
|
|
4
|
+
const { next } = list
|
|
4
5
|
const option = require("../option/module.f.cjs")
|
|
5
6
|
const { cmp } = require('../number/module.f.cjs')
|
|
6
7
|
const operator = require("../function/operator/module.f.cjs")
|
|
@@ -15,6 +16,11 @@ const operator = require("../function/operator/module.f.cjs")
|
|
|
15
16
|
* @typedef {sortedList.SortedList<Entry<T>>} RangeMap
|
|
16
17
|
*/
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @template T
|
|
21
|
+
* @typedef {readonly Entry<T>[]} RangeMapArray
|
|
22
|
+
*/
|
|
23
|
+
|
|
18
24
|
/**
|
|
19
25
|
* @template T
|
|
20
26
|
* @typedef {{
|
|
@@ -45,7 +51,7 @@ const reduceOp = union => equal => state => ([aItem, aMax]) => ([bItem, bMax])
|
|
|
45
51
|
/** @type {<T>(equal: operator.Equal<T>) => sortedList.TailReduce<Entry<T>, RangeState<T>>} */
|
|
46
52
|
const tailReduce = equal => state => tail => {
|
|
47
53
|
if (state === undefined) { return tail }
|
|
48
|
-
const tailResult =
|
|
54
|
+
const tailResult = next(tail)
|
|
49
55
|
if (tailResult === undefined) { return [state] }
|
|
50
56
|
if (equal(state[0])(tailResult.first[0])) { return tailResult }
|
|
51
57
|
return { first: state, tail: tailResult }
|
|
@@ -3,12 +3,18 @@ const list = require('../list/module.f.cjs')
|
|
|
3
3
|
const option = require('../option/module.f.cjs')
|
|
4
4
|
const { next } = list
|
|
5
5
|
const { identity } = require('../function/module.f.cjs')
|
|
6
|
+
const range = require('../range/module.f.cjs')
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @template T
|
|
9
10
|
* @typedef {list.List<T>} SortedList
|
|
10
11
|
*/
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @template T
|
|
15
|
+
* @typedef {readonly T[]} SortedArray
|
|
16
|
+
*/
|
|
17
|
+
|
|
12
18
|
/**
|
|
13
19
|
* @template T
|
|
14
20
|
* @typedef {(a: T) => (b: T) => compare.Sign} Cmp
|
|
@@ -78,9 +84,33 @@ const cmpReduce = cmp => () => a => b => {
|
|
|
78
84
|
/** @type {() => <T>(tail: list.List<T>) => list.List<T>} */
|
|
79
85
|
const mergeTail = () => identity
|
|
80
86
|
|
|
87
|
+
/** @type {<T>(cmp: Cmp<T>) => (value: T) => (array: SortedArray<T>) => T|undefined} */
|
|
88
|
+
const find = cmp => value => array => {
|
|
89
|
+
let b = 0
|
|
90
|
+
let e = array.length - 1
|
|
91
|
+
while (true) {
|
|
92
|
+
if (e - b < 0) return undefined
|
|
93
|
+
const mid = b + (e - b >> 1)
|
|
94
|
+
const sign = cmp(value)(array[mid])
|
|
95
|
+
switch(sign) {
|
|
96
|
+
case -1: {
|
|
97
|
+
e = mid - 1
|
|
98
|
+
break
|
|
99
|
+
}
|
|
100
|
+
case 0: { return value }
|
|
101
|
+
case 1: {
|
|
102
|
+
b = mid + 1
|
|
103
|
+
break
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
81
109
|
module.exports = {
|
|
82
110
|
/** @readonly */
|
|
83
111
|
merge,
|
|
84
112
|
/** @readonly */
|
|
85
|
-
genericMerge
|
|
113
|
+
genericMerge,
|
|
114
|
+
/** @readonly */
|
|
115
|
+
find
|
|
86
116
|
}
|
|
@@ -29,5 +29,23 @@ module.exports = {
|
|
|
29
29
|
const len = length(result)
|
|
30
30
|
if (len != n) { throw result }
|
|
31
31
|
}
|
|
32
|
+
],
|
|
33
|
+
find: [
|
|
34
|
+
() => {
|
|
35
|
+
const result = _.find(unsafeCmp)(0)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
36
|
+
if (result !== 0) { throw result }
|
|
37
|
+
},
|
|
38
|
+
() => {
|
|
39
|
+
const result = _.find(unsafeCmp)(3)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
40
|
+
if (result !== undefined) { throw result }
|
|
41
|
+
},
|
|
42
|
+
() => {
|
|
43
|
+
const result = _.find(unsafeCmp)(77)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
44
|
+
if (result !== undefined) { throw result }
|
|
45
|
+
},
|
|
46
|
+
() => {
|
|
47
|
+
const result = _.find(unsafeCmp)(80)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
48
|
+
if (result !== 80) { throw result }
|
|
49
|
+
}
|
|
32
50
|
]
|
|
33
51
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
const compare = require("../function/compare/module.f.cjs")
|
|
2
2
|
const { toArray } = require("../list/module.f.cjs")
|
|
3
3
|
const sortedList = require("../sorted_list/module.f.cjs")
|
|
4
|
-
const { merge, genericMerge } = sortedList
|
|
5
|
-
const list = require("../list/module.f.cjs")
|
|
6
|
-
const option = require("../option/module.f.cjs")
|
|
4
|
+
const { merge, genericMerge, find } = sortedList
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* @template T
|
|
@@ -34,9 +32,14 @@ const intersectReduce = cmp => state => a => b => {
|
|
|
34
32
|
|
|
35
33
|
const intersectTail = () => () => undefined
|
|
36
34
|
|
|
35
|
+
/** @type {<T>(cmp: Cmp<T>) => (value: T) => (set: SortedSet<T>) => boolean} */
|
|
36
|
+
const has = cmp => value => set => find(cmp)(value)(set) === value
|
|
37
|
+
|
|
37
38
|
module.exports = {
|
|
38
39
|
/** @readonly */
|
|
39
40
|
union,
|
|
40
41
|
/** @readonly */
|
|
41
|
-
intersect
|
|
42
|
+
intersect,
|
|
43
|
+
/** @readonly */
|
|
44
|
+
has
|
|
42
45
|
}
|
|
@@ -40,5 +40,23 @@ module.exports = {
|
|
|
40
40
|
const result = stringify(toArray(_.intersect(unsafeCmp)([1, 2, 3])([])))
|
|
41
41
|
if (result !== '[]') { throw result }
|
|
42
42
|
}
|
|
43
|
+
],
|
|
44
|
+
has: [
|
|
45
|
+
() => {
|
|
46
|
+
const result = _.has(unsafeCmp)(0)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
47
|
+
if (!result) { throw result }
|
|
48
|
+
},
|
|
49
|
+
() => {
|
|
50
|
+
const result = _.has(unsafeCmp)(3)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
51
|
+
if (result) { throw result }
|
|
52
|
+
},
|
|
53
|
+
() => {
|
|
54
|
+
const result = _.has(unsafeCmp)(77)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
55
|
+
if (result) { throw result }
|
|
56
|
+
},
|
|
57
|
+
() => {
|
|
58
|
+
const result = _.has(unsafeCmp)(80)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
59
|
+
if (!result) { throw result }
|
|
60
|
+
}
|
|
43
61
|
]
|
|
44
62
|
}
|