functionalscript 0.0.475 → 0.0.477

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/com/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # COM (Component Object Model)
2
2
 
3
- Basic Types: `f32`, `f64`, `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `usize`, `isize`, `bool`, ``.
3
+ Basic Types: `f32`, `f64`, `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `usize`, `isize`, `bool`, ``.
@@ -0,0 +1,28 @@
1
+ # Proposals For NanoCOM
2
+
3
+ ## Pointer Types
4
+
5
+ - By ownership
6
+ - direct reference/pointer. `&I`
7
+ - cloneable wrapper. For example, `ref<I>`.
8
+ - By nullability
9
+ - non-nullable, a reference. For example, `ref<I>`.
10
+ - nullable, a pointer. For example, `ptr<I>`.
11
+ - By mutability
12
+ - immutable. Multithreaded, with an atomic counter. The object can be mutable with synchronization mechanisms.
13
+ - mutable. Single-threaded. With a simple counter and mutable.
14
+ - By value
15
+ - interface. All functions are virtual. For example add_ref/release
16
+ - implementation. Functions can be called directly, including add_ref/release.
17
+ ```rust
18
+ trait IUnknown {
19
+ fn add_ref(self);
20
+ fn release(self);
21
+ fn query_interface<I>(self) -> ptr<I>;
22
+ }
23
+ // examples
24
+ impl IUnknown for &IImmutableInterface { ... }
25
+ impl IUnknown for &mut IMutableInterface { ... }
26
+ impl IUnknown for &IImmutableInterfaceImplementation { ... }
27
+ impl IUnknown for &mut IMutableInterfaceImplementation { ... }
28
+ ```
@@ -0,0 +1,4 @@
1
+ const ascii = require('../text/ascii/module.f.cjs')
2
+
3
+ module.exports = {
4
+ }
package/fsc/test.f.cjs ADDED
@@ -0,0 +1,6 @@
1
+ const _ = require('./module.f.cjs')
2
+
3
+ module.exports = {
4
+ a: () => {
5
+ }
6
+ }
package/fsm/module.f.cjs CHANGED
@@ -85,11 +85,10 @@ const initialStateStringify = stringifyIdentity(initialState)
85
85
  /** @type {(grammar: Grammar) => Dfa} */
86
86
  const dfa = grammar => addEntry(grammar)(initialState)({})
87
87
 
88
+ const get = rangeMap.get(emptyStateStringify)
89
+
88
90
  /** @type {(dfa: Dfa) => operator.Fold<number, string>} */
89
- const runOp = dfa => input => s => {
90
- const state = rangeMap.get(input)(dfa[s])
91
- return state === undefined ? emptyStateStringify : state
92
- }
91
+ const runOp = dfa => input => s => get(input)(dfa[s])
93
92
 
94
93
  /** @type {(dfa: Dfa) => (input: list.List<number>) => list.List<string>} */
95
94
  const run = dfa => input => foldScan(runOp(dfa))(initialStateStringify)(input)
package/html/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # HTML
2
+
3
+ |HTML |FunctionalScript DSL |
4
+ |--------------------------------------------|-------------------------------------------------|
5
+ |`<br>` |`['br']` |
6
+ |`<img src="https://example.com/image.jpg">` |`['img',{src:'https://example.com/image.jpg'}]` |
7
+ |`<a href="https://example.com/">Example</a>`|`['a',{href:'https://example.com/'},['Example']]`|
@@ -0,0 +1,49 @@
1
+ # JSON to HTML
2
+
3
+ ```json
4
+ {
5
+ "a": 34.5,
6
+ "b": true,
7
+ "c": [null]
8
+ }
9
+ ```
10
+
11
+ ```js
12
+ ['pre',
13
+ [
14
+ '\n',
15
+ ['span',{class:'symbol'},['{']],
16
+ '\n ',
17
+ ['span',{class:'string'},['"a"']],
18
+ ['span',{class:'symbol'},[':']],
19
+ ' ',
20
+ ['span',{class:'number'},['34.5']],
21
+ ['span',{class:'symbol'},[',']],
22
+ '\n ',
23
+ ['span',{class:'string'},['"b"']],
24
+ ['span',{class:'symbol'},[':']],
25
+ ' ',
26
+ ['span',{class:'bool'},['true']],
27
+ ['span',{class:'symbol'},[',']],
28
+ '\n ',
29
+ ['span',{class:'string'},['"c"']],
30
+ ['span',{class:'symbol'},[':']],
31
+ ' ',
32
+ ['span',{class:'symbol'},['[']],
33
+ ['span',{class:'null'},['null']],
34
+ ['span',{class:'symbol'},[']']],
35
+ '\n ',
36
+ ['span',{class:'symbol'},['}']],
37
+ '\n'
38
+ ]
39
+ ]
40
+ ```
41
+
42
+ ```html
43
+ <pre>
44
+ <span class="symbol">{</span>
45
+ <span class="string">"a"<span><span class="symbol">:</span> <span class="number">34.5</span><span class="symbol">,<span>
46
+ <span class="string">"b"<span><span class="symbol">:</span> <span class="bool">true</span><span class="symbol">,<span>
47
+ <span class="string">"c"<span><span class="symbol">:</span> <span class="symbol">[</span><span class="null">null</span><span class="symbol">]</span>
48
+ </pre>
49
+ ```
@@ -1,9 +1,49 @@
1
1
  const operator = require('../../types/function/operator/module.f.cjs')
