@temperlang/core 0.2.1 → 0.3.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/index.js +138 -29
- package/package.json +1 -1
- package/regex.js +7 -7
package/index.js
CHANGED
|
@@ -39,7 +39,16 @@ export function stringToInt(s) {
|
|
|
39
39
|
return result;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* @typedef StringSlice
|
|
44
|
+
*/
|
|
45
|
+
let StringSlice;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Specifically for utf8 and utf32, since utf16 is simpler in js.
|
|
49
|
+
*
|
|
50
|
+
* @implements StringSlice
|
|
51
|
+
*/
|
|
43
52
|
class TrickyStringSlice {
|
|
44
53
|
hasAtLeast(count) {
|
|
45
54
|
// Repeated calls to hasAtLeast are potentially expensive.
|
|
@@ -203,6 +212,40 @@ class Utf8StringSlice extends TrickyStringSlice {
|
|
|
203
212
|
: new Utf8StringSlice(this.content, this.left, newRight);
|
|
204
213
|
}
|
|
205
214
|
|
|
215
|
+
/**
|
|
216
|
+
* @param {StringSlice} slice
|
|
217
|
+
* @return {Utf8StringSlice}
|
|
218
|
+
*/
|
|
219
|
+
intersect(slice) {
|
|
220
|
+
let { content, left, right } = this;
|
|
221
|
+
let { left: otherLeft, right: otherRight } = slice;
|
|
222
|
+
|
|
223
|
+
// Derivation of this in StringSliceHelpers
|
|
224
|
+
let newLeft, newRight;
|
|
225
|
+
if (otherLeft >= right) {
|
|
226
|
+
newLeft = newRight = right;
|
|
227
|
+
} else if (otherRight <= left) {
|
|
228
|
+
newLeft = newLeft = left;
|
|
229
|
+
} else {
|
|
230
|
+
newLeft = Math.max(left, otherLeft);
|
|
231
|
+
newRight = Math.min(right, otherRight);
|
|
232
|
+
}
|
|
233
|
+
return newLeft === left && newRight === right
|
|
234
|
+
? this : new Utf8StringSlice(content, newLeft, newRight);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @param {StringSlice} slice
|
|
239
|
+
* @returns {Utf8StringSlice}
|
|
240
|
+
*/
|
|
241
|
+
excludeAfter(slice) {
|
|
242
|
+
let { content, left, right } = this;
|
|
243
|
+
let { left: otherLeft } = slice;
|
|
244
|
+
let newRight = Math.max(left, Math.min(right, otherLeft));
|
|
245
|
+
return right === newRight
|
|
246
|
+
? this : new Utf8StringSlice(content, left, newRight);
|
|
247
|
+
}
|
|
248
|
+
|
|
206
249
|
[Symbol.iterator]() {
|
|
207
250
|
function* bytes(content, left, limit) {
|
|
208
251
|
let i = left;
|
|
@@ -230,6 +273,9 @@ class Utf8StringSlice extends TrickyStringSlice {
|
|
|
230
273
|
}
|
|
231
274
|
}
|
|
232
275
|
|
|
276
|
+
/**
|
|
277
|
+
* @implements StringSlice
|
|
278
|
+
*/
|
|
233
279
|
class Utf16StringSlice {
|
|
234
280
|
constructor(content, left = 0, right = content.length) {
|
|
235
281
|
this.content = content;
|
|
@@ -296,6 +342,40 @@ class Utf16StringSlice {
|
|
|
296
342
|
: new Utf16StringSlice(this.content, this.left, newRight);
|
|
297
343
|
}
|
|
298
344
|
|
|
345
|
+
/**
|
|
346
|
+
* @param {StringSlice} slice
|
|
347
|
+
* @return {Utf16StringSlice}
|
|
348
|
+
*/
|
|
349
|
+
intersect(slice) {
|
|
350
|
+
let { content, left, right } = this;
|
|
351
|
+
let { left: otherLeft, right: otherRight } = slice;
|
|
352
|
+
|
|
353
|
+
// Derivation of this in StringSliceHelpers
|
|
354
|
+
let newLeft, newRight;
|
|
355
|
+
if (otherLeft >= right) {
|
|
356
|
+
newLeft = newRight = right;
|
|
357
|
+
} else if (otherRight <= left) {
|
|
358
|
+
newLeft = newLeft = left;
|
|
359
|
+
} else {
|
|
360
|
+
newLeft = Math.max(left, otherLeft);
|
|
361
|
+
newRight = Math.min(right, otherRight);
|
|
362
|
+
}
|
|
363
|
+
return newLeft === left && newRight === right
|
|
364
|
+
? this : new Utf16StringSlice(content, newLeft, newRight);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* @param {StringSlice} slice
|
|
369
|
+
* @returns {Utf16StringSlice}
|
|
370
|
+
*/
|
|
371
|
+
excludeAfter(slice) {
|
|
372
|
+
let { content, left, right } = this;
|
|
373
|
+
let { left: otherLeft } = slice;
|
|
374
|
+
let newRight = Math.max(left, Math.min(right, otherLeft));
|
|
375
|
+
return right === newRight
|
|
376
|
+
? this : new Utf16StringSlice(content, left, newRight);
|
|
377
|
+
}
|
|
378
|
+
|
|
299
379
|
[Symbol.iterator]() {
|
|
300
380
|
function* chars(content, left, limit) {
|
|
301
381
|
let i = left;
|
|
@@ -312,7 +392,7 @@ class Utf16StringSlice {
|
|
|
312
392
|
}
|
|
313
393
|
}
|
|
314
394
|
|
|
315
|
-
class
|
|
395
|
+
class CodePointStringSlice extends TrickyStringSlice {
|
|
316
396
|
constructor(content, left = 0, right = content.length) {
|
|
317
397
|
super();
|
|
318
398
|
this.content = content;
|
|
@@ -383,24 +463,57 @@ class CodePointsStringSlice extends TrickyStringSlice {
|
|
|
383
463
|
|
|
384
464
|
/**
|
|
385
465
|
* @param {number} count
|
|
386
|
-
* @return {
|
|
466
|
+
* @return {CodePointStringSlice}
|
|
387
467
|
*/
|
|
388
468
|
advance(count) {
|
|
389
469
|
let newLeft = this._advanceLeft(count);
|
|
390
470
|
return (newLeft === this.left)
|
|
391
471
|
? this
|
|
392
|
-
: new
|
|
472
|
+
: new CodePointStringSlice(this.content, newLeft, this.right);
|
|
393
473
|
}
|
|
394
474
|
|
|
395
475
|
/**
|
|
396
476
|
* @param {number} count
|
|
397
|
-
* @return {
|
|
477
|
+
* @return {CodePointStringSlice}
|
|
398
478
|
*/
|
|
399
479
|
limit(count) {
|
|
400
480
|
let newRight = this._advanceLeft(count);
|
|
401
481
|
return (newRight === this.right)
|
|
402
482
|
? this
|
|
403
|
-
: new
|
|
483
|
+
: new CodePointStringSlice(this.content, this.left, newRight);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* @param {StringSlice} slice
|
|
488
|
+
* @return {CodePointStringSlice}
|
|
489
|
+
*/
|
|
490
|
+
intersect(slice) {
|
|
491
|
+
let { content, left, right } = this;
|
|
492
|
+
let { left: otherLeft, right: otherRight } = slice;
|
|
493
|
+
|
|
494
|
+
// Derivation of this in StringSliceHelpers
|
|
495
|
+
let newLeft, newRight;
|
|
496
|
+
if (otherLeft >= right) {
|
|
497
|
+
newLeft = newRight = right;
|
|
498
|
+
} else if (otherRight <= left) {
|
|
499
|
+
newLeft = newLeft = left;
|
|
500
|
+
} else {
|
|
501
|
+
newLeft = Math.max(left, otherLeft);
|
|
502
|
+
newRight = Math.min(right, otherRight);
|
|
503
|
+
}
|
|
504
|
+
return newLeft === left && newRight === right
|
|
505
|
+
? this : new CodePointStringSlice(content, newLeft, newRight);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* @param {StringSlice} slice
|
|
510
|
+
* @returns {CodePointStringSlice}
|
|
511
|
+
*/
|
|
512
|
+
excludeAfter(slice) {
|
|
513
|
+
let { content, left, right } = this;
|
|
514
|
+
let { left: otherLeft } = slice;
|
|
515
|
+
let newRight = Math.max(left, Math.min(right, otherLeft));
|
|
516
|
+
return right === newRight ? this : new CodePointStringSlice(content, left, newRight);
|
|
404
517
|
}
|
|
405
518
|
|
|
406
519
|
[Symbol.iterator]() {
|
|
@@ -432,7 +545,7 @@ export function stringUtf16(string) {
|
|
|
432
545
|
|
|
433
546
|
// Implements extension method String::codePoints
|
|
434
547
|
export function stringCodePoints(string) {
|
|
435
|
-
return new
|
|
548
|
+
return new CodePointStringSlice(string);
|
|
436
549
|
}
|
|
437
550
|
|
|
438
551
|
// Implements extension method Int::toString
|
|
@@ -550,8 +663,8 @@ export function listBuilderAddAll(ls, newItems, at) {
|
|
|
550
663
|
ls.splice(at, 0, ...newItems);
|
|
551
664
|
}
|
|
552
665
|
}
|
|
553
|
-
// Implements extension method
|
|
554
|
-
export function
|
|
666
|
+
// Implements extension method Listed::filter
|
|
667
|
+
export function listedFilter(ls, predicate) {
|
|
555
668
|
let filtered = null;
|
|
556
669
|
let nFiltered = 0; // Just past index of last element of ls filtered onto filtered
|
|
557
670
|
let { length } = ls;
|
|
@@ -575,16 +688,16 @@ export function listFilter(ls, predicate) {
|
|
|
575
688
|
}
|
|
576
689
|
return freeze(fullyFiltered);
|
|
577
690
|
}
|
|
578
|
-
// Implements extension method
|
|
579
|
-
export function
|
|
691
|
+
// Implements extension method Listed::get
|
|
692
|
+
export function listedGet(ls, i) {
|
|
580
693
|
let { length } = ls;
|
|
581
694
|
if (0 <= i && i < length) {
|
|
582
695
|
return ls[i];
|
|
583
696
|
}
|
|
584
697
|
bubble();
|
|
585
698
|
}
|
|
586
|
-
// Implements extension method
|
|
587
|
-
export function
|
|
699
|
+
// Implements extension method Listed::getOr
|
|
700
|
+
export function listedGetOr(ls, i, fallback) {
|
|
588
701
|
let { length } = ls;
|
|
589
702
|
return 0 <= i && i < length ? ls[i] : fallback;
|
|
590
703
|
}
|
|
@@ -592,8 +705,8 @@ export function listGetOr(ls, i, fallback) {
|
|
|
592
705
|
export function listIsEmpty(ls) {
|
|
593
706
|
return !ls.length;
|
|
594
707
|
}
|
|
595
|
-
// Implements extension method
|
|
596
|
-
export function
|
|
708
|
+
// Implements extension method Listed::join
|
|
709
|
+
export function listedJoin(ls, separator, elementStringifier) {
|
|
597
710
|
let joined = "";
|
|
598
711
|
let { length } = ls;
|
|
599
712
|
for (let i = 0; i < length; ++i) {
|
|
@@ -606,16 +719,12 @@ export function listJoin(ls, separator, elementStringifier) {
|
|
|
606
719
|
}
|
|
607
720
|
return joined;
|
|
608
721
|
}
|
|
609
|
-
// Implements extension method
|
|
610
|
-
export function
|
|
611
|
-
return ls.length;
|
|
612
|
-
}
|
|
613
|
-
// Implements extension method List::mapDropping
|
|
614
|
-
export function listMapDropping() {
|
|
722
|
+
// Implements extension method Listed::mapDropping
|
|
723
|
+
export function listedMapDropping() {
|
|
615
724
|
throw new Error("TODO List::mapDropping");
|
|
616
725
|
}
|
|
617
|
-
// Implements extension method
|
|
618
|
-
export function
|
|
726
|
+
// Implements extension method Listed::map
|
|
727
|
+
export function listedMap(ls, transform) {
|
|
619
728
|
let mapped = [];
|
|
620
729
|
let { length } = ls;
|
|
621
730
|
for (let i = 0; i < length; ++i) {
|
|
@@ -624,6 +733,10 @@ export function listMap(ls, transform) {
|
|
|
624
733
|
}
|
|
625
734
|
return freeze(mapped);
|
|
626
735
|
}
|
|
736
|
+
// Implements extension method Listed::reduceFrom
|
|
737
|
+
export function listedReduceFrom(ls, initial, accumulate) {
|
|
738
|
+
return ls.reduce(accumulate, initial);
|
|
739
|
+
}
|
|
627
740
|
// Implements extension method Listed::toList
|
|
628
741
|
export function listedToList(ls) {
|
|
629
742
|
if (Object.isFrozen(ls)) {
|
|
@@ -670,8 +783,8 @@ export function listBuilderSplice(ls, index, removeCount, newValues) {
|
|
|
670
783
|
export function listBuilderToList(ls) {
|
|
671
784
|
return freeze(ls.slice());
|
|
672
785
|
}
|
|
673
|
-
// Implements extension method
|
|
674
|
-
export function
|
|
786
|
+
// Implements extension method Listed::slice
|
|
787
|
+
export function listedSlice(ls, startInclusive, endExclusive) {
|
|
675
788
|
if (startInclusive < 0) {
|
|
676
789
|
startInclusive = 0;
|
|
677
790
|
}
|
|
@@ -1138,9 +1251,5 @@ export function print(a) {
|
|
|
1138
1251
|
return void 0;
|
|
1139
1252
|
}
|
|
1140
1253
|
|
|
1141
|
-
export function adaptGenerator(generator) {
|
|
1142
|
-
return () => generator.next();
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
1254
|
// We might customize this in the future, but actual global console works today.
|
|
1146
1255
|
export const globalConsole = console;
|
package/package.json
CHANGED
package/regex.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function regexCompiledFound(_, compiled, text) {
|
|
2
2
|
return compiled.test(text);
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
export function
|
|
6
|
-
const match =
|
|
5
|
+
export function regexCompiledFind(_, compiled, text, regexRefs) {
|
|
6
|
+
const match = regexCompiledFindEx(_, compiled, text, regexRefs);
|
|
7
7
|
if (match === undefined) {
|
|
8
8
|
// We could just fail on `undefined.groups`, but that seems accidental.
|
|
9
9
|
throw Error();
|
|
@@ -15,7 +15,7 @@ export function compiledRegexCompiledFind(_, compiled, text, regexRefs) {
|
|
|
15
15
|
* @param {RegExp} compiled
|
|
16
16
|
* @param {string} text
|
|
17
17
|
*/
|
|
18
|
-
function
|
|
18
|
+
function regexCompiledFindEx(_, compiled, text, regexRefs) {
|
|
19
19
|
const match = compiled.exec(text);
|
|
20
20
|
if (match === null) {
|
|
21
21
|
return undefined;
|
|
@@ -74,7 +74,7 @@ function codePointIndices(text, unitNameIndexArray) {
|
|
|
74
74
|
* @param {(groups: Map<string, any>) => string} format
|
|
75
75
|
* @returns {string}
|
|
76
76
|
*/
|
|
77
|
-
export function
|
|
77
|
+
export function regexCompiledReplace(
|
|
78
78
|
_,
|
|
79
79
|
compiled,
|
|
80
80
|
text,
|
|
@@ -85,7 +85,7 @@ export function compiledRegexCompiledReplace(
|
|
|
85
85
|
// make our interface consistent, so we have to do this manually here.
|
|
86
86
|
// The hope is that we can optimize a bunch out when we have compile-time
|
|
87
87
|
// contant patterns and customized match result types.
|
|
88
|
-
let match =
|
|
88
|
+
let match = regexCompiledFindEx(_, compiled, text, regexRefs);
|
|
89
89
|
if (match === undefined) {
|
|
90
90
|
// Manually handle no match case for our manual replace logic.
|
|
91
91
|
return text;
|
|
@@ -96,7 +96,7 @@ export function compiledRegexCompiledReplace(
|
|
|
96
96
|
return text.slice(0, index) + content + text.slice(index + length);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
export function
|
|
99
|
+
export function regexCompileFormatted(_, formatted) {
|
|
100
100
|
return new RegExp(formatted, "du"); // d:hasIndices, u:unicode
|
|
101
101
|
}
|
|
102
102
|
|