@temperlang/core 0.0.6 → 0.2.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 +128 -66
- package/interface-types.js +0 -0
- package/package.json +1 -1
- package/regex.js +14 -16
package/index.js
CHANGED
|
@@ -1,19 +1,42 @@
|
|
|
1
1
|
export * from "./interface-types.js";
|
|
2
2
|
export * from "./regex.js";
|
|
3
3
|
|
|
4
|
-
export const bubbleException = new (class BubbleException extends Error {
|
|
5
|
-
constructor() {
|
|
6
|
-
super("Bubble");
|
|
7
|
-
}
|
|
8
|
-
})();
|
|
9
|
-
|
|
10
4
|
// Implements extension method String::isEmpty
|
|
11
5
|
export function stringIsEmpty(s) {
|
|
12
6
|
return s === "";
|
|
13
7
|
}
|
|
8
|
+
|
|
14
9
|
// Implements extension method String::split
|
|
15
10
|
export function stringSplit(s, separator) {
|
|
16
|
-
return s.split(separator).map((s) => s);
|
|
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;
|
|
17
40
|
}
|
|
18
41
|
|
|
19
42
|
/** Specifically for utf8 and utf32, since utf16 is simpler in js. */
|
|
@@ -114,7 +137,7 @@ class Utf8StringSlice extends TrickyStringSlice {
|
|
|
114
137
|
let left = this.left;
|
|
115
138
|
let right = this.right;
|
|
116
139
|
if (left >= right) {
|
|
117
|
-
|
|
140
|
+
bubble();
|
|
118
141
|
}
|
|
119
142
|
|
|
120
143
|
let content = this.content;
|
|
@@ -238,7 +261,7 @@ class Utf16StringSlice {
|
|
|
238
261
|
let left = this.left;
|
|
239
262
|
let right = this.right;
|
|
240
263
|
if (left >= right) {
|
|
241
|
-
|
|
264
|
+
bubble();
|
|
242
265
|
}
|
|
243
266
|
return this.content.charCodeAt(left);
|
|
244
267
|
}
|
|
@@ -329,7 +352,7 @@ class CodePointsStringSlice extends TrickyStringSlice {
|
|
|
329
352
|
|
|
330
353
|
read() {
|
|
331
354
|
if (this.left >= this.right) {
|
|
332
|
-
|
|
355
|
+
bubble();
|
|
333
356
|
}
|
|
334
357
|
return this.content.codePointAt(this.left);
|
|
335
358
|
}
|
|
@@ -435,7 +458,7 @@ export function float64ToInt(n) {
|
|
|
435
458
|
if (Math.abs(n - i) < 1) {
|
|
436
459
|
return i;
|
|
437
460
|
} else {
|
|
438
|
-
|
|
461
|
+
bubble();
|
|
439
462
|
}
|
|
440
463
|
}
|
|
441
464
|
|
|
@@ -454,27 +477,18 @@ export function float64ToIntUnsafe(n) {
|
|
|
454
477
|
export function float64ToString(n) {
|
|
455
478
|
// TODO(mikesamuel, issue#579): need functional test to nail down
|
|
456
479
|
// double formatting threshholds.
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
return "
|
|
468
|
-
|
|
469
|
-
let result = n.toString();
|
|
470
|
-
// Rely on eagerness and js number formatting rules here.
|
|
471
|
-
const groups = /(-?[0-9]+)(\.[0-9]+)?(.+)?/.exec(result);
|
|
472
|
-
if (groups === null) {
|
|
473
|
-
return result;
|
|
474
|
-
} else {
|
|
475
|
-
// Guarantee a decimal point for floats.
|
|
476
|
-
return `${groups[1]}${groups[2] || ".0"}${groups[3] || ""}`;
|
|
477
|
-
}
|
|
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
|
+
}
|
|
478
492
|
}
|
|
479
493
|
}
|
|
480
494
|
|
|
@@ -512,10 +526,6 @@ const byteInfos = [
|
|
|
512
526
|
{ andMask: 0b0011_1111, orMask: 0b1000_0000, shift: 0 },
|
|
513
527
|
];
|
|
514
528
|
|
|
515
|
-
function freeze(items) {
|
|
516
|
-
return Object.freeze(items);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
529
|
// Implements extension method ListBuilder::add
|
|
520
530
|
export function listBuilderAdd(ls, newItem, at) {
|
|
521
531
|
if (at === undefined) {
|
|
@@ -524,7 +534,7 @@ export function listBuilderAdd(ls, newItem, at) {
|
|
|
524
534
|
ls.push(newItem);
|
|
525
535
|
} else {
|
|
526
536
|
if (at < 0 || at > ls.length) {
|
|
527
|
-
|
|
537
|
+
bubble();
|
|
528
538
|
}
|
|
529
539
|
ls.splice(at, 0, newItem);
|
|
530
540
|
}
|
|
@@ -535,7 +545,7 @@ export function listBuilderAddAll(ls, newItems, at) {
|
|
|
535
545
|
ls.push(...newItems);
|
|
536
546
|
} else {
|
|
537
547
|
if (at < 0 || at > ls.length) {
|
|
538
|
-
|
|
548
|
+
bubble();
|
|
539
549
|
}
|
|
540
550
|
ls.splice(at, 0, ...newItems);
|
|
541
551
|
}
|
|
@@ -571,7 +581,7 @@ export function listGet(ls, i) {
|
|
|
571
581
|
if (0 <= i && i < length) {
|
|
572
582
|
return ls[i];
|
|
573
583
|
}
|
|
574
|
-
|
|
584
|
+
bubble();
|
|
575
585
|
}
|
|
576
586
|
// Implements extension method List::getOr
|
|
577
587
|
export function listGetOr(ls, i, fallback) {
|
|
@@ -627,7 +637,7 @@ export function listBuilderRemoveLast(ls) {
|
|
|
627
637
|
if (ls.length) {
|
|
628
638
|
return ls.pop();
|
|
629
639
|
} else {
|
|
630
|
-
|
|
640
|
+
bubble();
|
|
631
641
|
}
|
|
632
642
|
}
|
|
633
643
|
// Implements extension method ListBuilder::reverse
|
|
@@ -690,7 +700,7 @@ class FreezeMap extends Map {
|
|
|
690
700
|
}
|
|
691
701
|
}
|
|
692
702
|
export function mapConstructor(entries) {
|
|
693
|
-
return
|
|
703
|
+
return freeze(new FreezeMap(entries));
|
|
694
704
|
}
|
|
695
705
|
// MapBuilder
|
|
696
706
|
export function mapBuilderConstructor(entries) {
|
|
@@ -701,14 +711,23 @@ export function mapBuilderRemove(builder, key) {
|
|
|
701
711
|
if (builder.delete(key)) {
|
|
702
712
|
return result;
|
|
703
713
|
} else {
|
|
704
|
-
|
|
714
|
+
bubble();
|
|
705
715
|
}
|
|
706
716
|
}
|
|
707
717
|
export function mapBuilderSet(builder, key, value) {
|
|
708
718
|
builder.set(key, value);
|
|
709
719
|
}
|
|
710
|
-
export function
|
|
711
|
-
|
|
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);
|
|
712
731
|
}
|
|
713
732
|
// Pair
|
|
714
733
|
class Pair {
|
|
@@ -727,20 +746,47 @@ class Pair {
|
|
|
727
746
|
}
|
|
728
747
|
}
|
|
729
748
|
export function pairConstructor(key, value) {
|
|
730
|
-
return
|
|
749
|
+
return freeze(new Pair(key, value));
|
|
731
750
|
}
|
|
732
751
|
// Mapped
|
|
752
|
+
export function mappedLength(map) {
|
|
753
|
+
return map.size;
|
|
754
|
+
}
|
|
733
755
|
export function mappedGet(map, key) {
|
|
734
756
|
const result = map.get(key);
|
|
735
757
|
// TODO Under compiler-error-free Temper, could undefined values get set?
|
|
736
758
|
// TODO Would Map<?, Void> be impossible to feed once we get checks in place?
|
|
737
759
|
if (result === undefined) {
|
|
738
|
-
|
|
760
|
+
bubble();
|
|
739
761
|
}
|
|
740
762
|
return result;
|
|
741
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
|
+
}
|
|
742
776
|
export function mappedToList(map) {
|
|
743
|
-
return Array.from(map, ([key, value]) => new Pair(key, value));
|
|
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));
|
|
744
790
|
}
|
|
745
791
|
|
|
746
792
|
// Implements Date::constructor
|
|
@@ -807,7 +853,7 @@ export function dequeRemoveFirst(deque) {
|
|
|
807
853
|
if (length === nTaken) {
|
|
808
854
|
deque[DEQUE_NTAKEN] = 0;
|
|
809
855
|
deque.length = 0;
|
|
810
|
-
|
|
856
|
+
bubble();
|
|
811
857
|
}
|
|
812
858
|
let item = deque[nTaken];
|
|
813
859
|
let nShiftThreshhold = (length / 2) | 0;
|
|
@@ -877,6 +923,7 @@ const String = "".constructor;
|
|
|
877
923
|
const { isArray } = Array;
|
|
878
924
|
const { isSafeInteger } = Number;
|
|
879
925
|
const { trunc } = Math;
|
|
926
|
+
const { freeze } = Object;
|
|
880
927
|
|
|
881
928
|
export {
|
|
882
929
|
// Export reliable paths to JS builtins, so they can import them
|
|
@@ -889,35 +936,35 @@ export {
|
|
|
889
936
|
|
|
890
937
|
export function requireIsArray(x) {
|
|
891
938
|
if (!isArray(x)) {
|
|
892
|
-
|
|
939
|
+
bubble();
|
|
893
940
|
}
|
|
894
941
|
return x;
|
|
895
942
|
}
|
|
896
943
|
|
|
897
944
|
export function requireInstanceOf(x, typeRequirement) {
|
|
898
945
|
if (!(x instanceof typeRequirement)) {
|
|
899
|
-
|
|
946
|
+
bubble();
|
|
900
947
|
}
|
|
901
948
|
return x;
|
|
902
949
|
}
|
|
903
950
|
|
|
904
951
|
export function requireIsSafeInteger(x) {
|
|
905
952
|
if (!isSafeInteger(x)) {
|
|
906
|
-
|
|
953
|
+
bubble();
|
|
907
954
|
}
|
|
908
955
|
return x;
|
|
909
956
|
}
|
|
910
957
|
|
|
911
958
|
export function requireSame(x, y) {
|
|
912
959
|
if (x !== y) {
|
|
913
|
-
|
|
960
|
+
bubble();
|
|
914
961
|
}
|
|
915
962
|
return x;
|
|
916
963
|
}
|
|
917
964
|
|
|
918
965
|
export function requireTypeOf(x, typeOfString) {
|
|
919
966
|
if (typeof x !== typeOfString) {
|
|
920
|
-
|
|
967
|
+
bubble();
|
|
921
968
|
}
|
|
922
969
|
return x;
|
|
923
970
|
}
|
|
@@ -938,7 +985,7 @@ export function divDubDub(x, y) {
|
|
|
938
985
|
export function divIntInt(x, y) {
|
|
939
986
|
const result = trunc(x / y);
|
|
940
987
|
if (!isSafeInteger(result)) {
|
|
941
|
-
|
|
988
|
+
bubble();
|
|
942
989
|
}
|
|
943
990
|
/* not NaN or infinite */
|
|
944
991
|
return result;
|
|
@@ -946,7 +993,7 @@ export function divIntInt(x, y) {
|
|
|
946
993
|
export function modIntInt(x, y) {
|
|
947
994
|
const result = trunc(x % y);
|
|
948
995
|
if (!isSafeInteger(result)) {
|
|
949
|
-
|
|
996
|
+
bubble();
|
|
950
997
|
}
|
|
951
998
|
/* not NaN or infinite */
|
|
952
999
|
return result;
|
|
@@ -1017,16 +1064,23 @@ export function cmpGeneric(a, b) {
|
|
|
1017
1064
|
if (a === b) {
|
|
1018
1065
|
return Object.is(a, 0) - Object.is(b, 0);
|
|
1019
1066
|
}
|
|
1067
|
+
if (isNaN(a) || isNaN(b)) {
|
|
1068
|
+
return isNaN(a) - isNaN(b);
|
|
1069
|
+
}
|
|
1020
1070
|
return a - b;
|
|
1021
1071
|
}
|
|
1022
1072
|
if (typeof a === "boolean" && typeof b === "boolean") {
|
|
1023
1073
|
return a - b;
|
|
1024
1074
|
}
|
|
1025
|
-
|
|
1075
|
+
bubble();
|
|
1026
1076
|
};
|
|
1027
1077
|
export function ltGeneric(a, b) {
|
|
1028
1078
|
if (typeof a === "number" && typeof b === "number") {
|
|
1029
|
-
return
|
|
1079
|
+
return (
|
|
1080
|
+
(isNaN(b) && !isNaN(a)) ||
|
|
1081
|
+
a < b ||
|
|
1082
|
+
(a === 0 && b === 0 && Object.is(a, 0) < Object.is(b, 0))
|
|
1083
|
+
);
|
|
1030
1084
|
}
|
|
1031
1085
|
if (typeof a == "boolean" && typeof b === "boolean") {
|
|
1032
1086
|
return a < b;
|
|
@@ -1035,7 +1089,10 @@ export function ltGeneric(a, b) {
|
|
|
1035
1089
|
}
|
|
1036
1090
|
export function leGeneric(a, b) {
|
|
1037
1091
|
if (typeof a === "number" && typeof b === "number") {
|
|
1038
|
-
return
|
|
1092
|
+
return (
|
|
1093
|
+
isNaN(b) ||
|
|
1094
|
+
(a <= b && (a !== 0 || b !== 0 || Object.is(a, 0) <= Object.is(b, 0)))
|
|
1095
|
+
);
|
|
1039
1096
|
}
|
|
1040
1097
|
if (typeof a == "boolean" && typeof b === "boolean") {
|
|
1041
1098
|
return a <= b;
|
|
@@ -1044,7 +1101,11 @@ export function leGeneric(a, b) {
|
|
|
1044
1101
|
}
|
|
1045
1102
|
export function gtGeneric(a, b) {
|
|
1046
1103
|
if (typeof a === "number" && typeof b === "number") {
|
|
1047
|
-
return
|
|
1104
|
+
return (
|
|
1105
|
+
(isNaN(a) && !isNaN(b)) ||
|
|
1106
|
+
a > b ||
|
|
1107
|
+
(a === 0 && b === 0 && Object.is(a, 0) > Object.is(b, 0))
|
|
1108
|
+
);
|
|
1048
1109
|
}
|
|
1049
1110
|
if (typeof a == "boolean" && typeof b === "boolean") {
|
|
1050
1111
|
return a > b;
|
|
@@ -1053,7 +1114,10 @@ export function gtGeneric(a, b) {
|
|
|
1053
1114
|
}
|
|
1054
1115
|
export function geGeneric(a, b) {
|
|
1055
1116
|
if (typeof a === "number" && typeof b === "number") {
|
|
1056
|
-
return
|
|
1117
|
+
return (
|
|
1118
|
+
isNaN(a) ||
|
|
1119
|
+
(a >= b && (a !== 0 || b !== 0 || Object.is(a, 0) >= Object.is(b, 0)))
|
|
1120
|
+
);
|
|
1057
1121
|
}
|
|
1058
1122
|
if (typeof a == "boolean" && typeof b === "boolean") {
|
|
1059
1123
|
return a >= b;
|
|
@@ -1067,17 +1131,15 @@ export function neGeneric(a, b) {
|
|
|
1067
1131
|
return !Object.is(a, b);
|
|
1068
1132
|
}
|
|
1069
1133
|
export function bubble() {
|
|
1070
|
-
throw
|
|
1134
|
+
throw Error();
|
|
1071
1135
|
}
|
|
1072
1136
|
export function print(a) {
|
|
1073
1137
|
console.log("%s", a);
|
|
1074
1138
|
return void 0;
|
|
1075
1139
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
generator.next()
|
|
1080
|
-
)(f());
|
|
1140
|
+
|
|
1141
|
+
export function adaptGenerator(generator) {
|
|
1142
|
+
return () => generator.next();
|
|
1081
1143
|
}
|
|
1082
1144
|
|
|
1083
1145
|
// We might customize this in the future, but actual global console works today.
|
package/interface-types.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
package/regex.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {bubbleException} from "./index.js";
|
|
2
|
-
|
|
3
1
|
export function compiledRegexCompiledFound(_, compiled, text) {
|
|
4
2
|
return compiled.test(text);
|
|
5
3
|
}
|
|
6
4
|
|
|
7
5
|
export function compiledRegexCompiledFind(_, compiled, text, regexRefs) {
|
|
8
|
-
|
|
6
|
+
const match = compiledRegexCompiledFindEx(_, compiled, text, regexRefs);
|
|
7
|
+
if (match === undefined) {
|
|
8
|
+
// We could just fail on `undefined.groups`, but that seems accidental.
|
|
9
|
+
throw Error();
|
|
10
|
+
}
|
|
11
|
+
return match.groups;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
/**
|
|
@@ -15,9 +18,11 @@ export function compiledRegexCompiledFind(_, compiled, text, regexRefs) {
|
|
|
15
18
|
function compiledRegexCompiledFindEx(_, compiled, text, regexRefs) {
|
|
16
19
|
const match = compiled.exec(text);
|
|
17
20
|
if (match === null) {
|
|
18
|
-
|
|
21
|
+
return undefined;
|
|
19
22
|
}
|
|
20
|
-
const { groups, indices: { groups:
|
|
23
|
+
const { groups: groupsMaybe, indices: { groups: indexGroupsMaybe } } = match;
|
|
24
|
+
const groups = groupsMaybe || {};
|
|
25
|
+
const indexGroups = indexGroupsMaybe || [];
|
|
21
26
|
// Find the begin indices in code points for all matched groups.
|
|
22
27
|
const rawBegins = [];
|
|
23
28
|
const defaultFull = !("full" in groups);
|
|
@@ -80,17 +85,10 @@ export function compiledRegexCompiledReplace(
|
|
|
80
85
|
// make our interface consistent, so we have to do this manually here.
|
|
81
86
|
// The hope is that we can optimize a bunch out when we have compile-time
|
|
82
87
|
// contant patterns and customized match result types.
|
|
83
|
-
let match;
|
|
84
|
-
|
|
85
|
-
match
|
|
86
|
-
|
|
87
|
-
if (e === bubbleException) {
|
|
88
|
-
// Manually handle no match case for our manual replace logic.
|
|
89
|
-
return text;
|
|
90
|
-
} else {
|
|
91
|
-
// This shouldn't happen if we don't have bugs, but forward it in case.
|
|
92
|
-
throw e;
|
|
93
|
-
}
|
|
88
|
+
let match = compiledRegexCompiledFindEx(_, compiled, text, regexRefs);
|
|
89
|
+
if (match === undefined) {
|
|
90
|
+
// Manually handle no match case for our manual replace logic.
|
|
91
|
+
return text;
|
|
94
92
|
}
|
|
95
93
|
// Index and length in js space should save some processing.
|
|
96
94
|
const { groups, index, length } = match;
|