2
2
  const list = require('../../types/list/module.f.cjs')
3
- const range = require('../../types/range/module.f.cjs')
4
- const { stateScan, flat, concat } = list
5
- const { contains } = range
3
+ const { contains } = require('../../types/range/module.f.cjs')
4
+ const { stateScan, flat } = list
6
5
  const { fromCharCode } = String
6
+ const {
7
+ range,
8
+ //
9
+ backspace,
10
+ ht,
11
+ lf,
12
+ ff,
13
+ cr,
14
+ //
15
+ space,
16
+ quotationMark,
17
+ plusSign,
18
+ comma,
19
+ hyphenMinus,
20
+ fullStop,
21
+ solidus,
22
+ //
23
+ digitRange,
24
+ digit0,
25
+ colon,
26
+ //
27
+ latinCapitalLetterA,
28
+ latinCapitalLetterE,
29
+ //
30
+ leftSquareBracket,
31
+ reverseSolidus,
32
+ rightSquareBracket,
33
+ //
34
+ latinSmallLetterRange,
35
+ latinSmallLetterA,
36
+ latinSmallLetterB,
37
+ latinSmallLetterE,
38
+ latinSmallLetterF,
39
+ latinSmallLetterN,
40
+ latinSmallLetterR,
41
+ latinSmallLetterT,
42
+ latinSmallLetterU,
43
+ //
44
+ leftCurlyBracket,
45
+ rightCurlyBracket
46
+ } = require('../../text/ascii/module.f.cjs')
7
47
 
8
48
  /**
9
49
  * @typedef {{
@@ -32,50 +72,11 @@ const { fromCharCode } = String
32
72
  * } JsonToken
33
73
  */
34
74
 
35
- const leftBrace = 0x7b
36
- const rightBrace = 0x7d
37
- const colon = 0x3a
38
- const comma = 0x2c
39
- const leftBracket = 0x5b
40
- const rightBracket = 0x5d
41
-
42
- const quotationMark = 0x22
43
- const digit0 = 0x30
44
- const digit1 = 0x31
45
- const digit9 = 0x39
46
- const signPlus = 0x2b
47
- const signMinus = 0x2d
48
- const decimalPoint = 0x2e
49
-
50
- const horizontalTab = 0x09
51
- const newLine = 0x0a
52
- const carriageReturn = 0x0d
53
- const space = 0x20
54
-
55
- const backslash = 0x5c
56
- const slash = 0x2f
57
- const backspace = 0x08
58
- const formfeed = 0x0c
59
-
60
- const capitalLetterA = 0x41
61
- const capitalLetterE = 0x45
62
- const capitalLetterF = 0x46
63
-
64
- const letterA = 0x61
65
- const letterB = 0x62
66
- const letterE = 0x65
67
- const letterF = 0x66
68
- const letterN = 0x6e
69
- const letterR = 0x72
70
- const letterT = 0x74
71
- const letterU = 0x75
72
- const letterZ = 0x7a
73
-
74
- const containsDigit = contains([digit0, digit9])
75
- const containsDigitOneNine = contains([digit1, digit9])
76
- const containsSmallAF = contains([letterA, letterF])
77
- const containsCapitalAF = contains([capitalLetterA, capitalLetterF])
78
- const containsSmallLetter = contains([letterA, letterZ])
75
+ const containsDigit = contains(digitRange)
76
+ const containsDigitOneNine = contains(range('19'))
77
+ const containsSmallAF = contains(range('af'))
78
+ const containsCapitalAF = contains(range('AF'))
79
+ const containsSmallLetter = contains(latinSmallLetterRange)
79
80
 
