functionalscript 0.0.388 → 0.0.391
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/cpp/module.f.cjs +41 -31
- package/com/cs/module.f.cjs +60 -41
- package/com/types/module.f.cjs +6 -2
- package/commonjs/build/module.f.cjs +18 -13
- package/commonjs/package/dependencies/module.f.cjs +5 -2
- package/commonjs/package/module.f.cjs +4 -2
- package/commonjs/path/module.f.cjs +16 -14
- package/doc/vm.md +126 -118
- package/html/module.f.cjs +15 -9
- package/json/module.f.cjs +18 -11
- package/json/tokenizer/module.f.cjs +128 -164
- package/json/tokenizer/test.f.cjs +2 -1
- package/nodejs/version/module.f.cjs +4 -4
- package/package.json +1 -1
- package/sha2/module.f.cjs +29 -29
- package/text/encoding/module.f.cjs +24 -8
- package/text/encoding/test.f.cjs +14 -0
- package/text/module.f.cjs +2 -1
- package/types/array/module.f.cjs +2 -1
- package/types/btree/find/module.f.cjs +3 -2
- package/types/btree/remove/module.f.cjs +6 -5
- package/types/btree/set/module.f.cjs +9 -5
- package/types/list/module.f.cjs +39 -29
- package/types/list/test.f.cjs +1 -5
- package/types/map/module.f.cjs +11 -10
- package/types/object/module.f.cjs +9 -6
- package/types/object/test.html +9 -0
- package/types/result/module.cjs +3 -2
- package/types/stringset/module.f.cjs +12 -8
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const operator = require('../../types/function/operator/module.f.cjs')
|
|
2
2
|
const list = require('../../types/list/module.f.cjs')
|
|
3
3
|
const range = require('../../types/range/module.f.cjs')
|
|
4
|
+
const { stateScan, flat, concat } = list
|
|
5
|
+
const { contains } = range
|
|
6
|
+
const { fromCharCode } = String
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* @typedef {{
|
|
@@ -68,11 +71,11 @@ const letterT = 0x74
|
|
|
68
71
|
const letterU = 0x75
|
|
69
72
|
const letterZ = 0x7a
|
|
70
73
|
|
|
71
|
-
const containsDigit =
|
|
72
|
-
const containsDigitOneNine =
|
|
73
|
-
const containsSmallAF =
|
|
74
|
-
const containsCapitalAF =
|
|
75
|
-
const containsSmallLetter =
|
|
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])
|
|
76
79
|
|
|
77
80
|
/**
|
|
78
81
|
* @typedef {|
|
|
@@ -124,134 +127,111 @@ const containsSmallLetter = range.contains([letterA, letterZ])
|
|
|
124
127
|
/** @typedef {number|undefined} CharCodeOrEof */
|
|
125
128
|
|
|
126
129
|
/** @type {(old: string) => (input: number) => string} */
|
|
127
|
-
const appendChar = old => input => `${old}${
|
|
130
|
+
const appendChar = old => input => `${old}${fromCharCode(input)}`
|
|
128
131
|
|
|
129
132
|
/** @type {(state: InitialState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
130
|
-
const initialStateOp = initialState => input =>
|
|
131
|
-
{
|
|
132
|
-
|
|
133
|
-
{
|
|
134
|
-
return [undefined, { kind: 'number', value: String.fromCharCode(input), numberKind: 'int'}]
|
|
133
|
+
const initialStateOp = initialState => input => {
|
|
134
|
+
if (containsDigitOneNine(input)) {
|
|
135
|
+
return [undefined, { kind: 'number', value: fromCharCode(input), numberKind: 'int' }]
|
|
135
136
|
}
|
|
136
|
-
if (containsSmallLetter(input))
|
|
137
|
-
|
|
138
|
-
return [undefined, { kind: 'keyword', value: String.fromCharCode(input)}]
|
|
137
|
+
if (containsSmallLetter(input)) {
|
|
138
|
+
return [undefined, { kind: 'keyword', value: fromCharCode(input) }]
|
|
139
139
|
}
|
|
140
|
-
if (isWhiteSpace(input))
|
|
141
|
-
{
|
|
140
|
+
if (isWhiteSpace(input)) {
|
|
142
141
|
return [undefined, initialState]
|
|
143
142
|
}
|
|
144
|
-
switch(input)
|
|
145
|
-
|
|
146
|
-
case
|
|
147
|
-
case
|
|
148
|
-
case
|
|
149
|
-
case
|
|
150
|
-
case
|
|
151
|
-
case
|
|
152
|
-
case
|
|
153
|
-
case
|
|
154
|
-
|
|
155
|
-
default: return [[{kind: 'error', message: 'unexpected character'}], initialState]
|
|
143
|
+
switch (input) {
|
|
144
|
+
case leftBrace: return [[{ kind: '{' }], initialState]
|
|
145
|
+
case rightBrace: return [[{ kind: '}' }], initialState]
|
|
146
|
+
case colon: return [[{ kind: ':' }], initialState]
|
|
147
|
+
case comma: return [[{ kind: ',' }], initialState]
|
|
148
|
+
case leftBracket: return [[{ kind: '[' }], initialState]
|
|
149
|
+
case rightBracket: return [[{ kind: ']' }], initialState]
|
|
150
|
+
case quotationMark: return [undefined, { kind: 'string', value: '' }]
|
|
151
|
+
case digit0: return [undefined, { kind: 'number', value: fromCharCode(input), numberKind: '0' }]
|
|
152
|
+
case signMinus: return [undefined, { kind: 'number', value: fromCharCode(input), numberKind: '-' }]
|
|
153
|
+
default: return [[{ kind: 'error', message: 'unexpected character' }], initialState]
|
|
156
154
|
}
|
|
157
155
|
}
|
|
158
156
|
|
|
159
157
|
/** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
160
|
-
const parseNumberStateOp = state => input =>
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
-
{
|
|
164
|
-
switch (state.numberKind)
|
|
165
|
-
{
|
|
158
|
+
const parseNumberStateOp = state => input => {
|
|
159
|
+
if (input === decimalPoint) {
|
|
160
|
+
switch (state.numberKind) {
|
|
166
161
|
case '0':
|
|
167
|
-
case 'int': return [undefined, {kind: 'number', value: appendChar(state.value)(input), numberKind: '.'}]
|
|
168
|
-
default: return tokenizeOp({kind: 'invalidNumber'})(input)
|
|
162
|
+
case 'int': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: '.' }]
|
|
163
|
+
default: return tokenizeOp({ kind: 'invalidNumber' })(input)
|
|
169
164
|
}
|
|
170
165
|
}
|
|
171
|
-
if (input === digit0)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
case '
|
|
176
|
-
case '-': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: '0'}]
|
|
177
|
-
case '.': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'fractional'}]
|
|
166
|
+
if (input === digit0) {
|
|
167
|
+
switch (state.numberKind) {
|
|
168
|
+
case '0': return tokenizeOp({ kind: 'invalidNumber' })(input)
|
|
169
|
+
case '-': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: '0' }]
|
|
170
|
+
case '.': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'fractional' }]
|
|
178
171
|
case 'e':
|
|
179
172
|
case 'e+':
|
|
180
|
-
case 'e-': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'expDigits'}]
|
|
181
|
-
default: return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: state.numberKind}]
|
|
173
|
+
case 'e-': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'expDigits' }]
|
|
174
|
+
default: return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: state.numberKind }]
|
|
182
175
|
}
|
|
183
176
|
}
|
|
184
|
-
if (containsDigitOneNine(input))
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
case '
|
|
189
|
-
case '-': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'int'}]
|
|
190
|
-
case '.': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'fractional'}]
|
|
177
|
+
if (containsDigitOneNine(input)) {
|
|
178
|
+
switch (state.numberKind) {
|
|
179
|
+
case '0': return tokenizeOp({ kind: 'invalidNumber' })(input)
|
|
180
|
+
case '-': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'int' }]
|
|
181
|
+
case '.': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'fractional' }]
|
|
191
182
|
case 'e':
|
|
192
183
|
case 'e+':
|
|
193
|
-
case 'e-': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'expDigits'}]
|
|
194
|
-
default: return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: state.numberKind}]
|
|
184
|
+
case 'e-': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'expDigits' }]
|
|
185
|
+
default: return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: state.numberKind }]
|
|
195
186
|
}
|
|
196
187
|
}
|
|
197
|
-
if (input === letterE || input === capitalLetterE)
|
|
198
|
-
|
|
199
|
-
switch (state.numberKind)
|
|
200
|
-
{
|
|
188
|
+
if (input === letterE || input === capitalLetterE) {
|
|
189
|
+
switch (state.numberKind) {
|
|
201
190
|
case '0':
|
|
202
191
|
case 'int':
|
|
203
|
-
case 'fractional': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'e'}]
|
|
204
|
-
default: return tokenizeOp({kind: 'invalidNumber'})(input)
|
|
192
|
+
case 'fractional': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'e' }]
|
|
193
|
+
default: return tokenizeOp({ kind: 'invalidNumber' })(input)
|
|
205
194
|
}
|
|
206
195
|
}
|
|
207
|
-
if (input === signMinus)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
case 'e': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'e-'}]
|
|
212
|
-
default: return tokenizeOp({kind: 'invalidNumber'})(input)
|
|
196
|
+
if (input === signMinus) {
|
|
197
|
+
switch (state.numberKind) {
|
|
198
|
+
case 'e': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'e-' }]
|
|
199
|
+
default: return tokenizeOp({ kind: 'invalidNumber' })(input)
|
|
213
200
|
}
|
|
214
201
|
}
|
|
215
|
-
if (input === signPlus)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
case 'e': return [undefined, {kind:'number', value: appendChar(state.value)(input), numberKind: 'e+'}]
|
|
220
|
-
default: return tokenizeOp({kind: 'invalidNumber'})(input)
|
|
202
|
+
if (input === signPlus) {
|
|
203
|
+
switch (state.numberKind) {
|
|
204
|
+
case 'e': return [undefined, { kind: 'number', value: appendChar(state.value)(input), numberKind: 'e+' }]
|
|
205
|
+
default: return tokenizeOp({ kind: 'invalidNumber' })(input)
|
|
221
206
|
}
|
|
222
207
|
}
|
|
223
|
-
if (isTerminalForNumber(input))
|
|
224
|
-
|
|
225
|
-
switch (state.numberKind)
|
|
226
|
-
{
|
|
208
|
+
if (isTerminalForNumber(input)) {
|
|
209
|
+
switch (state.numberKind) {
|
|
227
210
|
case '-':
|
|
228
211
|
case '.':
|
|
229
212
|
case 'e':
|
|
230
213
|
case 'e+':
|
|
231
214
|
case 'e-':
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
215
|
+
{
|
|
216
|
+
const next = tokenizeOp({ kind: 'initial' })(input)
|
|
217
|
+
return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
|
|
218
|
+
}
|
|
236
219
|
default:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
220
|
+
{
|
|
221
|
+
const next = tokenizeOp({ kind: 'initial' })(input)
|
|
222
|
+
return [{ first: { kind: 'number', value: state.value }, tail: next[0] }, next[1]]
|
|
223
|
+
}
|
|
241
224
|
}
|
|
242
225
|
}
|
|
243
|
-
return tokenizeOp({kind: 'invalidNumber'})(input)
|
|
226
|
+
return tokenizeOp({ kind: 'invalidNumber' })(input)
|
|
244
227
|
}
|
|
245
228
|
|
|
246
229
|
/** @type {(char: number) => boolean} */
|
|
247
|
-
const isTerminalForNumber = char =>
|
|
248
|
-
{
|
|
249
|
-
if (isWhiteSpace(char))
|
|
250
|
-
{
|
|
230
|
+
const isTerminalForNumber = char => {
|
|
231
|
+
if (isWhiteSpace(char)) {
|
|
251
232
|
return true;
|
|
252
233
|
}
|
|
253
|
-
switch (char)
|
|
254
|
-
{
|
|
234
|
+
switch (char) {
|
|
255
235
|
case quotationMark:
|
|
256
236
|
case comma:
|
|
257
237
|
case leftBrace:
|
|
@@ -264,10 +244,8 @@ const isTerminalForNumber = char =>
|
|
|
264
244
|
}
|
|
265
245
|
|
|
266
246
|
/** @type {(char: number) => boolean} */
|
|
267
|
-
const isWhiteSpace = char =>
|
|
268
|
-
{
|
|
269
|
-
switch (char)
|
|
270
|
-
{
|
|
247
|
+
const isWhiteSpace = char => {
|
|
248
|
+
switch (char) {
|
|
271
249
|
case horizontalTab:
|
|
272
250
|
case newLine:
|
|
273
251
|
case carriageReturn:
|
|
@@ -277,102 +255,88 @@ const isWhiteSpace = char =>
|
|
|
277
255
|
}
|
|
278
256
|
|
|
279
257
|
/** @type {(state: InvalidNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
280
|
-
const invalidNumberStateOp = state => input =>
|
|
281
|
-
{
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const next = tokenizeOp({kind: 'initial'})(input)
|
|
285
|
-
return [{first: {kind: 'error', message: 'invalid number'}, tail: next[0]}, next[1]]
|
|
258
|
+
const invalidNumberStateOp = state => input => {
|
|
259
|
+
if (isTerminalForNumber(input)) {
|
|
260
|
+
const next = tokenizeOp({ kind: 'initial' })(input)
|
|
261
|
+
return [{ first: { kind: 'error', message: 'invalid number' }, tail: next[0] }, next[1]]
|
|
286
262
|
}
|
|
287
|
-
return [undefined, {kind: 'invalidNumber'}]
|
|
263
|
+
return [undefined, { kind: 'invalidNumber' }]
|
|
288
264
|
}
|
|
289
265
|
|
|
290
266
|
/** @type {(state: ParseStringState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
291
|
-
const parseStringStateOp = state => input =>
|
|
292
|
-
{
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
case backslash: return [undefined, {kind:'escapeChar', value: state.value}]
|
|
297
|
-
default: return [undefined, {kind:'string', value: appendChar(state.value)(input)}]
|
|
267
|
+
const parseStringStateOp = state => input => {
|
|
268
|
+
switch (input) {
|
|
269
|
+
case quotationMark: return [[{ kind: 'string', value: state.value }], { kind: 'initial' }]
|
|
270
|
+
case backslash: return [undefined, { kind: 'escapeChar', value: state.value }]
|
|
271
|
+
default: return [undefined, { kind: 'string', value: appendChar(state.value)(input) }]
|
|
298
272
|
}
|
|
299
273
|
}
|
|
300
274
|
|
|
301
275
|
/** @type {(state: ParseEscapeCharState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
302
|
-
const parseEscapeCharStateOp = state => input =>
|
|
303
|
-
{
|
|
304
|
-
switch(input)
|
|
305
|
-
{
|
|
276
|
+
const parseEscapeCharStateOp = state => input => {
|
|
277
|
+
switch (input) {
|
|
306
278
|
case quotationMark:
|
|
307
279
|
case backslash:
|
|
308
|
-
case slash: return [undefined, {kind: 'string', value: appendChar(state.value)(input)}]
|
|
309
|
-
case letterB: return [undefined, {kind: 'string', value: appendChar(state.value)(backspace)}]
|
|
310
|
-
case letterF: return [undefined, {kind: 'string', value: appendChar(state.value)(formfeed)}]
|
|
311
|
-
case letterN: return [undefined, {kind: 'string', value: appendChar(state.value)(newLine)}]
|
|
312
|
-
case letterR: return [undefined, {kind: 'string', value: appendChar(state.value)(carriageReturn)}]
|
|
313
|
-
case letterT: return [undefined, {kind: 'string', value: appendChar(state.value)(horizontalTab)}]
|
|
314
|
-
case letterU: return [undefined, {kind: 'unicodeChar', value: state.value, unicode: 0, hexIndex: 0}]
|
|
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 }]
|
|
315
287
|
default: {
|
|
316
|
-
const next = tokenizeOp({kind: 'string', value: state.value})(input)
|
|
317
|
-
return [{first: {kind: 'error', message: 'unescaped character'}, tail: next[0]}, next[1]]
|
|
288
|
+
const next = tokenizeOp({ kind: 'string', value: state.value })(input)
|
|
289
|
+
return [{ first: { kind: 'error', message: 'unescaped character' }, tail: next[0] }, next[1]]
|
|
318
290
|
}
|
|
319
291
|
}
|
|
320
292
|
}
|
|
321
293
|
|
|
322
294
|
/** @type {(hex: number) => number|undefined} */
|
|
323
|
-
const hexDigitToNumber = hex =>
|
|
324
|
-
{
|
|
295
|
+
const hexDigitToNumber = hex => {
|
|
325
296
|
if (containsDigit(hex)) { return hex - digit0 }
|
|
326
297
|
if (containsCapitalAF(hex)) { return hex - capitalLetterA + 10 }
|
|
327
298
|
if (containsSmallAF(hex)) { return hex - letterA + 10 }
|
|
328
299
|
}
|
|
329
300
|
|
|
330
301
|
/** @type {(state: ParseUnicodeCharState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
331
|
-
const parseUnicodeCharStateOp = state => input =>
|
|
332
|
-
{
|
|
302
|
+
const parseUnicodeCharStateOp = state => input => {
|
|
333
303
|
const hexValue = hexDigitToNumber(input)
|
|
334
|
-
if (hexValue === undefined)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
return [{first: {kind: 'error', message: 'invalid hex value'}, tail: next[0]}, next[1]]
|
|
304
|
+
if (hexValue === undefined) {
|
|
305
|
+
const next = tokenizeOp({ kind: 'string', value: state.value })(input)
|
|
306
|
+
return [{ first: { kind: 'error', message: 'invalid hex value' }, tail: next[0] }, next[1]]
|
|
338
307
|
}
|
|
339
308
|
const newUnicode = state.unicode | (hexValue << (3 - state.hexIndex) * 4)
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
309
|
+
return [undefined, state.hexIndex === 3 ?
|
|
310
|
+
{ kind: 'string', value: appendChar(state.value)(newUnicode) } :
|
|
311
|
+
{ kind: 'unicodeChar', value: state.value, unicode: newUnicode, hexIndex: state.hexIndex + 1 }]
|
|
343
312
|
}
|
|
344
313
|
|
|
345
314
|
/** @type {(s: string) => JsonToken} */
|
|
346
|
-
const stringToKeywordToken = s =>
|
|
347
|
-
{
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
case '
|
|
351
|
-
|
|
352
|
-
case 'null': return {kind: 'null'}
|
|
353
|
-
default: return {kind: 'error', message: 'invalid keyword'}
|
|
315
|
+
const stringToKeywordToken = s => {
|
|
316
|
+
switch (s) {
|
|
317
|
+
case 'true': return { kind: 'true' }
|
|
318
|
+
case 'false': return { kind: 'false' }
|
|
319
|
+
case 'null': return { kind: 'null' }
|
|
320
|
+
default: return { kind: 'error', message: 'invalid keyword' }
|
|
354
321
|
}
|
|
355
322
|
}
|
|
356
323
|
|
|
357
324
|
/** @type {(state: ParseKeywordState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
358
|
-
const parseKeyWordStateOp = state => input =>
|
|
359
|
-
{
|
|
360
|
-
|
|
361
|
-
{
|
|
362
|
-
return [undefined, {kind: 'keyword', value: appendChar(state.value)(input)}]
|
|
325
|
+
const parseKeyWordStateOp = state => input => {
|
|
326
|
+
if (containsSmallLetter(input)) {
|
|
327
|
+
return [undefined, { kind: 'keyword', value: appendChar(state.value)(input) }]
|
|
363
328
|
}
|
|
364
329
|
const keyWordToken = stringToKeywordToken(state.value)
|
|
365
|
-
const next = tokenizeOp({kind: 'initial'})(input)
|
|
366
|
-
return [{first: keyWordToken, tail: next[0]}, next[1]]
|
|
330
|
+
const next = tokenizeOp({ kind: 'initial' })(input)
|
|
331
|
+
return [{ first: keyWordToken, tail: next[0] }, next[1]]
|
|
367
332
|
}
|
|
368
333
|
|
|
369
334
|
/** @type {(state: EofState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
370
|
-
const eofStateOp = state => input => [[{kind: 'error', message: 'eof'}], state]
|
|
335
|
+
const eofStateOp = state => input => [[{ kind: 'error', message: 'eof' }], state]
|
|
371
336
|
|
|
372
337
|
/** @type {operator.StateScan<number, TokenizerState, list.List<JsonToken>>} */
|
|
373
338
|
const tokenizeCharCodeOp = state => {
|
|
374
|
-
switch(state.kind)
|
|
375
|
-
{
|
|
339
|
+
switch (state.kind) {
|
|
376
340
|
case 'initial': return initialStateOp(state)
|
|
377
341
|
case 'keyword': return parseKeyWordStateOp(state)
|
|
378
342
|
case 'string': return parseStringStateOp(state)
|
|
@@ -386,35 +350,35 @@ const tokenizeCharCodeOp = state => {
|
|
|
386
350
|
|
|
387
351
|
/** @type {(state: TokenizerState) => readonly[list.List<JsonToken>, TokenizerState]} */
|
|
388
352
|
const tokenizeEofOp = state => {
|
|
389
|
-
switch(state.kind)
|
|
390
|
-
|
|
391
|
-
case '
|
|
392
|
-
case 'keyword': return [[stringToKeywordToken(state.value)], {kind: 'eof'}]
|
|
353
|
+
switch (state.kind) {
|
|
354
|
+
case 'initial': return [undefined, { kind: 'eof' }]
|
|
355
|
+
case 'keyword': return [[stringToKeywordToken(state.value)], { kind: 'eof' }]
|
|
393
356
|
case 'string':
|
|
394
357
|
case 'escapeChar':
|
|
395
|
-
case 'unicodeChar': return [[{kind: 'error', message: '" are missing'}], {kind: 'eof'}]
|
|
396
|
-
case 'invalidNumber': return [[{kind: 'error', message: 'invalid number'}], {kind: 'eof'}]
|
|
358
|
+
case 'unicodeChar': return [[{ kind: 'error', message: '" are missing' }], { kind: 'eof' }]
|
|
359
|
+
case 'invalidNumber': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'eof' }]
|
|
397
360
|
case 'number':
|
|
398
|
-
switch (state.numberKind)
|
|
399
|
-
{
|
|
361
|
+
switch (state.numberKind) {
|
|
400
362
|
case '-':
|
|
401
363
|
case '.':
|
|
402
364
|
case 'e':
|
|
403
365
|
case 'e+':
|
|
404
|
-
case 'e-': return [[{kind: 'error', message: 'invalid number'}], {kind: 'invalidNumber', }]
|
|
405
|
-
default: return [[{kind: 'number', value: state.value}], {kind: 'eof'}]
|
|
366
|
+
case 'e-': return [[{ kind: 'error', message: 'invalid number' }], { kind: 'invalidNumber', }]
|
|
367
|
+
default: return [[{ kind: 'number', value: state.value }], { kind: 'eof' }]
|
|
406
368
|
}
|
|
407
|
-
case 'eof': return [[{kind: 'error', message: 'eof'}], state]
|
|
369
|
+
case 'eof': return [[{ kind: 'error', message: 'eof' }], state]
|
|
408
370
|
}
|
|
409
371
|
}
|
|
410
372
|
|
|
411
373
|
/** @type {operator.StateScan<CharCodeOrEof, TokenizerState, list.List<JsonToken>>} */
|
|
412
374
|
const tokenizeOp = state => input => input === undefined ? tokenizeEofOp(state) : tokenizeCharCodeOp(state)(input)
|
|
413
375
|
|
|
414
|
-
const
|
|
376
|
+
const scanTokenize = stateScan(tokenizeOp)
|
|
377
|
+
|
|
378
|
+
const initial = scanTokenize({ kind: 'initial' })
|
|
415
379
|
|
|
416
380
|
/** @type {(input: list.List<number>) => list.List<JsonToken>} */
|
|
417
|
-
const tokenize = input =>
|
|
381
|
+
const tokenize = input => flat(initial(flat([/** @type {list.List<CharCodeOrEof>} */(input), [undefined]])))
|
|
418
382
|
|
|
419
383
|
module.exports = {
|
|
420
384
|
/** @readonly */
|
|
@@ -2,9 +2,10 @@ const tokenizer = require('./module.f.cjs')
|
|
|
2
2
|
const list = require('../../types/list/module.f.cjs')
|
|
3
3
|
const json = require('../module.f.cjs')
|
|
4
4
|
const { sort } = require('../../types/object/module.f.cjs')
|
|
5
|
+
const encoding = require('../../text/encoding/module.f.cjs');
|
|
5
6
|
|
|
6
7
|
/** @type {(s: string) => readonly tokenizer.JsonToken[]} */
|
|
7
|
-
const tokenizeString = s => list.toArray(tokenizer.tokenize(
|
|
8
|
+
const tokenizeString = s => list.toArray(tokenizer.tokenize(encoding.stringToUtf16List(s)))
|
|
8
9
|
|
|
9
10
|
const stringify = json.stringify(sort)
|
|
10
11
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const pack = require('../../commonjs/package/module.f.cjs')
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @typedef {{
|
|
5
3
|
* readonly execSync: (cmd: string) => Buffer
|
|
@@ -22,13 +20,15 @@ const pack = require('../../commonjs/package/module.f.cjs')
|
|
|
22
20
|
* }} Node
|
|
23
21
|
*/
|
|
24
22
|
|
|
23
|
+
const { stringify, parse } = JSON
|
|
24
|
+
|
|
25
25
|
/** @type {<T>(node: Node<T>) => T} */
|
|
26
26
|
const version = ({ child_process, fs }) =>
|
|
27
27
|
fs.writeFileSync(
|
|
28
28
|
'package.json',
|
|
29
|
-
|
|
29
|
+
stringify(
|
|
30
30
|
{
|
|
31
|
-
...
|
|
31
|
+
...parse(fs.readFileSync('package.json').toString()),
|
|
32
32
|
version: `0.0.${child_process.execSync('git log --oneline').toString().split('\n').length - 1}`
|
|
33
33
|
},
|
|
34
34
|
null,
|
package/package.json
CHANGED
package/sha2/module.f.cjs
CHANGED
|
@@ -73,33 +73,6 @@ const smallSigma0 = smallSigma(7)(18)(3)
|
|
|
73
73
|
|
|
74
74
|
const smallSigma1 = smallSigma(17)(19)(10)
|
|
75
75
|
|
|
76
|
-
/** @type {Hash8} */
|
|
77
|
-
const init256 = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
|
|
78
|
-
|
|
79
|
-
/** @type {(input: readonly number[]) => (bitsCount: number) => Hash8} */
|
|
80
|
-
const computeSha256 = input => bitsCount => compute(input)(bitsCount)(init256)
|
|
81
|
-
|
|
82
|
-
/** @type {Hash8} */
|
|
83
|
-
const init224 = [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]
|
|
84
|
-
|
|
85
|
-
const k = [
|
|
86
|
-
[
|
|
87
|
-
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
88
|
-
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174],
|
|
89
|
-
[
|
|
90
|
-
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
91
|
-
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967],
|
|
92
|
-
[
|
|
93
|
-
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
94
|
-
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070],
|
|
95
|
-
[
|
|
96
|
-
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
97
|
-
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2],
|
|
98
|
-
];
|
|
99
|
-
|
|
100
|
-
/** @type {(input: readonly number[]) => (bitsCount: number) => Hash8} */
|
|
101
|
-
const computeSha224 = input => bitsCount => compute(input)(bitsCount)(init224)
|
|
102
|
-
|
|
103
76
|
/** @type {(a: array.Array4<number>) => number} */
|
|
104
77
|
const wi = a => (smallSigma1(a[0]) + a[1] + smallSigma0(a[2]) + a[3]) | 0
|
|
105
78
|
|
|
@@ -166,8 +139,8 @@ const compress = init => data => {
|
|
|
166
139
|
]
|
|
167
140
|
}
|
|
168
141
|
|
|
169
|
-
/** @type {(input: readonly number[]) => (bitsCount: number) =>
|
|
170
|
-
const compute =
|
|
142
|
+
/** @type {(init: Hash8) => (input: readonly number[]) => (bitsCount: number) => Hash8} */
|
|
143
|
+
const compute = init => input => bitsCount => {
|
|
171
144
|
const { f, length } = padding(input)(bitsCount)
|
|
172
145
|
|
|
173
146
|
let result = init
|
|
@@ -183,6 +156,33 @@ const compute = input => bitsCount => init => {
|
|
|
183
156
|
return result
|
|
184
157
|
}
|
|
185
158
|
|
|
159
|
+
/** @type {Hash8} */
|
|
160
|
+
const init256 = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
|
|
161
|
+
|
|
162
|
+
/** @type {(input: readonly number[]) => (bitsCount: number) => Hash8} */
|
|
163
|
+
const computeSha256 = compute(init256)
|
|
164
|
+
|
|
165
|
+
/** @type {Hash8} */
|
|
166
|
+
const init224 = [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]
|
|
167
|
+
|
|
168
|
+
const k = [
|
|
169
|
+
[
|
|
170
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
171
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174],
|
|
172
|
+
[
|
|
173
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
174
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967],
|
|
175
|
+
[
|
|
176
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
177
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070],
|
|
178
|
+
[
|
|
179
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
180
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2],
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
/** @type {(input: readonly number[]) => (bitsCount: number) => Hash8} */
|
|
184
|
+
const computeSha224 = compute(init224)
|
|
185
|
+
|
|
186
186
|
module.exports = {
|
|
187
187
|
/** @readonly */
|
|
188
188
|
padding,
|
|
@@ -3,6 +3,8 @@ const list = require('../../types/list/module.f.cjs')
|
|
|
3
3
|
const operator = require('../../types/function/operator/module.f.cjs')
|
|
4
4
|
const array = require('../../types/array/module.f.cjs')
|
|
5
5
|
const { contains } = require('../../types/range/module.f.cjs')
|
|
6
|
+
const { compose } = require('../../types/function/module.f.cjs')
|
|
7
|
+
const { map, flat, stateScan, concat, fold, toArray, flatMap } = list
|
|
6
8
|
const { ok, error } = result
|
|
7
9
|
|
|
8
10
|
/** @typedef {result.Result<number,number>} ByteResult */
|
|
@@ -53,11 +55,9 @@ const codePointToUtf16 = input =>
|
|
|
53
55
|
return [input & 0xffff]
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
const codePointListToUtf8List = list.flatMap(codePointToUtf8)
|
|
58
|
+
const codePointListToUtf8List = flatMap(codePointToUtf8)
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
const codePointListToUtf16List = list.flatMap(codePointToUtf16)
|
|
60
|
+
const codePointListToUtf16List = flatMap(codePointToUtf16)
|
|
61
61
|
|
|
62
62
|
/** @type {operator.StateScan<number, Utf8State, list.List<CodePointResult>>} */
|
|
63
63
|
const utf8ByteToCodePointOp = state => byte => {
|
|
@@ -85,7 +85,7 @@ const utf8ByteToCodePointOp = state => byte => {
|
|
|
85
85
|
return [[ok(((state[0] & 0x07) << 18) + ((state[1] & 0x3f) << 12) + ((state[2] & 0x3f) << 6) + (byte & 0x3f))], undefined]
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
return [[error(
|
|
88
|
+
return [[error(toArray(concat(state)([byte])))], undefined]
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/** @type {(state: Utf8State) => readonly[list.List<CodePointResult>, Utf8State]} */
|
|
@@ -95,7 +95,7 @@ const utf8EofToCodePointOp = state => [state === undefined ? undefined : [error(
|
|
|
95
95
|
const utf8ByteOrEofToCodePointOp = state => input => input === undefined ? utf8EofToCodePointOp(state) : utf8ByteToCodePointOp(state)(input)
|
|
96
96
|
|
|
97
97
|
/** @type {(input: list.List<number>) => list.List<CodePointResult>} */
|
|
98
|
-
const utf8ListToCodePointList = input =>
|
|
98
|
+
const utf8ListToCodePointList = input => flat(stateScan(utf8ByteOrEofToCodePointOp)(undefined)(concat(/** @type {list.List<ByteOrEof>} */(input))([undefined])))
|
|
99
99
|
|
|
100
100
|
/** @type {operator.StateScan<u16, Utf16State, list.List<i32>>} */
|
|
101
101
|
const utf16ByteToCodePointOp = state => byte => {
|
|
@@ -124,7 +124,19 @@ const utf16EofToCodePointOp = state => [state === undefined ? undefined : [state
|
|
|
124
124
|
const utf16ByteOrEofToCodePointOp = state => input => input === undefined ? utf16EofToCodePointOp(state) : utf16ByteToCodePointOp(state)(input)
|
|
125
125
|
|
|
126
126
|
/** @type {(input: list.List<u16>) => list.List<i32>} */
|
|
127
|
-
const utf16ListToCodePointList = input =>
|
|
127
|
+
const utf16ListToCodePointList = input => flat(stateScan(utf16ByteOrEofToCodePointOp)(undefined)(concat(/** @type {list.List<WordOrEof>} */(input))([undefined])))
|
|
128
|
+
|
|
129
|
+
/** @type {(s: string) => list.List<u16>} */
|
|
130
|
+
const stringToUtf16List = s => {
|
|
131
|
+
/** @type {(i: number) => list.Result<number>} */
|
|
132
|
+
const at = i => {
|
|
133
|
+
const first = s.charCodeAt(i)
|
|
134
|
+
return isNaN(first) ? undefined : { first, tail: () => at(i + 1) }
|
|
135
|
+
}
|
|
136
|
+
return at(0)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const utf16ListToString = compose(map(String.fromCharCode))(fold(operator.concat)(''))
|
|
128
140
|
|
|
129
141
|
module.exports = {
|
|
130
142
|
/** @readonly */
|
|
@@ -134,5 +146,9 @@ module.exports = {
|
|
|
134
146
|
/** @readonly */
|
|
135
147
|
utf8ListToCodePointList,
|
|
136
148
|
/** @readonly */
|
|
137
|
-
utf16ListToCodePointList
|
|
149
|
+
utf16ListToCodePointList,
|
|
150
|
+
/** @readonly */
|
|
151
|
+
stringToUtf16List,
|
|
152
|
+
/** @readonly */
|
|
153
|
+
utf16ListToString
|
|
138
154
|
}
|
package/text/encoding/test.f.cjs
CHANGED
|
@@ -206,4 +206,18 @@ const stringify = a => json.stringify(sort)(a)
|
|
|
206
206
|
if (result !== '[-2147427328,0]') { throw result }
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
+
{
|
|
210
|
+
const utf16List = encoding.stringToUtf16List("Hello world!😂🚜🚲")
|
|
211
|
+
const result = encoding.utf16ListToString(utf16List)
|
|
212
|
+
if (result !== "Hello world!😂🚜🚲") { throw result }
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
{
|
|
216
|
+
const a = encoding.stringToUtf16List("Hello world!😂🚜🚲")
|
|
217
|
+
const b = encoding.utf16ListToCodePointList(a)
|
|
218
|
+
const c = encoding.codePointListToUtf16List(b)
|
|
219
|
+
const result = encoding.utf16ListToString(c)
|
|
220
|
+
if (result !== "Hello world!😂🚜🚲") { throw result }
|
|
221
|
+
}
|
|
222
|
+
|
|
209
223
|
module.exports = {}
|