@temperlang/core 0.2.1 → 0.4.0
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/async.js +71 -0
- package/bitvector.js +103 -0
- package/check-type.js +65 -0
- package/core.js +107 -0
- package/date.js +45 -0
- package/deque.js +67 -0
- package/float.js +74 -0
- package/index.js +12 -1145
- package/interface.js +56 -0
- package/listed.js +289 -0
- package/mapped.js +216 -0
- package/package.json +1 -1
- package/pair.js +69 -0
- package/regex.js +91 -76
- package/string.js +198 -0
- package/interface-types.js +0 -121
package/index.js
CHANGED
|
@@ -1,1146 +1,13 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./async.js";
|
|
2
|
+
export * from "./bitvector.js";
|
|
3
|
+
export * from "./check-type.js";
|
|
4
|
+
export * from "./core.js";
|
|
5
|
+
export * from "./date.js";
|
|
6
|
+
export * from "./deque.js";
|
|
7
|
+
export * from "./float.js";
|
|
8
|
+
export * from "./interface.js";
|
|
9
|
+
export * from "./listed.js";
|
|
10
|
+
export * from "./mapped.js";
|
|
11
|
+
export * from "./pair.js";
|
|
2
12
|
export * from "./regex.js";
|
|
3
|
-
|
|
4
|
-
// Implements extension method String::isEmpty
|
|
5
|
-
export function stringIsEmpty(s) {
|
|
6
|
-
return s === "";
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// Implements extension method String::split
|
|
10
|
-
export function stringSplit(s, separator) {
|
|
11
|
-
return separator ? s.split(separator).map((s) => s) : Array.from(s);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Implements extension method String::toFloat64
|
|
16
|
-
* @param {string} s
|
|
17
|
-
*/
|
|
18
|
-
export function stringToFloat64(s) {
|
|
19
|
-
// TODO Consider JSON.parse + bonus constants instead? Faster or not?
|
|
20
|
-
if (!/^\s*-?(?:\d+(?:\.\d+)?(?:[eE][-+]?\d+)?|NaN|Infinity)\s*$/.test(s)) {
|
|
21
|
-
bubble();
|
|
22
|
-
}
|
|
23
|
-
return Number(s);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Implements extension method String::toInt
|
|
28
|
-
* @param {string} s
|
|
29
|
-
*/
|
|
30
|
-
export function stringToInt(s) {
|
|
31
|
-
// I'm not sure there's another simple reliable way to know if it's all used.
|
|
32
|
-
// This also checks against things like 2e0 -> 2.
|
|
33
|
-
if (!/^\s*-?\d+\s*$/.test(s)) {
|
|
34
|
-
bubble();
|
|
35
|
-
}
|
|
36
|
-
const result = parseInt(s, 10);
|
|
37
|
-
// TODO Could we use a more precise regex above to avoid this check here?
|
|
38
|
-
requireIsSafeInteger(result);
|
|
39
|
-
return result;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Specifically for utf8 and utf32, since utf16 is simpler in js. */
|
|
43
|
-
class TrickyStringSlice {
|
|
44
|
-
hasAtLeast(count) {
|
|
45
|
-
// Repeated calls to hasAtLeast are potentially expensive.
|
|
46
|
-
return (this.length ?? this._lengthUntil(count)) >= count;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
get length() {
|
|
50
|
-
if (this._length === undefined) {
|
|
51
|
-
this._length = this._lengthUntil();
|
|
52
|
-
}
|
|
53
|
-
return this._length;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
_lengthUntil(stop = undefined) {
|
|
57
|
-
// To be overridden in subclasses.
|
|
58
|
-
return 0;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
class Utf8StringSlice extends TrickyStringSlice {
|
|
63
|
-
constructor(content, left = 0, right = content.length * 4) {
|
|
64
|
-
super();
|
|
65
|
-
this.content = content;
|
|
66
|
-
this.left = left;
|
|
67
|
-
this.right = right;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
toString() {
|
|
71
|
-
let left = this.left;
|
|
72
|
-
let right = this.right;
|
|
73
|
-
let content = this.content;
|
|
74
|
-
|
|
75
|
-
if (left === right) {
|
|
76
|
-
return "";
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// If we're only using some bytes on the left or right, replace that codepoint with U+FFFD.
|
|
80
|
-
let leftPartial = left & 3; // Do we have an incomplete code-point on the left?
|
|
81
|
-
let leftIndex = (left + 3) >> 2;
|
|
82
|
-
let rightIndex = right >> 2;
|
|
83
|
-
let rightPartial = right & 3;
|
|
84
|
-
|
|
85
|
-
// If leftIndex is in the middle of a surrogate pair, advance over the tail.
|
|
86
|
-
if (leftIndex < rightIndex) {
|
|
87
|
-
let leftCodeUnitUtf16 = content.charCodeAt(leftIndex);
|
|
88
|
-
if (0xdc00 < leftCodeUnitUtf16 && leftCodeUnitUtf16 <= 0xdfff) {
|
|
89
|
-
leftIndex += 1;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (leftIndex > rightIndex) {
|
|
94
|
-
return "\uFFFD";
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
let sub = content.substring(leftIndex, rightIndex);
|
|
98
|
-
if (leftPartial || rightPartial) {
|
|
99
|
-
return `${leftPartial ? "\uFFFD" : ""}${sub}${
|
|
100
|
-
rightPartial ? "\uFFFD" : ""
|
|
101
|
-
}`;
|
|
102
|
-
} else {
|
|
103
|
-
return sub;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
valueOf() {
|
|
108
|
-
return this.toString();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
_lengthUntil(stop) {
|
|
112
|
-
const left = this.left;
|
|
113
|
-
const right = this.right;
|
|
114
|
-
const content = this.content;
|
|
115
|
-
let i = left >> 2;
|
|
116
|
-
// Add bytes between codePointBoundaryBeforeLimit and right
|
|
117
|
-
// Subtract bytes past zeroth in codepoint for left
|
|
118
|
-
let len = (right & 3) - (left & 3);
|
|
119
|
-
const codePointBoundaryBeforeLimit = (right & ~3) >> 2;
|
|
120
|
-
while (i < codePointBoundaryBeforeLimit) {
|
|
121
|
-
if (stop !== undefined && len >= stop) {
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
let cp = content.codePointAt(i);
|
|
125
|
-
let nBytes = nUtf8BytesInChar(cp);
|
|
126
|
-
len += nBytes;
|
|
127
|
-
i += (4 + nBytes) >> 2;
|
|
128
|
-
}
|
|
129
|
-
return len;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
get isEmpty() {
|
|
133
|
-
return this.left >= this.right;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
read() {
|
|
137
|
-
let left = this.left;
|
|
138
|
-
let right = this.right;
|
|
139
|
-
if (left >= right) {
|
|
140
|
-
bubble();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
let content = this.content;
|
|
144
|
-
let cp = content.codePointAt(left >> 2);
|
|
145
|
-
if (cp < 0x80) {
|
|
146
|
-
return cp;
|
|
147
|
-
} else {
|
|
148
|
-
let byteOffset = left & 3;
|
|
149
|
-
let nBytes = nUtf8BytesInChar(cp);
|
|
150
|
-
let byteInfo = byteInfos[(nBytes - 1) * 4 + byteOffset];
|
|
151
|
-
let codeUnit =
|
|
152
|
-
((cp >>> byteInfo.shift) & byteInfo.andMask) | byteInfo.orMask;
|
|
153
|
-
return codeUnit;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* @param {number} count
|
|
159
|
-
* @return {number}
|
|
160
|
-
*/
|
|
161
|
-
_advanceLeft(count) {
|
|
162
|
-
let left = this.left;
|
|
163
|
-
let content = this.content;
|
|
164
|
-
let contentLen = content.length;
|
|
165
|
-
let idx = left >> 2;
|
|
166
|
-
let sub = left & 3;
|
|
167
|
-
|
|
168
|
-
while (count > 0 && idx < contentLen) {
|
|
169
|
-
let cp = content.codePointAt(idx);
|
|
170
|
-
let rem = nUtf8BytesInChar(cp) - sub;
|
|
171
|
-
if (rem > count) {
|
|
172
|
-
sub += count;
|
|
173
|
-
count = 0;
|
|
174
|
-
} else {
|
|
175
|
-
count -= rem;
|
|
176
|
-
sub = 0;
|
|
177
|
-
idx += cp > 0x10000 ? 2 : 1;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return count ? this.right : Math.min(idx << 2 | sub, this.right);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* @param {number} count
|
|
186
|
-
* @return {Utf8StringSlice}
|
|
187
|
-
*/
|
|
188
|
-
advance(count) {
|
|
189
|
-
let newLeft = this._advanceLeft(count);
|
|
190
|
-
return (this.left === newLeft)
|
|
191
|
-
? this
|
|
192
|
-
: new Utf8StringSlice(this.content, newLeft, this.right);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* @param {number} count
|
|
197
|
-
* @return {Utf8StringSlice}
|
|
198
|
-
*/
|
|
199
|
-
limit(count) {
|
|
200
|
-
let newRight = this._advanceLeft(count);
|
|
201
|
-
return (this.right === newRight)
|
|
202
|
-
? this
|
|
203
|
-
: new Utf8StringSlice(this.content, this.left, newRight);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
[Symbol.iterator]() {
|
|
207
|
-
function* bytes(content, left, limit) {
|
|
208
|
-
let i = left;
|
|
209
|
-
while (i < limit) {
|
|
210
|
-
let cp = content.codePointAt(i >> 2);
|
|
211
|
-
if (cp < 0x80) {
|
|
212
|
-
yield cp;
|
|
213
|
-
i += 4;
|
|
214
|
-
} else {
|
|
215
|
-
let byteOffset = i & 3;
|
|
216
|
-
let nBytes = nUtf8BytesInChar(cp);
|
|
217
|
-
let byteInfo = byteInfos[(nBytes - 1) * 4 + byteOffset];
|
|
218
|
-
let codeUnit =
|
|
219
|
-
((cp >>> byteInfo.shift) & byteInfo.andMask) | byteInfo.orMask;
|
|
220
|
-
yield codeUnit;
|
|
221
|
-
i = byteOffset + 1 < nBytes ? i + 1 : (i & ~3) + ((nBytes + 4) & ~3);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return bytes(this.content, this.left, this.right);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
toJSON() {
|
|
229
|
-
return { content: this.content, left: this.left, right: this.right };
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
class Utf16StringSlice {
|
|
234
|
-
constructor(content, left = 0, right = content.length) {
|
|
235
|
-
this.content = content;
|
|
236
|
-
this.left = left;
|
|
237
|
-
this.right = right;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
toString() {
|
|
241
|
-
return this.content.substring(this.left, this.right);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
valueOf() {
|
|
245
|
-
return this.toString();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
hasAtLeast(count) {
|
|
249
|
-
return this.length >= count;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
get length() {
|
|
253
|
-
return this.right - this.left;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
get isEmpty() {
|
|
257
|
-
return this.left >= this.right;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
read() {
|
|
261
|
-
let left = this.left;
|
|
262
|
-
let right = this.right;
|
|
263
|
-
if (left >= right) {
|
|
264
|
-
bubble();
|
|
265
|
-
}
|
|
266
|
-
return this.content.charCodeAt(left);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* @param {number} count
|
|
271
|
-
* @return {number}
|
|
272
|
-
*/
|
|
273
|
-
_advanceLeft(count) {
|
|
274
|
-
return Math.min(this.left + count, this.right);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* @param {number} count
|
|
279
|
-
* @return {Utf16StringSlice}
|
|
280
|
-
*/
|
|
281
|
-
advance(count) {
|
|
282
|
-
let newLeft = this._advanceLeft(count);
|
|
283
|
-
return this.left === newLeft
|
|
284
|
-
? this
|
|
285
|
-
: new Utf16StringSlice(this.content, newLeft, this.right);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* @param {number} count
|
|
290
|
-
* @return {Utf16StringSlice}
|
|
291
|
-
*/
|
|
292
|
-
limit(count) {
|
|
293
|
-
let newRight = this._advanceLeft(count);
|
|
294
|
-
return this.right === newRight
|
|
295
|
-
? this
|
|
296
|
-
: new Utf16StringSlice(this.content, this.left, newRight);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
[Symbol.iterator]() {
|
|
300
|
-
function* chars(content, left, limit) {
|
|
301
|
-
let i = left;
|
|
302
|
-
while (i < limit) {
|
|
303
|
-
yield content.charCodeAt(i);
|
|
304
|
-
i += 1;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return chars(this.content, this.left, this.right);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
toJSON() {
|
|
311
|
-
return { content: this.content, left: this.left, right: this.right };
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
class CodePointsStringSlice extends TrickyStringSlice {
|
|
316
|
-
constructor(content, left = 0, right = content.length) {
|
|
317
|
-
super();
|
|
318
|
-
this.content = content;
|
|
319
|
-
this.left = left;
|
|
320
|
-
this.right = right;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
toString() {
|
|
324
|
-
return this.content.substring(this.left, this.right);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
valueOf() {
|
|
328
|
-
return this.toString();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
_lengthUntil(stop) {
|
|
332
|
-
let i = this.left;
|
|
333
|
-
let len = 0;
|
|
334
|
-
while (i < this.right) {
|
|
335
|
-
if (stop !== undefined && len >= stop) {
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
let cp = this.content.codePointAt(i);
|
|
339
|
-
if (cp > 0xffff) {
|
|
340
|
-
i += 2;
|
|
341
|
-
} else {
|
|
342
|
-
i += 1;
|
|
343
|
-
}
|
|
344
|
-
len += 1;
|
|
345
|
-
}
|
|
346
|
-
return len;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
get isEmpty() {
|
|
350
|
-
return this.left >= this.right;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
read() {
|
|
354
|
-
if (this.left >= this.right) {
|
|
355
|
-
bubble();
|
|
356
|
-
}
|
|
357
|
-
return this.content.codePointAt(this.left);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* @param {number} count
|
|
362
|
-
* @return {number}
|
|
363
|
-
*/
|
|
364
|
-
_advanceLeft(count) {
|
|
365
|
-
let left = this.left;
|
|
366
|
-
let right = this.right;
|
|
367
|
-
let content = this.content;
|
|
368
|
-
if (count <= 0) { return left }
|
|
369
|
-
let newLeft = left;
|
|
370
|
-
for (let i = count; i && newLeft < right; --i) {
|
|
371
|
-
let cp = content.codePointAt(newLeft);
|
|
372
|
-
if (cp > 0xffff) {
|
|
373
|
-
newLeft += 2;
|
|
374
|
-
} else {
|
|
375
|
-
newLeft += 1;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
if (newLeft >= right) {
|
|
379
|
-
newLeft = right;
|
|
380
|
-
}
|
|
381
|
-
return newLeft;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* @param {number} count
|
|
386
|
-
* @return {CodePointsStringSlice}
|
|
387
|
-
*/
|
|
388
|
-
advance(count) {
|
|
389
|
-
let newLeft = this._advanceLeft(count);
|
|
390
|
-
return (newLeft === this.left)
|
|
391
|
-
? this
|
|
392
|
-
: new CodePointsStringSlice(this.content, newLeft, this.right);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* @param {number} count
|
|
397
|
-
* @return {CodePointsStringSlice}
|
|
398
|
-
*/
|
|
399
|
-
limit(count) {
|
|
400
|
-
let newRight = this._advanceLeft(count);
|
|
401
|
-
return (newRight === this.right)
|
|
402
|
-
? this
|
|
403
|
-
: new CodePointsStringSlice(this.content, this.left, newRight);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
[Symbol.iterator]() {
|
|
407
|
-
function* chars(content, left, limit) {
|
|
408
|
-
let i = left;
|
|
409
|
-
while (i < limit) {
|
|
410
|
-
let cp = content.codePointAt(i);
|
|
411
|
-
yield cp;
|
|
412
|
-
i += cp > 0xffff ? 2 : 1;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
return chars(this.content, this.left, this.right);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
toJSON() {
|
|
419
|
-
return { content: this.content, left: this.left, right: this.right };
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// Implements extension method String::utf8
|
|
424
|
-
export function stringUtf8(string) {
|
|
425
|
-
return new Utf8StringSlice(string);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// Implements extension method String::utf16
|
|
429
|
-
export function stringUtf16(string) {
|
|
430
|
-
return new Utf16StringSlice(string);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// Implements extension method String::codePoints
|
|
434
|
-
export function stringCodePoints(string) {
|
|
435
|
-
return new CodePointsStringSlice(string);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// Implements extension method Int::toString
|
|
439
|
-
export function intToString(i, radix) {
|
|
440
|
-
return i.toString(radix);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// Implements extension method Float64::near
|
|
444
|
-
export function float64Near(x, y, relTol, absTol) {
|
|
445
|
-
if (relTol === undefined) {
|
|
446
|
-
relTol = 1e-9;
|
|
447
|
-
}
|
|
448
|
-
if (absTol === undefined) {
|
|
449
|
-
absTol = 0;
|
|
450
|
-
}
|
|
451
|
-
const margin = Math.max(Math.max(Math.abs(x), Math.abs(y)) * relTol, absTol);
|
|
452
|
-
return Math.abs(x - y) < margin;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// Implements extension method Float64::toInt
|
|
456
|
-
export function float64ToInt(n) {
|
|
457
|
-
const i = float64ToIntUnsafe(n);
|
|
458
|
-
if (Math.abs(n - i) < 1) {
|
|
459
|
-
return i;
|
|
460
|
-
} else {
|
|
461
|
-
bubble();
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// Implements extension method Float64::toIntUnsafe
|
|
466
|
-
export function float64ToIntUnsafe(n) {
|
|
467
|
-
// We are free to do whatever with NaN here.
|
|
468
|
-
return isNaN(n)
|
|
469
|
-
? 0
|
|
470
|
-
: Math.max(
|
|
471
|
-
Number.MIN_SAFE_INTEGER,
|
|
472
|
-
Math.min(Math.trunc(n), Number.MAX_SAFE_INTEGER)
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// Implements extension method Float64::toString
|
|
477
|
-
export function float64ToString(n) {
|
|
478
|
-
// TODO(mikesamuel, issue#579): need functional test to nail down
|
|
479
|
-
// double formatting threshholds.
|
|
480
|
-
if (n == 0) {
|
|
481
|
-
return Object.is(n, -0) ? "-0.0" : "0.0";
|
|
482
|
-
} else {
|
|
483
|
-
let result = n.toString();
|
|
484
|
-
// Rely on eagerness and js number formatting rules here.
|
|
485
|
-
const groups = /(-?[0-9]+)(\.[0-9]+)?(.+)?/.exec(result);
|
|
486
|
-
if (groups === null) {
|
|
487
|
-
return result;
|
|
488
|
-
} else {
|
|
489
|
-
// Guarantee a decimal point for floats.
|
|
490
|
-
return `${groups[1]}${groups[2] || ".0"}${groups[3] || ""}`;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
function nUtf8BytesInChar(cp) {
|
|
496
|
-
return cp < 0x0800 ? (cp < 0x80 ? 1 : 2) : cp < 0x10000 ? 3 : 4;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/*
|
|
500
|
-
* | First code point | Last code point | Byte 0 | Byte 1 | Byte 2 | Byte 3 |
|
|
501
|
-
* | ---------------- | --------------- | --------- | --------- | --------- | --------- |
|
|
502
|
-
* | U+0000 | U+007F | 0xxx_xxxx | | | |
|
|
503
|
-
* | U+0080 | U+07FF | 110x_xxxx | 10xx_xxxx | | |
|
|
504
|
-
* | U+0800 | U+FFFF | 1110_xxxx | 10xx_xxxx | 10xx_xxxx | |
|
|
505
|
-
* | U+10000 | U+10FFFF | 1111_0xxx | 10xx_xxxx | 10xx_xxxx | 10xx_xxxx |
|
|
506
|
-
*/
|
|
507
|
-
const byteInfos = [
|
|
508
|
-
{ andMask: 0b0111_1111, orMask: 0, shift: 0 },
|
|
509
|
-
null,
|
|
510
|
-
null,
|
|
511
|
-
null,
|
|
512
|
-
|
|
513
|
-
{ andMask: 0b0001_1111, orMask: 0b1100_0000, shift: 6 },
|
|
514
|
-
{ andMask: 0b0011_1111, orMask: 0b1000_0000, shift: 0 },
|
|
515
|
-
null,
|
|
516
|
-
null,
|
|
517
|
-
|
|
518
|
-
{ andMask: 0b0000_1111, orMask: 0b1110_0000, shift: 12 },
|
|
519
|
-
{ andMask: 0b0011_1111, orMask: 0b1000_0000, shift: 6 },
|
|
520
|
-
{ andMask: 0b0011_1111, orMask: 0b1000_0000, shift: 0 },
|
|
521
|
-
null,
|
|
522
|
-
|
|
523
|
-
{ andMask: 0b0000_0111, orMask: 0b1111_0000, shift: 18 },
|
|
524
|
-
{ andMask: 0b0011_1111, orMask: 0b1000_0000, shift: 12 },
|
|
525
|
-
{ andMask: 0b0011_1111, orMask: 0b1000_0000, shift: 6 },
|
|
526
|
-
{ andMask: 0b0011_1111, orMask: 0b1000_0000, shift: 0 },
|
|
527
|
-
];
|
|
528
|
-
|
|
529
|
-
// Implements extension method ListBuilder::add
|
|
530
|
-
export function listBuilderAdd(ls, newItem, at) {
|
|
531
|
-
if (at === undefined) {
|
|
532
|
-
// Technically, we could also use splice instead of push for this case.
|
|
533
|
-
// Which is better might depend on minifiers and/or execution speed.
|
|
534
|
-
ls.push(newItem);
|
|
535
|
-
} else {
|
|
536
|
-
if (at < 0 || at > ls.length) {
|
|
537
|
-
bubble();
|
|
538
|
-
}
|
|
539
|
-
ls.splice(at, 0, newItem);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
// Implements extension method ListBuilder::addAll
|
|
543
|
-
export function listBuilderAddAll(ls, newItems, at) {
|
|
544
|
-
if (at === undefined) {
|
|
545
|
-
ls.push(...newItems);
|
|
546
|
-
} else {
|
|
547
|
-
if (at < 0 || at > ls.length) {
|
|
548
|
-
bubble();
|
|
549
|
-
}
|
|
550
|
-
ls.splice(at, 0, ...newItems);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
// Implements extension method List::filter
|
|
554
|
-
export function listFilter(ls, predicate) {
|
|
555
|
-
let filtered = null;
|
|
556
|
-
let nFiltered = 0; // Just past index of last element of ls filtered onto filtered
|
|
557
|
-
let { length } = ls;
|
|
558
|
-
for (let i = 0; i < length; ++i) {
|
|
559
|
-
let element = ls[i];
|
|
560
|
-
let ok = predicate(element);
|
|
561
|
-
if (!ok) {
|
|
562
|
-
if (!filtered) {
|
|
563
|
-
filtered = [];
|
|
564
|
-
}
|
|
565
|
-
filtered.push(...ls.slice(nFiltered, i));
|
|
566
|
-
nFiltered = i + 1;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
let fullyFiltered;
|
|
570
|
-
if (filtered) {
|
|
571
|
-
filtered.push(...ls.slice(nFiltered, length));
|
|
572
|
-
fullyFiltered = filtered;
|
|
573
|
-
} else {
|
|
574
|
-
fullyFiltered = ls;
|
|
575
|
-
}
|
|
576
|
-
return freeze(fullyFiltered);
|
|
577
|
-
}
|
|
578
|
-
// Implements extension method List::get
|
|
579
|
-
export function listGet(ls, i) {
|
|
580
|
-
let { length } = ls;
|
|
581
|
-
if (0 <= i && i < length) {
|
|
582
|
-
return ls[i];
|
|
583
|
-
}
|
|
584
|
-
bubble();
|
|
585
|
-
}
|
|
586
|
-
// Implements extension method List::getOr
|
|
587
|
-
export function listGetOr(ls, i, fallback) {
|
|
588
|
-
let { length } = ls;
|
|
589
|
-
return 0 <= i && i < length ? ls[i] : fallback;
|
|
590
|
-
}
|
|
591
|
-
// Implements extension method List::isEmpty
|
|
592
|
-
export function listIsEmpty(ls) {
|
|
593
|
-
return !ls.length;
|
|
594
|
-
}
|
|
595
|
-
// Implements extension method List::join
|
|
596
|
-
export function listJoin(ls, separator, elementStringifier) {
|
|
597
|
-
let joined = "";
|
|
598
|
-
let { length } = ls;
|
|
599
|
-
for (let i = 0; i < length; ++i) {
|
|
600
|
-
if (i) {
|
|
601
|
-
joined += separator;
|
|
602
|
-
}
|
|
603
|
-
let element = ls[i];
|
|
604
|
-
let stringifiedElement = elementStringifier(element);
|
|
605
|
-
joined += stringifiedElement;
|
|
606
|
-
}
|
|
607
|
-
return joined;
|
|
608
|
-
}
|
|
609
|
-
// Implements extension method List::length
|
|
610
|
-
export function listLength(ls) {
|
|
611
|
-
return ls.length;
|
|
612
|
-
}
|
|
613
|
-
// Implements extension method List::mapDropping
|
|
614
|
-
export function listMapDropping() {
|
|
615
|
-
throw new Error("TODO List::mapDropping");
|
|
616
|
-
}
|
|
617
|
-
// Implements extension method List::map
|
|
618
|
-
export function listMap(ls, transform) {
|
|
619
|
-
let mapped = [];
|
|
620
|
-
let { length } = ls;
|
|
621
|
-
for (let i = 0; i < length; ++i) {
|
|
622
|
-
let transformed = transform(ls[i]);
|
|
623
|
-
mapped[i] = transformed;
|
|
624
|
-
}
|
|
625
|
-
return freeze(mapped);
|
|
626
|
-
}
|
|
627
|
-
// Implements extension method Listed::toList
|
|
628
|
-
export function listedToList(ls) {
|
|
629
|
-
if (Object.isFrozen(ls)) {
|
|
630
|
-
return ls;
|
|
631
|
-
} else {
|
|
632
|
-
return listBuilderToList(ls);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
// Implements extension method ListBuilder::removeLast
|
|
636
|
-
export function listBuilderRemoveLast(ls) {
|
|
637
|
-
if (ls.length) {
|
|
638
|
-
return ls.pop();
|
|
639
|
-
} else {
|
|
640
|
-
bubble();
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
// Implements extension method ListBuilder::reverse
|
|
644
|
-
export function listBuilderReverse(ls) {
|
|
645
|
-
let { length } = ls;
|
|
646
|
-
let lastIndex = length - 1;
|
|
647
|
-
let mid = length >> 1;
|
|
648
|
-
for (let i = 0; i < mid; ++i) {
|
|
649
|
-
let j = lastIndex - i;
|
|
650
|
-
let a = ls[i];
|
|
651
|
-
ls[i] = ls[j];
|
|
652
|
-
ls[j] = a;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
// Implements extension method ListBuilder::set
|
|
656
|
-
export function listBuilderSet(ls, i, newValue) {
|
|
657
|
-
if (0 <= i && i <= ls.length) {
|
|
658
|
-
ls[i] = newValue;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
// Implements extension method ListBuilder::removeLast
|
|
662
|
-
export function listBuilderSplice(ls, index, removeCount, newValues) {
|
|
663
|
-
// Missing count is all, but explicit undefined is 0, so give explicit length.
|
|
664
|
-
if (removeCount === undefined) {
|
|
665
|
-
removeCount = ls.length;
|
|
666
|
-
}
|
|
667
|
-
return freeze(ls.splice(index, removeCount, ...(newValues || [])));
|
|
668
|
-
}
|
|
669
|
-
// Implements extension method ListBuilder::toList
|
|
670
|
-
export function listBuilderToList(ls) {
|
|
671
|
-
return freeze(ls.slice());
|
|
672
|
-
}
|
|
673
|
-
// Implements extension method List::slice
|
|
674
|
-
export function listSlice(ls, startInclusive, endExclusive) {
|
|
675
|
-
if (startInclusive < 0) {
|
|
676
|
-
startInclusive = 0;
|
|
677
|
-
}
|
|
678
|
-
if (endExclusive < 0) {
|
|
679
|
-
endExclusive = 0;
|
|
680
|
-
}
|
|
681
|
-
return freeze(ls.slice(startInclusive, endExclusive));
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
// Map
|
|
685
|
-
class FreezeMap extends Map {
|
|
686
|
-
// TODO Don't worry to freeze? Or worry more by wrapping private map?
|
|
687
|
-
// TODO Wrapping/Object.proxy presumably pays an extra cost when wrapped.
|
|
688
|
-
clear() {
|
|
689
|
-
throw new TypeError();
|
|
690
|
-
}
|
|
691
|
-
delete() {
|
|
692
|
-
throw new TypeError();
|
|
693
|
-
}
|
|
694
|
-
set(key, value) {
|
|
695
|
-
if (Object.isFrozen(this)) {
|
|
696
|
-
// Crash only after frozen because constructor calls set.
|
|
697
|
-
throw new TypeError();
|
|
698
|
-
}
|
|
699
|
-
return super.set(key, value);
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
export function mapConstructor(entries) {
|
|
703
|
-
return freeze(new FreezeMap(entries));
|
|
704
|
-
}
|
|
705
|
-
// MapBuilder
|
|
706
|
-
export function mapBuilderConstructor(entries) {
|
|
707
|
-
return new Map();
|
|
708
|
-
}
|
|
709
|
-
export function mapBuilderRemove(builder, key) {
|
|
710
|
-
const result = builder.get(key);
|
|
711
|
-
if (builder.delete(key)) {
|
|
712
|
-
return result;
|
|
713
|
-
} else {
|
|
714
|
-
bubble();
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
export function mapBuilderSet(builder, key, value) {
|
|
718
|
-
builder.set(key, value);
|
|
719
|
-
}
|
|
720
|
-
export function mappedToMap(mapped) {
|
|
721
|
-
if (mapped instanceof FreezeMap) {
|
|
722
|
-
return mapped;
|
|
723
|
-
}
|
|
724
|
-
return freeze(new FreezeMap(mapped));
|
|
725
|
-
}
|
|
726
|
-
export function mapBuilderToMap(mapped) {
|
|
727
|
-
return freeze(new FreezeMap(mapped));
|
|
728
|
-
}
|
|
729
|
-
export function mappedToMapBuilder(mapped) {
|
|
730
|
-
return new Map(mapped);
|
|
731
|
-
}
|
|
732
|
-
// Pair
|
|
733
|
-
class Pair {
|
|
734
|
-
constructor(key, value) {
|
|
735
|
-
this.key = key;
|
|
736
|
-
this.value = value;
|
|
737
|
-
}
|
|
738
|
-
get [0]() {
|
|
739
|
-
return this.key;
|
|
740
|
-
}
|
|
741
|
-
get [1]() {
|
|
742
|
-
return this.value;
|
|
743
|
-
}
|
|
744
|
-
get length() {
|
|
745
|
-
return 2;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
export function pairConstructor(key, value) {
|
|
749
|
-
return freeze(new Pair(key, value));
|
|
750
|
-
}
|
|
751
|
-
// Mapped
|
|
752
|
-
export function mappedLength(map) {
|
|
753
|
-
return map.size;
|
|
754
|
-
}
|
|
755
|
-
export function mappedGet(map, key) {
|
|
756
|
-
const result = map.get(key);
|
|
757
|
-
// TODO Under compiler-error-free Temper, could undefined values get set?
|
|
758
|
-
// TODO Would Map<?, Void> be impossible to feed once we get checks in place?
|
|
759
|
-
if (result === undefined) {
|
|
760
|
-
bubble();
|
|
761
|
-
}
|
|
762
|
-
return result;
|
|
763
|
-
}
|
|
764
|
-
export function mappedGetOr(map, key, fallback) {
|
|
765
|
-
return map.get(key) ?? fallback;
|
|
766
|
-
}
|
|
767
|
-
export function mappedHas(map, key) {
|
|
768
|
-
return map.has(key);
|
|
769
|
-
}
|
|
770
|
-
export function mappedKeys(map) {
|
|
771
|
-
return freeze(Array.prototype.slice.call(map.keys()));
|
|
772
|
-
}
|
|
773
|
-
export function mappedValues(map) {
|
|
774
|
-
return freeze(Array.prototype.slice.call(map.values()));
|
|
775
|
-
}
|
|
776
|
-
export function mappedToList(map) {
|
|
777
|
-
return freeze(Array.from(map, ([key, value]) => new Pair(key, value)));
|
|
778
|
-
}
|
|
779
|
-
export function mappedToListWith(map, func) {
|
|
780
|
-
return freeze(Array.from(map, ([key, value]) => func(key, value)));
|
|
781
|
-
}
|
|
782
|
-
export function mappedToListBuilder(map) {
|
|
783
|
-
return freeze(Array.from(map, ([key, value]) => new Pair(key, value)));
|
|
784
|
-
}
|
|
785
|
-
export function mappedToListBuilderWith(map, func) {
|
|
786
|
-
return freeze(Array.from(map, ([key, value]) => func(key, value)));
|
|
787
|
-
}
|
|
788
|
-
export function mappedForEach(map, func) {
|
|
789
|
-
map.forEach((v, k) => func(k, v));
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
// Implements Date::constructor
|
|
793
|
-
export function dateConstructor(year, month, day) {
|
|
794
|
-
let d = new Date(0);
|
|
795
|
-
// If we were to pass year into `new Date`, then it would
|
|
796
|
-
// have 1900 added when in the range [0, 99].
|
|
797
|
-
// developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date#year
|
|
798
|
-
d.setUTCFullYear(year);
|
|
799
|
-
d.setUTCMonth(month - 1 /* JS months are zero indexed */);
|
|
800
|
-
d.setUTCDate(day); // UTCDay is day of the week
|
|
801
|
-
return d;
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
// Implements Date::today
|
|
805
|
-
/**
|
|
806
|
-
* @returns {Date}
|
|
807
|
-
*/
|
|
808
|
-
export function dateToday() {
|
|
809
|
-
let d = new Date(Date.now());
|
|
810
|
-
// Get rid of the time component.
|
|
811
|
-
d.setTime(
|
|
812
|
-
Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())
|
|
813
|
-
);
|
|
814
|
-
return d;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
// Implements Date::yearsBetween
|
|
818
|
-
/**
|
|
819
|
-
* @param {Date} start
|
|
820
|
-
* @param {Date} end
|
|
821
|
-
*
|
|
822
|
-
* @returns {number}
|
|
823
|
-
*/
|
|
824
|
-
export function dateYearsBetween(start, end) {
|
|
825
|
-
let yearDelta = end.getUTCFullYear() - start.getUTCFullYear();
|
|
826
|
-
let monthDelta = end.getUTCMonth() - start.getUTCMonth();
|
|
827
|
-
return yearDelta -
|
|
828
|
-
// If the end month/day is before the start's then we
|
|
829
|
-
// don't have a full year.
|
|
830
|
-
(monthDelta < 0 || monthDelta == 0 && end.getUTCDate() < start.getUTCDate());
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// Implements extension method Deque::constructor
|
|
834
|
-
const DEQUE_NTAKEN = Symbol("Deque::nTaken");
|
|
835
|
-
export function dequeConstructor() {
|
|
836
|
-
let deque = [];
|
|
837
|
-
Object.defineProperty(deque, DEQUE_NTAKEN, { value: 0, writable: true });
|
|
838
|
-
return deque;
|
|
839
|
-
}
|
|
840
|
-
// Implements extension method Deque::add
|
|
841
|
-
export function dequeAdd(deque, element) {
|
|
842
|
-
deque.push(element);
|
|
843
|
-
}
|
|
844
|
-
// Implements extension method Deque::isEmpty
|
|
845
|
-
export function dequeIsEmpty(deque) {
|
|
846
|
-
return deque.length === (deque[DEQUE_NTAKEN] || 0);
|
|
847
|
-
}
|
|
848
|
-
// Implements extension method Deque::removeFirst
|
|
849
|
-
export function dequeRemoveFirst(deque) {
|
|
850
|
-
// https://gist.github.com/mikesamuel/444258e7005e8fc9534d9cf274b1df58
|
|
851
|
-
let nTaken = deque[DEQUE_NTAKEN];
|
|
852
|
-
let length = deque.length;
|
|
853
|
-
if (length === nTaken) {
|
|
854
|
-
deque[DEQUE_NTAKEN] = 0;
|
|
855
|
-
deque.length = 0;
|
|
856
|
-
bubble();
|
|
857
|
-
}
|
|
858
|
-
let item = deque[nTaken];
|
|
859
|
-
let nShiftThreshhold = (length / 2) | 0;
|
|
860
|
-
if (nShiftThreshhold < 32) {
|
|
861
|
-
nShiftThreshhold = 32;
|
|
862
|
-
}
|
|
863
|
-
if (nTaken >= nShiftThreshhold) {
|
|
864
|
-
deque.splice(0, nTaken + 1);
|
|
865
|
-
deque[DEQUE_NTAKEN] = 0;
|
|
866
|
-
} else {
|
|
867
|
-
deque[nTaken] = undefined;
|
|
868
|
-
deque[DEQUE_NTAKEN] = nTaken + 1;
|
|
869
|
-
}
|
|
870
|
-
return item;
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
class DenseBitVector {
|
|
874
|
-
constructor() {
|
|
875
|
-
this.bits = [];
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
get(index) {
|
|
879
|
-
return this.bits[index] == null ? false : this.bits[index];
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
set(index, newBitValue) {
|
|
883
|
-
this.bits[index] = Boolean(newBitValue);
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
toString() {
|
|
887
|
-
return `0b${this.bits.map(Number).join("")}`;
|
|
888
|
-
}
|
|
889
|
-
toJSON() {
|
|
890
|
-
return this.bits;
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
// Implements extension method DenseBitVector::constructor
|
|
895
|
-
export function denseBitVectorConstructor(capacity) {
|
|
896
|
-
return new DenseBitVector();
|
|
897
|
-
}
|
|
898
|
-
// Implements extension method DenseBitVector::get
|
|
899
|
-
export function denseBitVectorGet(denseBitVector, index) {
|
|
900
|
-
return denseBitVector.get(index);
|
|
901
|
-
}
|
|
902
|
-
// Implements extension method DenseBitVector::set
|
|
903
|
-
export function denseBitVectorSet(denseBitVector, index, newBitValue) {
|
|
904
|
-
return denseBitVector.set(index, newBitValue);
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
// Implements extension method Boolean::toString
|
|
908
|
-
export function booleanToString(b) {
|
|
909
|
-
return b ? "true" : "false";
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
// Implements Symbol construction.
|
|
913
|
-
export function symbolFor(text) {
|
|
914
|
-
return Symbol.for(text);
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
// Stubs out static property verification
|
|
918
|
-
export function getStatic(reifiedType, symbol) {
|
|
919
|
-
return undefined; // TODO(bps, #780)
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
const String = "".constructor;
|
|
923
|
-
const { isArray } = Array;
|
|
924
|
-
const { isSafeInteger } = Number;
|
|
925
|
-
const { trunc } = Math;
|
|
926
|
-
const { freeze } = Object;
|
|
927
|
-
|
|
928
|
-
export {
|
|
929
|
-
// Export reliable paths to JS builtins, so they can import them
|
|
930
|
-
// via an unambiguous name locally and not worry about masking.
|
|
931
|
-
isArray,
|
|
932
|
-
isSafeInteger,
|
|
933
|
-
};
|
|
934
|
-
|
|
935
|
-
// Export runtime value type checks used for safe casting
|
|
936
|
-
|
|
937
|
-
export function requireIsArray(x) {
|
|
938
|
-
if (!isArray(x)) {
|
|
939
|
-
bubble();
|
|
940
|
-
}
|
|
941
|
-
return x;
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
export function requireInstanceOf(x, typeRequirement) {
|
|
945
|
-
if (!(x instanceof typeRequirement)) {
|
|
946
|
-
bubble();
|
|
947
|
-
}
|
|
948
|
-
return x;
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
export function requireIsSafeInteger(x) {
|
|
952
|
-
if (!isSafeInteger(x)) {
|
|
953
|
-
bubble();
|
|
954
|
-
}
|
|
955
|
-
return x;
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
export function requireSame(x, y) {
|
|
959
|
-
if (x !== y) {
|
|
960
|
-
bubble();
|
|
961
|
-
}
|
|
962
|
-
return x;
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
export function requireTypeOf(x, typeOfString) {
|
|
966
|
-
if (typeof x !== typeOfString) {
|
|
967
|
-
bubble();
|
|
968
|
-
}
|
|
969
|
-
return x;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
// When we need a reference to builtin that normally we inline
|
|
973
|
-
export function bitwiseAnd(a, b) {
|
|
974
|
-
return a & b;
|
|
975
|
-
}
|
|
976
|
-
export function bitwiseOr(a, b) {
|
|
977
|
-
return a | b;
|
|
978
|
-
}
|
|
979
|
-
export function booleanNegation(b) {
|
|
980
|
-
return !b;
|
|
981
|
-
}
|
|
982
|
-
export function divDubDub(x, y) {
|
|
983
|
-
return x / y;
|
|
984
|
-
}
|
|
985
|
-
export function divIntInt(x, y) {
|
|
986
|
-
const result = trunc(x / y);
|
|
987
|
-
if (!isSafeInteger(result)) {
|
|
988
|
-
bubble();
|
|
989
|
-
}
|
|
990
|
-
/* not NaN or infinite */
|
|
991
|
-
return result;
|
|
992
|
-
}
|
|
993
|
-
export function modIntInt(x, y) {
|
|
994
|
-
const result = trunc(x % y);
|
|
995
|
-
if (!isSafeInteger(result)) {
|
|
996
|
-
bubble();
|
|
997
|
-
}
|
|
998
|
-
/* not NaN or infinite */
|
|
999
|
-
return result;
|
|
1000
|
-
}
|
|
1001
|
-
export function minusDub(x) {
|
|
1002
|
-
return -x;
|
|
1003
|
-
}
|
|
1004
|
-
export function minusInt(x) {
|
|
1005
|
-
return -x;
|
|
1006
|
-
}
|
|
1007
|
-
export function minusDubDub(x, y) {
|
|
1008
|
-
return x - y;
|
|
1009
|
-
}
|
|
1010
|
-
export function minusIntInt(x, y) {
|
|
1011
|
-
return x - y;
|
|
1012
|
-
}
|
|
1013
|
-
export function plusDub(x) {
|
|
1014
|
-
return +x;
|
|
1015
|
-
}
|
|
1016
|
-
export function plusInt(x) {
|
|
1017
|
-
return +x;
|
|
1018
|
-
}
|
|
1019
|
-
export function plusDubDub(x, y) {
|
|
1020
|
-
return x + y;
|
|
1021
|
-
}
|
|
1022
|
-
export function plusIntInt(x, y) {
|
|
1023
|
-
return x + y;
|
|
1024
|
-
}
|
|
1025
|
-
export function timesDubDub(x, y) {
|
|
1026
|
-
return x * y;
|
|
1027
|
-
}
|
|
1028
|
-
export function timesIntInt(x, y) {
|
|
1029
|
-
return x * y;
|
|
1030
|
-
}
|
|
1031
|
-
export function strCat(...args) {
|
|
1032
|
-
let s = "";
|
|
1033
|
-
for (let arg of args) {
|
|
1034
|
-
s += String(arg); // Does not throw on Symbols
|
|
1035
|
-
}
|
|
1036
|
-
return s;
|
|
1037
|
-
}
|
|
1038
|
-
export function listify(...args) {
|
|
1039
|
-
return freeze(args);
|
|
1040
|
-
}
|
|
1041
|
-
export function cmpGeneric(a, b) {
|
|
1042
|
-
if (typeof a === "string" && typeof b === "string") {
|
|
1043
|
-
if (Object.is(a, b)) {
|
|
1044
|
-
return 0;
|
|
1045
|
-
}
|
|
1046
|
-
const aLen = a.length;
|
|
1047
|
-
const bLen = b.length;
|
|
1048
|
-
const minLen = aLen < bLen ? aLen : bLen;
|
|
1049
|
-
for (let i = 0; i < minLen; ) {
|
|
1050
|
-
const ca = a.codePointAt(i);
|
|
1051
|
-
const cb = b.codePointAt(i);
|
|
1052
|
-
const d = ca - cb;
|
|
1053
|
-
if (d !== 0) {
|
|
1054
|
-
return d;
|
|
1055
|
-
}
|
|
1056
|
-
i += ca < 0x10000 ? 1 : 2;
|
|
1057
|
-
}
|
|
1058
|
-
return aLen - bLen;
|
|
1059
|
-
}
|
|
1060
|
-
if (typeof a === "number" && typeof b === "number") {
|
|
1061
|
-
if (Object.is(a, b)) {
|
|
1062
|
-
return 0;
|
|
1063
|
-
}
|
|
1064
|
-
if (a === b) {
|
|
1065
|
-
return Object.is(a, 0) - Object.is(b, 0);
|
|
1066
|
-
}
|
|
1067
|
-
if (isNaN(a) || isNaN(b)) {
|
|
1068
|
-
return isNaN(a) - isNaN(b);
|
|
1069
|
-
}
|
|
1070
|
-
return a - b;
|
|
1071
|
-
}
|
|
1072
|
-
if (typeof a === "boolean" && typeof b === "boolean") {
|
|
1073
|
-
return a - b;
|
|
1074
|
-
}
|
|
1075
|
-
bubble();
|
|
1076
|
-
};
|
|
1077
|
-
export function ltGeneric(a, b) {
|
|
1078
|
-
if (typeof a === "number" && typeof b === "number") {
|
|
1079
|
-
return (
|
|
1080
|
-
(isNaN(b) && !isNaN(a)) ||
|
|
1081
|
-
a < b ||
|
|
1082
|
-
(a === 0 && b === 0 && Object.is(a, 0) < Object.is(b, 0))
|
|
1083
|
-
);
|
|
1084
|
-
}
|
|
1085
|
-
if (typeof a == "boolean" && typeof b === "boolean") {
|
|
1086
|
-
return a < b;
|
|
1087
|
-
}
|
|
1088
|
-
return cmpGeneric(a, b) < 0;
|
|
1089
|
-
}
|
|
1090
|
-
export function leGeneric(a, b) {
|
|
1091
|
-
if (typeof a === "number" && typeof b === "number") {
|
|
1092
|
-
return (
|
|
1093
|
-
isNaN(b) ||
|
|
1094
|
-
(a <= b && (a !== 0 || b !== 0 || Object.is(a, 0) <= Object.is(b, 0)))
|
|
1095
|
-
);
|
|
1096
|
-
}
|
|
1097
|
-
if (typeof a == "boolean" && typeof b === "boolean") {
|
|
1098
|
-
return a <= b;
|
|
1099
|
-
}
|
|
1100
|
-
return cmpGeneric(a, b) <= 0;
|
|
1101
|
-
}
|
|
1102
|
-
export function gtGeneric(a, b) {
|
|
1103
|
-
if (typeof a === "number" && typeof b === "number") {
|
|
1104
|
-
return (
|
|
1105
|
-
(isNaN(a) && !isNaN(b)) ||
|
|
1106
|
-
a > b ||
|
|
1107
|
-
(a === 0 && b === 0 && Object.is(a, 0) > Object.is(b, 0))
|
|
1108
|
-
);
|
|
1109
|
-
}
|
|
1110
|
-
if (typeof a == "boolean" && typeof b === "boolean") {
|
|
1111
|
-
return a > b;
|
|
1112
|
-
}
|
|
1113
|
-
return cmpGeneric(a, b) > 0;
|
|
1114
|
-
}
|
|
1115
|
-
export function geGeneric(a, b) {
|
|
1116
|
-
if (typeof a === "number" && typeof b === "number") {
|
|
1117
|
-
return (
|
|
1118
|
-
isNaN(a) ||
|
|
1119
|
-
(a >= b && (a !== 0 || b !== 0 || Object.is(a, 0) >= Object.is(b, 0)))
|
|
1120
|
-
);
|
|
1121
|
-
}
|
|
1122
|
-
if (typeof a == "boolean" && typeof b === "boolean") {
|
|
1123
|
-
return a >= b;
|
|
1124
|
-
}
|
|
1125
|
-
return cmpGeneric(a, b) >= 0;
|
|
1126
|
-
}
|
|
1127
|
-
export function eqGeneric(a, b) {
|
|
1128
|
-
return Object.is(a, b);
|
|
1129
|
-
}
|
|
1130
|
-
export function neGeneric(a, b) {
|
|
1131
|
-
return !Object.is(a, b);
|
|
1132
|
-
}
|
|
1133
|
-
export function bubble() {
|
|
1134
|
-
throw Error();
|
|
1135
|
-
}
|
|
1136
|
-
export function print(a) {
|
|
1137
|
-
console.log("%s", a);
|
|
1138
|
-
return void 0;
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
export function adaptGenerator(generator) {
|
|
1142
|
-
return () => generator.next();
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
// We might customize this in the future, but actual global console works today.
|
|
1146
|
-
export const globalConsole = console;
|
|
13
|
+
export * from "./string.js";
|