80
81
  /**
81
82
  * @typedef {|
@@ -141,22 +142,22 @@ const initialStateOp = initialState => input => {
141
142
  return [undefined, initialState]
142
143
  }
143
144
  switch (input) {
144
- case leftBrace: return [[{ kind: '{' }], initialState]
145
- case rightBrace: return [[{ kind: '}' }], initialState]
145
+ case leftCurlyBracket: return [[{ kind: '{' }], initialState]
146
+ case rightCurlyBracket: return [[{ kind: '}' }], initialState]
146
147
  case colon: return [[{ kind: ':' }], initialState]
147
148
  case comma: return [[{ kind: ',' }], initialState]
148
- case leftBracket: return [[{ kind: '[' }], initialState]
149
- case rightBracket: return [[{ kind: ']' }], initialState]
149
+ case leftSquareBracket: return [[{ kind: '[' }], initialState]
150
+ case rightSquareBracket: return [[{ kind: ']' }], initialState]
150
151
  case quotationMark: return [undefined, { kind: 'string', value: '' }]
151
152
  case digit0: return [undefined, { kind: 'number', value: fromCharCode(input), numberKind: '0' }]
152
- case signMinus: return [undefined, { kind: 'number', value: fromCharCode(input), numberKind: '-' }]
153
+ case hyphenMinus: return [undefined, { kind: 'number', value: fromCharCode(input), numberKind: '-' }]
153
154
  default: return [[{ kind: 'error', message: 'unexpected character' }], initialState]
154
155
  }
155
156
  }
156
157
 
157
158
  /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
158
159
  const parseNumberStateOp = state => input => {
159
- if (input === decimalPoint) {
160
+ if (input === fullStop) {
160
161
  switch (state.numberKind) {
161
162
  case '0':
162
163
  case 'int': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: '.' }]
@@ -185,7 +186,7 @@ const parseNumberStateOp = state => input => {
185
186
  default: return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: state.numberKind }]
186
187
  }
187
188
  }
188
- if (input === letterE || input === capitalLetterE) {
189
+ if (input === latinSmallLetterE || input === latinCapitalLetterE) {
189
190
  switch (state.numberKind) {
190
191
  case '0':
191
192
  case 'int':
@@ -193,13 +194,13 @@ const parseNumberStateOp = state => input => {
193
194
  default: return tokenizeOp({ kind: 'invalidNumber' })(input)
194
195
  }
195
196
  }
196
- if (input === signMinus) {
197
+ if (input === hyphenMinus) {
197
198
  switch (state.numberKind) {
198
199
  case 'e': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'e-' }]
199
200
  default: return tokenizeOp({ kind: 'invalidNumber' })(input)
200
201
  }
201
202
  }
202
- if (input === signPlus) {
203
+ if (input === plusSign) {
203
204
  switch (state.numberKind) {
204
205
  case 'e': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'e+' }]
205
206
  default: return tokenizeOp({ kind: 'invalidNumber' })(input)
@@ -234,10 +235,10 @@ const isTerminalForNumber = char => {
234
235
  switch (char) {
235
236
  case quotationMark:
236
237
  case comma:
237
- case leftBrace:
238
- case rightBrace:
239
- case leftBracket:
240
- case rightBracket:
238
+ case leftCurlyBracket:
239
+ case rightCurlyBracket:
240
+ case leftSquareBracket:
241
+ case rightSquareBracket:
241
242
  case colon: return true
242
243
  default: return false
243
244
  }
@@ -246,16 +247,16 @@ const isTerminalForNumber = char => {
246
247
  /** @type {(char: number) => boolean} */
247
248
  const isWhiteSpace = char => {
248
249
  switch (char) {
249
- case horizontalTab:
250
- case newLine:
251
- case carriageReturn:
250
+ case ht:
251
+ case lf:
252
+ case cr:
252
253
  case space: return true
253
254
  default: return false
254
255
  }
255
256
  }
