@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 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
- let stack = [[]];
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
- intValue(v) { store(Math.trunc(v)); },
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::toInt
26
+ * Implements extension method Float64::toInt32
26
27
  * @param {number} n
27
28
  * @returns {number}
28
29
  */
29
- export const float64ToInt = (n) => {
30
- const i = float64ToIntUnsafe(n);
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::toIntUnsafe
40
+ * Implements extension method Float64::toInt32Unsafe
40
41
  * @param {number} n
41
42
  * @returns {number}
42
43
  */
43
- export const float64ToIntUnsafe = (n) => {
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
- Number.MIN_SAFE_INTEGER,
49
- Math.min(Math.trunc(n), Number.MAX_SAFE_INTEGER)
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.5.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 { requireIsSafeInteger } from "./check-type.js";
2
- import {bubble} from "./core.js";
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::toInt
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 stringToInt = (s, radix) => {
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
- requireIsSafeInteger(result);
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
+ }