@temperlang/core 0.5.0 → 0.6.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 +0 -0
- package/bitvector.js +0 -0
- package/check-type.js +0 -11
- package/core.js +137 -4
- package/date.js +0 -0
- package/deque.js +0 -0
- package/float.js +38 -8
- package/index.js +0 -0
- package/interface.js +0 -0
- package/listed.js +0 -0
- package/mapped.js +0 -0
- package/net.js +0 -0
- package/package.json +2 -2
- package/pair.js +0 -0
- package/regex.js +0 -0
- package/string.js +44 -6
- package/tsconfig.json +26 -0
package/async.js
CHANGED
|
File without changes
|
package/bitvector.js
CHANGED
|
File without changes
|
package/check-type.js
CHANGED
|
@@ -27,17 +27,6 @@ export const requireInstanceOf = (x, typeRequirement) => {
|
|
|
27
27
|
export const requireNotNull = (x) =>
|
|
28
28
|
x == null ? bubble() : x
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
* @param {number} x
|
|
32
|
-
* @returns {number}
|
|
33
|
-
*/
|
|
34
|
-
export const requireIsSafeInteger = (x) => {
|
|
35
|
-
if (!Number.isSafeInteger(x)) {
|
|
36
|
-
bubble();
|
|
37
|
-
}
|
|
38
|
-
return x;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
30
|
/**
|
|
42
31
|
* @template X, Y
|
|
43
32
|
* @param {X} x
|
package/core.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
|
|
2
3
|
/**
|
|
3
4
|
* @param {number} x
|
|
@@ -10,7 +11,7 @@ export const divIntInt = (x, y) => {
|
|
|
10
11
|
bubble();
|
|
11
12
|
}
|
|
12
13
|
/* not NaN or infinite */
|
|
13
|
-
return result;
|
|
14
|
+
return result | 0;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -25,9 +26,137 @@ export const modIntInt = (x, y) => {
|
|
|
25
26
|
bubble();
|
|
26
27
|
}
|
|
27
28
|
/* not NaN or infinite */
|
|
28
|
-
return result;
|
|
29
|
+
return result | 0;
|
|
29
30
|
};
|
|
30
31
|
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} s
|
|
34
|
+
* @param {(number | bigint)?} radix
|
|
35
|
+
* @returns {bigint}
|
|
36
|
+
*/
|
|
37
|
+
export const parseBigInt = (s, radix) => {
|
|
38
|
+
const rdx = BigInt(radix ?? 10);
|
|
39
|
+
let result = 0n;
|
|
40
|
+
// TODO Definitions of whitespace? Better to check /\s/ on the fly?
|
|
41
|
+
s = s.trim();
|
|
42
|
+
let i = 0;
|
|
43
|
+
let sign = 1n;
|
|
44
|
+
if (s.startsWith("-")) {
|
|
45
|
+
i++;
|
|
46
|
+
sign = -1n;
|
|
47
|
+
}
|
|
48
|
+
for (; i < s.length; i++) {
|
|
49
|
+
const c = s.charCodeAt(i);
|
|
50
|
+
/** @type {bigint} */
|
|
51
|
+
let digit;
|
|
52
|
+
if (c >= c0 && c <= c9) {
|
|
53
|
+
digit = BigInt(c - c0);
|
|
54
|
+
} else if (c >= cA && c <= cZ) {
|
|
55
|
+
digit = BigInt(c - cA + 10);
|
|
56
|
+
} else if (c >= ca && c <= cz) {
|
|
57
|
+
digit = BigInt(c - ca + 10);
|
|
58
|
+
} else {
|
|
59
|
+
bubble();
|
|
60
|
+
}
|
|
61
|
+
if (digit >= rdx) {
|
|
62
|
+
bubble();
|
|
63
|
+
}
|
|
64
|
+
result = result * rdx + digit;
|
|
65
|
+
}
|
|
66
|
+
return sign * result;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const c0 = "0".charCodeAt(0);
|
|
70
|
+
const c9 = "9".charCodeAt(0);
|
|
71
|
+
const cA = "A".charCodeAt(0);
|
|
72
|
+
const cZ = "Z".charCodeAt(0);
|
|
73
|
+
const ca = "a".charCodeAt(0);
|
|
74
|
+
const cz = "z".charCodeAt(0);
|
|
75
|
+
|
|
76
|
+
export const INT32_MAX = (2 ** 31) - 1;
|
|
77
|
+
export const INT32_MIN = -(2 ** 31);
|
|
78
|
+
export const INT64_MAX = (2n ** 63n) - 1n;
|
|
79
|
+
export const INT64_MIN = -(2n ** 63n);
|
|
80
|
+
|
|
81
|
+
// Related to int64 limits above.
|
|
82
|
+
const edge64 = 1n << 64n;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {bigint} x
|
|
86
|
+
* @returns {bigint}
|
|
87
|
+
*/
|
|
88
|
+
export const clampInt64 = (x) => {
|
|
89
|
+
x = x % edge64;
|
|
90
|
+
if (x > INT64_MAX) {
|
|
91
|
+
x -= edge64;
|
|
92
|
+
} else if (x < INT64_MIN) {
|
|
93
|
+
x += edge64;
|
|
94
|
+
}
|
|
95
|
+
return x;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Implements extension method Int64::max
|
|
100
|
+
* @param {bigint} a
|
|
101
|
+
* @param {bigint} b
|
|
102
|
+
* @returns {bigint}
|
|
103
|
+
*/
|
|
104
|
+
export const int64Max = (a, b) => {
|
|
105
|
+
return a > b ? a : b;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Implements extension method Int64::min
|
|
110
|
+
* @param {bigint} a
|
|
111
|
+
* @param {bigint} b
|
|
112
|
+
* @returns {bigint}
|
|
113
|
+
*/
|
|
114
|
+
export const int64Min = (a, b) => {
|
|
115
|
+
return a < b ? a : b;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Implements extension method Int64::toInt32
|
|
120
|
+
* @param {bigint} n
|
|
121
|
+
* @returns {number}
|
|
122
|
+
*/
|
|
123
|
+
export const int64ToInt32 = (n) => {
|
|
124
|
+
if (n < INT32_MIN || n > INT32_MAX) {
|
|
125
|
+
bubble();
|
|
126
|
+
}
|
|
127
|
+
return int64ToInt32Unsafe(n);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Implements extension method Int64::toInt32Unsafe
|
|
132
|
+
* @param {bigint} n
|
|
133
|
+
* @returns {number}
|
|
134
|
+
*/
|
|
135
|
+
export const int64ToInt32Unsafe = (n) => {
|
|
136
|
+
return Number(n) | 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Implements extension method Int64::toFloat64
|
|
141
|
+
* @param {bigint} n
|
|
142
|
+
* @returns {number}
|
|
143
|
+
*/
|
|
144
|
+
export const int64ToFloat64 = (n) => {
|
|
145
|
+
if (n < Number.MIN_SAFE_INTEGER || n > Number.MAX_SAFE_INTEGER) {
|
|
146
|
+
bubble();
|
|
147
|
+
}
|
|
148
|
+
return Number(n);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Implements extension method Int64::toFloat63Unsafe
|
|
153
|
+
* @param {bigint} n
|
|
154
|
+
* @returns {number}
|
|
155
|
+
*/
|
|
156
|
+
export const int64ToFloat64Unsafe = (n) => {
|
|
157
|
+
return Number(n);
|
|
158
|
+
}
|
|
159
|
+
|
|
31
160
|
/**
|
|
32
161
|
* Compare two Strings.
|
|
33
162
|
* @param {string} a
|
|
@@ -64,9 +193,11 @@ export const cmpFloat = (a, b) => {
|
|
|
64
193
|
return 0;
|
|
65
194
|
}
|
|
66
195
|
if (a === b) {
|
|
196
|
+
// @ts-ignore
|
|
67
197
|
return Object.is(a, 0) - Object.is(b, 0);
|
|
68
198
|
}
|
|
69
199
|
if (isNaN(a) || isNaN(b)) {
|
|
200
|
+
// @ts-ignore
|
|
70
201
|
return isNaN(a) - isNaN(b);
|
|
71
202
|
}
|
|
72
203
|
return a - b;
|
|
@@ -86,6 +217,7 @@ export const cmpGeneric = (a, b) => {
|
|
|
86
217
|
return cmpFloat(a, b);
|
|
87
218
|
}
|
|
88
219
|
if (typeof a === "boolean" && typeof b === "boolean") {
|
|
220
|
+
// @ts-ignore
|
|
89
221
|
return a - b;
|
|
90
222
|
}
|
|
91
223
|
bubble();
|
|
@@ -121,7 +253,8 @@ export const print = (a) => {
|
|
|
121
253
|
* @return any
|
|
122
254
|
*/
|
|
123
255
|
export let marshalToJsonObject = (jsonAdapter, value) => {
|
|
124
|
-
|
|
256
|
+
/** @type {any[]} */
|
|
257
|
+
const stack = [[]];
|
|
125
258
|
let pendingKey = null;
|
|
126
259
|
function store(value) {
|
|
127
260
|
let top = stack[stack.length - 1];
|
|
@@ -154,7 +287,7 @@ export let marshalToJsonObject = (jsonAdapter, value) => {
|
|
|
154
287
|
|
|
155
288
|
nullValue() { store(null); },
|
|
156
289
|
booleanValue(b) { store(!!b); },
|
|
157
|
-
|
|
290
|
+
int32Value(v) { store(Math.trunc(v)); },
|
|
158
291
|
float64Value(v) { store(+v); },
|
|
159
292
|
numericTokenValue(s) { store(+s); },
|
|
160
293
|
stringValue(s) { store(`${s}`); },
|
package/date.js
CHANGED
|
File without changes
|
package/deque.js
CHANGED
|
File without changes
|
package/float.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
|
|
2
3
|
// Implements extension method Float64::near
|
|
3
|
-
import {bubble} from "./core.js";
|
|
4
|
+
import {bubble, INT32_MAX, INT32_MIN, INT64_MAX, INT64_MIN} from "./core.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Implements extension method Float64::near
|
|
@@ -22,12 +23,12 @@ export const float64Near = (x, y, relTol, absTol) => {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
|
-
* Implements extension method Float64::
|
|
26
|
+
* Implements extension method Float64::toInt32
|
|
26
27
|
* @param {number} n
|
|
27
28
|
* @returns {number}
|
|
28
29
|
*/
|
|
29
|
-
export const
|
|
30
|
-
const i =
|
|
30
|
+
export const float64ToInt32 = (n) => {
|
|
31
|
+
const i = float64ToInt32Unsafe(n);
|
|
31
32
|
if (Math.abs(n - i) < 1) {
|
|
32
33
|
return i;
|
|
33
34
|
} else {
|
|
@@ -36,20 +37,49 @@ export const float64ToInt = (n) => {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
|
-
* Implements extension method Float64::
|
|
40
|
+
* Implements extension method Float64::toInt32Unsafe
|
|
40
41
|
* @param {number} n
|
|
41
42
|
* @returns {number}
|
|
42
43
|
*/
|
|
43
|
-
export const
|
|
44
|
+
export const float64ToInt32Unsafe = (n) => {
|
|
44
45
|
// We are free to do whatever with NaN here.
|
|
45
46
|
return isNaN(n)
|
|
46
47
|
? 0
|
|
47
48
|
: Math.max(
|
|
48
|
-
|
|
49
|
-
Math.min(Math.trunc(n),
|
|
49
|
+
INT32_MIN,
|
|
50
|
+
Math.min(Math.trunc(n), INT32_MAX)
|
|
50
51
|
);
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Implements extension method Float64::toInt64
|
|
56
|
+
* @param {number} n
|
|
57
|
+
* @returns {bigint}
|
|
58
|
+
*/
|
|
59
|
+
export const float64ToInt64 = (n) => {
|
|
60
|
+
// Also blocks NaNs.
|
|
61
|
+
if (!(n >= Number.MIN_SAFE_INTEGER && n <= Number.MAX_SAFE_INTEGER)) {
|
|
62
|
+
bubble();
|
|
63
|
+
}
|
|
64
|
+
return float64ToInt64Unsafe(n);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Implements extension method Float64::toInt64Unsafe
|
|
69
|
+
* @param {number} n
|
|
70
|
+
* @returns {bigint}
|
|
71
|
+
*/
|
|
72
|
+
export const float64ToInt64Unsafe = (n) => {
|
|
73
|
+
// We are free to do whatever with NaN here.
|
|
74
|
+
return isNaN(n)
|
|
75
|
+
? 0n
|
|
76
|
+
: BigInt(Math.max(
|
|
77
|
+
// Avoid converting giant numbers to bigint.
|
|
78
|
+
Number(INT64_MIN),
|
|
79
|
+
Math.min(Math.trunc(n), Number(INT64_MAX)),
|
|
80
|
+
));
|
|
81
|
+
}
|
|
82
|
+
|
|
53
83
|
/**
|
|
54
84
|
* Implements extension method Float64::toString
|
|
55
85
|
* @param {number} n
|
package/index.js
CHANGED
|
File without changes
|
package/interface.js
CHANGED
|
File without changes
|
package/listed.js
CHANGED
|
File without changes
|
package/mapped.js
CHANGED
|
File without changes
|
package/net.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temperlang/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Runtime support for JS generated by Temper",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "https://github.com/mikesamuel",
|
|
8
|
-
"license": "Apache-2.0"
|
|
8
|
+
"license": "Apache-2.0 OR MIT"
|
|
9
9
|
}
|
package/pair.js
CHANGED
|
File without changes
|
package/regex.js
CHANGED
|
File without changes
|
package/string.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
bubble, INT32_MAX, INT32_MIN, INT64_MAX, INT64_MIN, parseBigInt
|
|
3
|
+
} from "./core.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Implements extension method String::fromCodePoint
|
|
@@ -57,20 +58,38 @@ export const stringToFloat64 = (s) => {
|
|
|
57
58
|
};
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
|
-
* Implements extension method String::
|
|
61
|
+
* Implements extension method String::toInt32
|
|
61
62
|
* @param {string} s
|
|
62
63
|
* @param {number?} radix
|
|
63
64
|
* @returns {number}
|
|
64
65
|
*/
|
|
65
|
-
export const
|
|
66
|
+
export const stringToInt32 = (s, radix) => {
|
|
66
67
|
// This currently maybe allocates for trim and then also for check.
|
|
67
68
|
// TODO Avoid that with manual char checks? Arbitrary base makes regex harder.
|
|
68
69
|
s = s.trim();
|
|
69
70
|
radix = radix ?? 10;
|
|
70
71
|
const result = parseInt(s, radix);
|
|
71
|
-
|
|
72
|
+
// This check also catches nan.
|
|
73
|
+
if (!(result >= INT32_MIN && result <= INT32_MAX)) {
|
|
74
|
+
bubble();
|
|
75
|
+
}
|
|
72
76
|
const trimmed = s.slice(0, s.length - 1);
|
|
73
77
|
if (parseInt(trimmed, radix) === result) {
|
|
78
|
+
// Extraneous junk was ignored that we disallow.
|
|
79
|
+
bubble();
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Implements extension method String::toInt64
|
|
86
|
+
* @param {string} s
|
|
87
|
+
* @param {number?} radix
|
|
88
|
+
* @returns {number}
|
|
89
|
+
*/
|
|
90
|
+
export const stringToInt64 = (s, radix) => {
|
|
91
|
+
const result = parseBigInt(s, radix);
|
|
92
|
+
if (result < INT64_MIN || result > INT64_MAX) {
|
|
74
93
|
bubble();
|
|
75
94
|
}
|
|
76
95
|
return result;
|
|
@@ -164,6 +183,25 @@ export const stringPrev = (s, i) => {
|
|
|
164
183
|
return iPrev;
|
|
165
184
|
};
|
|
166
185
|
|
|
186
|
+
/**
|
|
187
|
+
* @param {string} s
|
|
188
|
+
* @param {number} i
|
|
189
|
+
* @param {number} by
|
|
190
|
+
* @returns {number}
|
|
191
|
+
*/
|
|
192
|
+
export const stringStep = (s, i, by) => {
|
|
193
|
+
let step = by >= 0 ? stringNext : stringPrev;
|
|
194
|
+
by = Math.abs(by);
|
|
195
|
+
for (let j = 0; j < by; j += 1) {
|
|
196
|
+
const iOld = i;
|
|
197
|
+
i = step(s, i);
|
|
198
|
+
if (i == iOld) {
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return i;
|
|
203
|
+
};
|
|
204
|
+
|
|
167
205
|
/**
|
|
168
206
|
* @param {string} s
|
|
169
207
|
* @param {(number) => void} f
|
|
@@ -218,4 +256,4 @@ const denySurrogate = (c) => {
|
|
|
218
256
|
if (c >= 0xD800 && c <= 0xDFFF) {
|
|
219
257
|
throw new RangeError(`Invalid Unicode scalar value ${c}`)
|
|
220
258
|
}
|
|
221
|
-
}
|
|
259
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"noEmit": true,
|
|
5
|
+
"preserveConstEnums": false,
|
|
6
|
+
"removeComments": true,
|
|
7
|
+
"sourceMap": false,
|
|
8
|
+
"target": "es2020"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"async.js",
|
|
12
|
+
"bitvector.js",
|
|
13
|
+
"check-type.js",
|
|
14
|
+
"core.js",
|
|
15
|
+
"date.js",
|
|
16
|
+
"deque.js",
|
|
17
|
+
"float.js",
|
|
18
|
+
"index.js",
|
|
19
|
+
"interface.js",
|
|
20
|
+
"listed.js",
|
|
21
|
+
"mapped.js",
|
|
22
|
+
"pair.js",
|
|
23
|
+
"regex.js",
|
|
24
|
+
"string.js"
|
|
25
|
+
]
|
|
26
|
+
}
|