256
257
 
257
258
  /** @type {(state: InvalidNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
258
- const invalidNumberStateOp = state => input => {
259
+ const invalidNumberStateOp = () => input => {
259
260
  if (isTerminalForNumber(input)) {
260
261
  const next = tokenizeOp({ kind: 'initial' })(input)
261
262
  return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
@@ -267,7 +268,7 @@ const invalidNumberStateOp = state => input => {
267
268
  const parseStringStateOp = state => input => {
268
269
  switch (input) {
269
270
  case quotationMark: return [[{ kind: 'string', value: state.value }], { kind: 'initial' }]
270
- case backslash: return [undefined, { kind: 'escapeChar', value: state.value }]
271
+ case reverseSolidus: return [undefined, { kind: 'escapeChar', value: state.value }]
271
272
  default: return [undefined, { kind: 'string', value: appendChar(state.value)(input) }]
272
273
  }
273
274
  }
@@ -276,14 +277,14 @@ const parseStringStateOp = state => input => {
276
277
  const parseEscapeCharStateOp = state => input => {
277
278
  switch (input) {
278
279
  case quotationMark:
279
- case backslash:
280
- case slash: return [undefined, { kind: 'string', value: appendChar(state.value)(input) }]
281
- case letterB: return [undefined, { kind: 'string', value: appendChar(state.value)(backspace) }]
282
- case letterF: return [undefined, { kind: 'string', value: appendChar(state.value)(formfeed) }]
283
- case letterN: return [undefined, { kind: 'string', value: appendChar(state.value)(newLine) }]
284
- case letterR: return [undefined, { kind: 'string', value: appendChar(state.value)(carriageReturn) }]
285
- case letterT: return [undefined, { kind: 'string', value: appendChar(state.value)(horizontalTab) }]
286
- case letterU: return [undefined, { kind: 'unicodeChar', value: state.value, unicode: 0, hexIndex: 0 }]
280
+ case reverseSolidus:
281
+ case solidus: return [undefined, { kind: 'string', value: appendChar(state.value)(input) }]
282
+ case latinSmallLetterB: return [undefined, { kind: 'string', value: appendChar(state.value)(backspace) }]
283
+ case latinSmallLetterF: return [undefined, { kind: 'string', value: appendChar(state.value)(ff) }]
284
+ case latinSmallLetterN: return [undefined, { kind: 'string', value: appendChar(state.value)(lf) }]
285
+ case latinSmallLetterR: return [undefined, { kind: 'string', value: appendChar(state.value)(cr) }]
286
+ case latinSmallLetterT: return [undefined, { kind: 'string', value: appendChar(state.value)(ht) }]
287
+ case latinSmallLetterU: return [undefined, { kind: 'unicodeChar', value: state.value, unicode: 0, hexIndex: 0 }]
287
288
  default: {
288
289
  const next = tokenizeOp({ kind: 'string', value: state.value })(input)
289
290
  return [{ first: { kind: 'error', message: 'unescaped character' }, tail: next[0] }, next[1]]
@@ -294,8 +295,8 @@ const parseEscapeCharStateOp = state => input => {
294
295
  /** @type {(hex: number) => number|undefined} */
295
296
  const hexDigitToNumber = hex => {
296
297
  if (containsDigit(hex)) { return hex - digit0 }
297
- if (containsCapitalAF(hex)) { return hex - capitalLetterA + 10 }
298
- if (containsSmallAF(hex)) { return hex - letterA + 10 }
298
+ if (containsCapitalAF(hex)) { return hex - latinCapitalLetterA + 10 }
299
+ if (containsSmallAF(hex)) { return hex - latinSmallLetterA + 10 }
299
300
  }
300
301
 
301
302
  /** @type {(state: ParseUnicodeCharState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.475",
3
+ "version": "0.0.477",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "module.f.cjs",
6
6
  "scripts": {
@@ -0,0 +1,222 @@
1
+ const _range = require('../../types/range/module.f.cjs')
2
+
3
+ /** @type {(s: string) => (i: number) => number} */
4
+ const at = s => i => {
5
+ const r = s.codePointAt(i)
6
+ if (r === undefined) { throw s }
7
+ return r
8
+ }
9
+
10
+ /** @type {(s: string) => number} */
11
+ const one = s => at(s)(0)
12
+
13
+ /** @type {(s: string) => _range.Range} */
14
+ const range = s => {
15
+ const f = at(s)
16
+ return [f(0), f(1)]
17
+ }
18
+
19
+ module.exports = {
20
+ /** @readonly */
21
+ one,
22
+ /** @readonly */
23
+ range,
24
+
25
+ // 0x00..
26
+
27
+ /** @readonly 0x08 */
28
+ backspace: one('\b'),
29
+
30
+ /** @readonly 0x09 */
31
+ ht: one('\t'),
32
+
33
+ /** @readonly 0x0A */
34
+ lf: one('\n'),
35
+
36
+ /** @readonly 0x0C */
37
+ ff: one('\f'),
38
+ /** @readonly 0x0D */
39
+ cr: one('\r'),
40
+
41
+ // 0x20..
42
+
43
+ /** @readonly 0x20 */
44
+ space: one(' '),
45
+
46
+ /** @readonly 0x21 */
47
+ exclamationMark: one('!'),
48
+
49
+ /** @readonly 0x22 */
50
+ quotationMark: one('"'),
51
+
52
+ /** @readonly 0x23 */
53
+ numberSign: one('#'),
54
+
55
+ /** @readonly 0x24 */
56
+ dollarSign: one('$'),
57
+
58
+ /** @readonly 0x25 */
59
+ percentSign: one('%'),
60
+
61
+ /** @readonly 0x26 */
62
+ ampersand: one('&'),
63
+
64
+ /** @readonly 0x27 */
65
+ apostrophe: one("'"),
66
+
67
+ /** @readonly 0x28 */
68
+ leftParenthesis: one('('),
69
+
70
+ /** @readonly 0x29 */
71
+ rightParenthesis: one(')'),
72
+
73
+ /** @readonly 0x2A */
74
+ asterisk: one('*'),
75
+
76
+ /** @readonly 0x2B */
77
+ plusSign: one('+'),
78
+
79
+ /** @readonly 0x2C */
80
+ comma: one(','),
81
+
82
+ /** @readonly 0x2D */
83
+ hyphenMinus: one('-'),
84
+
85
+ /** @readonly 0x2E */
86
+ fullStop: one('.'),
87
+
88
+ /** @readonly 0x2F */
89
+ solidus: one('/'),
90
+
91
+ // 0x30..
92
+
93
+ /** @readonly 0x30..0x39 */
94
+ digitRange: range('09'),
95
+
96
+ /** @readonly 0x30 */
97
+ digit0: one('0'),
98
+
99
+ /** @readonly 0x31 */
100
+ digit1: one('1'),
101
+
102
+ /** @readonly 0x32 */
103
+ digit2: one('2'),
104
+
105
+ /** @readonly 0x33 */
106
+ digit3: one('3'),
107
+
108
+ /** @readonly 0x34 */
109
+ digit4: one('4'),
110
+
111
+ /** @readonly 0x35 */
112
+ digit5: one('5'),
113
+
114
+ /** @readonly 0x36 */
115
+ digit6: one('6'),
116
+
117
+ /** @readonly 0x37 */
118
+ digit7: one('7'),
119
+
120
+ /** @readonly 0x38 */
121
+ digit8: one('8'),
122
+
123
+ /** @readonly 0x39 */
124
+ digit9: one('9'),
125
+
126
+ /** @readonly 0x3A */
127
+ colon: one(':'),
128
+
129
+ /** @readonly 0x3B */
130
+ semicolon: one(';'),
131
+
132
+ /** @readonly 0x3C */
133
+ lessThanSign: one('<'),
134
+
135
+ /** @readonly 0x3D */
136
+ equalsSign: one('='),
137
+
138
+ /** @readonly 0x3E */
139
+ greaterThanSign: one('>'),
140
+
141
+ /** @readonly 0x3F */
142
+ questionMark: one('?'),
143
+
144
+ // 0x40..
145
+
146
+ /** @readonly 0x40 */
147
+ commercialAt: one('@'),
148
+
149
+ /** @readonly 0x41..0x5A */
150
+ latinCapitalLetterRange: range('AZ'),
151
+
152
+ /** @readonly 0x41 */
153
+ latinCapitalLetterA: one('A'),
154
+
155
+ /** @readonly 0x45 */
156
+ latinCapitalLetterE: one('E'),
157
+
158
+ /** @readonly 0x46 */
159
+ latinCapitalLetterF: one('F'),
160
+
161
+ /** @readonly 0x5B */
162
+ leftSquareBracket: one('['),
163
+
164
+ /** @readonly 0x5C */
165
+ reverseSolidus: one('\\'),
166
+
167
+ /** @readonly 0x5D */
168
+ rightSquareBracket: one(']'),
169
+
170
+ /** @readonly 0x5E */
171
+ circumflexAccent: one('^'),
172
+
173
+ /** @readonly 0x5F */
174
+ lowLine: one('_'),
175
+
176
+ // 0x60..
177
+
178
+ /** @readonly 0x60 */
179
+ graveAccent: one('`'),
180
+
181
+ /** @readonly 0x61..0x7A */
182
+ latinSmallLetterRange: range('az'),
183
+
184
+ /** @readonly 0x61 */
185
+ latinSmallLetterA: one('a'),
186
+
187
+ /** @readonly 0x62 */
188
+ latinSmallLetterB: one('b'),
189
+
190
+ /** @readonly 0x65 */
191
+ latinSmallLetterE: one('e'),
192
+
193
+ /** @readonly 0x66 */
194
+ latinSmallLetterF: one('f'),
195
+
196
+ /** @readonly 0x6E */
197
+ latinSmallLetterN: one('n'),
198
+
199
+ /** @readonly 0x72 */
200
+ latinSmallLetterR: one('r'),
201
+
202
+ /** @readonly 0x74 */
203
+ latinSmallLetterT: one('t'),
204
+
205
+ /** @readonly 0x75 */
206
+ latinSmallLetterU: one('u'),
207
+
208
+ /** @readonly 0x7A */
209
+ latinSmallLetterZ: one('z'),
210
+
211
+ /** @readonly 0x7B */
212
+ leftCurlyBracket: one('{'),
213
+
214
+ /** @readonly 0x7C */
215
+ verticalLine: one('|'),
216
+
217
+ /** @readonly 0x7D */
218
+ rightCurlyBracket: one('}'),
219
+
220
+ /** @readonly 0x7E */
221
+ tilde: one('~'),
222
+ }
@@ -5,6 +5,7 @@ const { next } = list
5
5
  const option = require("../option/module.f.cjs")
6
6
  const { cmp } = require('../number/module.f.cjs')
7
7
  const operator = require("../function/operator/module.f.cjs")
8
+ const _range = require('../range/module.f.cjs')
8
9
 
9
10
  /**
10
11
  * @template T
@@ -60,32 +61,31 @@ const tailReduce = equal => state => tail => {
60
61
  /** @type {<T>(op: Operators<T>) => RangeMerge<T>} */
61
62
  const merge = ({union, equal}) => genericMerge({reduceOp: reduceOp(union)(equal), tailReduce: tailReduce(equal)})(undefined)
62
63
 
63
- /** @type {<T>(value: number) => (rm: RangeMapArray<T>) => T|undefined} */
64
- const get = value => rm => {
64
+ /** @type {<T>(def: T) => (value: number) => (rm: RangeMapArray<T>) => T} */
65
+ const get = def => value => rm => {
66
+ const len = rm.length
65
67
  let b = 0
66
- let e = rm.length - 1
68
+ let e = len - 1
67
69
  while (true) {
68
- if (b >= rm.length) return undefined
69
- if (e - b < 0) return rm[b][0]
70
+ if (b >= len) { return def }
71
+ if (e - b < 0) { return rm[b][0] }
70
72
  const mid = b + (e - b >> 1)
71
- const sign = cmp(value)(rm[mid][1])
72
- switch(sign) {
73
- case -1: {
74
- e = mid - 1
75
- break
76
- }
77
- case 0: { return rm[mid][0] }
78
- case 1: {
79
- b = mid + 1
80
- break
81
- }
73
+ if (value <= rm[mid][1]) {
74
+ e = mid - 1
75
+ } else {
76
+ b = mid + 1
82
77
  }
83
78
  }
84
79
  }
85
80
 
81
+ /** @type {<T>(def: T) => (r: _range.Range) => (value: T) => RangeMapArray<T>} */
82
+ const fromRange = def => ([a, b]) => v => [[def, a - 1], [v, b]]
83
+
86
84
  module.exports = {
87
85
  /** @readonly */
88
86
  merge,
89
87
  /** @readonly */
90
- get
88
+ get,
89
+ /** @readonly */
90
+ fromRange,
91
91
  }
@@ -78,54 +78,85 @@ module.exports = {
78
78
  if (result !== '[[["a"],1],[["a","b"],2],[["a"],5]]') { throw result }
79
79
  }
80
80
  ],
81
- get: [
82
- () => {
83
- /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
84
- const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
85
- const result = stringify(_.get(5)(rm))
86
- if (result !== '["a"]') { throw result }
87
- },
88
- () => {
89
- /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
90
- const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
91
- const result = stringify(_.get(10)(rm))
92
- if (result !== '["a"]') { throw result }
93
- },
94
- () => {
95
- /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
96
- const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
97
- const result = stringify(_.get(15)(rm))
98
- if (result !== '["b"]') { throw result }
99
- },
100
- () => {
101
- /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
102
- const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
103
- const result = stringify(_.get(20)(rm))
104
- if (result !== '["b"]') { throw result }
105
- },
106
- () => {
107
- /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
108
- const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
109
- const result = stringify(_.get(25)(rm))
110
- if (result !== '["c"]') { throw result }
111
- },
112
- () => {
113
- /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
114
- const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
115
- const result = stringify(_.get(30)(rm))
116
- if (result !== '["c"]') { throw result }
117
- },
118
- () => {
119
- /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
120
- const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
121
- const result = _.get(35)(rm)
122
- if (result !== undefined) { throw result }
123
- },
124
- () => {
125
- /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
126
- const rm = []
127
- const result = _.get(10)(rm)
128
- if (result !== undefined) { throw result }
129
- }
130
- ]
131
- }
81
+ get: () => {
82
+ /** @type {sortedSet.SortedSet<string>} */
83
+ const sortedSetEmpty = []
84
+ const get = _.get(sortedSetEmpty)
85
+ return [
86
+ () => {
87
+ /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
88
+ const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
89
+ const result = stringify(get(5)(rm))
90
+ if (result !== '["a"]') { throw result }
91
+ },
92
+ () => {
93
+ /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
94
+ const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
95
+ const result = stringify(get(10)(rm))
96
+ if (result !== '["a"]') { throw result }
97
+ },
98
+ () => {
99
+ /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
100
+ const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
101
+ const result = stringify(get(15)(rm))
102
+ if (result !== '["b"]') { throw result }
103
+ },
104
+ () => {
105
+ /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
106
+ const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
107
+ const result = stringify(get(20)(rm))
108
+ if (result !== '["b"]') { throw result }
109
+ },
110
+ () => {
111
+ /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
112
+ const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
113
+ const result = stringify(get(25)(rm))
114
+ if (result !== '["c"]') { throw result }
115
+ },
116
+ () => {
117
+ /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
118
+ const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
119
+ const result = stringify(get(30)(rm))
120
+ if (result !== '["c"]') { throw result }
121
+ },
122
+ () => {
123
+ /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
124
+ const rm = [[['a'], 10], [['b'], 20], [['c'], 30]]
125
+ const result = stringify(get(35)(rm))
126
+ if (result !== '[]') { throw result }
127
+ },
128
+ () => {
129
+ /** @type {_.RangeMapArray<sortedSet.SortedSet<string>>} */
130
+ const rm = []
131
+ const result = stringify(get(10)(rm))
132
+ if (result !== '[]') { throw result }
133
+ }
134
+ ]
135
+ },
136
+ fromRange: () => {
137
+ const def = -1
138
+ const rm = _.fromRange(def)([1, 7])(42)
139
+ return [
140
+ () => {
141
+ const result = _.get(def)(0)(rm)
142
+ if (result !== -1) { throw result }
143
+ },
144
+ () => {
145
+ const result = _.get(def)(1)(rm)
146
+ if (result !== 42) { throw result }
147
+ },
148
+ () => {
149
+ const result = _.get(def)(3)(rm)
150
+ if (result !== 42) { throw result }
151
+ },
152
+ () => {
153
+ const result = _.get(def)(7)(rm)
154
+ if (result !== 42) { throw result }
155
+ },
156
+ () => {
157
+ const result = _.get(def)(9)(rm)
158
+ if (result !== -1) { throw result }
159
+ },
160
+ ]
161
+ }
162
+ }