@grain/stdlib 0.5.12 → 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/CHANGELOG.md +200 -0
- package/LICENSE +1 -1
- package/README.md +25 -2
- package/array.gr +1512 -199
- package/array.md +2032 -94
- package/bigint.gr +239 -140
- package/bigint.md +450 -106
- package/buffer.gr +595 -102
- package/buffer.md +903 -145
- package/bytes.gr +401 -110
- package/bytes.md +551 -63
- package/char.gr +228 -49
- package/char.md +373 -7
- package/exception.gr +26 -12
- package/exception.md +29 -5
- package/float32.gr +130 -109
- package/float32.md +185 -57
- package/float64.gr +112 -99
- package/float64.md +185 -57
- package/hash.gr +47 -37
- package/hash.md +21 -3
- package/int16.gr +430 -0
- package/int16.md +618 -0
- package/int32.gr +200 -269
- package/int32.md +254 -289
- package/int64.gr +142 -225
- package/int64.md +254 -289
- package/int8.gr +511 -0
- package/int8.md +786 -0
- package/json.gr +2084 -0
- package/json.md +608 -0
- package/list.gr +120 -68
- package/list.md +125 -80
- package/map.gr +560 -57
- package/map.md +672 -56
- package/marshal.gr +239 -227
- package/marshal.md +36 -4
- package/number.gr +626 -676
- package/number.md +738 -153
- package/option.gr +33 -35
- package/option.md +58 -42
- package/package.json +2 -2
- package/path.gr +148 -187
- package/path.md +47 -96
- package/pervasives.gr +75 -416
- package/pervasives.md +85 -180
- package/priorityqueue.gr +433 -74
- package/priorityqueue.md +422 -54
- package/queue.gr +362 -80
- package/queue.md +433 -38
- package/random.gr +67 -75
- package/random.md +68 -40
- package/range.gr +135 -63
- package/range.md +198 -43
- package/rational.gr +284 -0
- package/rational.md +545 -0
- package/regex.gr +933 -1066
- package/regex.md +59 -60
- package/result.gr +23 -25
- package/result.md +54 -39
- package/runtime/atof/common.gr +78 -82
- package/runtime/atof/common.md +22 -10
- package/runtime/atof/decimal.gr +102 -127
- package/runtime/atof/decimal.md +28 -7
- package/runtime/atof/lemire.gr +56 -71
- package/runtime/atof/lemire.md +9 -1
- package/runtime/atof/parse.gr +83 -110
- package/runtime/atof/parse.md +12 -2
- package/runtime/atof/slow.gr +28 -35
- package/runtime/atof/slow.md +9 -1
- package/runtime/atof/table.gr +19 -18
- package/runtime/atof/table.md +10 -2
- package/runtime/atoi/parse.gr +153 -136
- package/runtime/atoi/parse.md +50 -1
- package/runtime/bigint.gr +410 -517
- package/runtime/bigint.md +71 -57
- package/runtime/compare.gr +176 -85
- package/runtime/compare.md +31 -1
- package/runtime/dataStructures.gr +144 -32
- package/runtime/dataStructures.md +267 -31
- package/runtime/debugPrint.gr +34 -15
- package/runtime/debugPrint.md +37 -5
- package/runtime/equal.gr +53 -52
- package/runtime/equal.md +30 -1
- package/runtime/exception.gr +38 -47
- package/runtime/exception.md +10 -8
- package/runtime/gc.gr +23 -152
- package/runtime/gc.md +13 -17
- package/runtime/malloc.gr +31 -31
- package/runtime/malloc.md +11 -3
- package/runtime/numberUtils.gr +191 -172
- package/runtime/numberUtils.md +17 -9
- package/runtime/numbers.gr +1695 -1021
- package/runtime/numbers.md +1098 -134
- package/runtime/string.gr +540 -242
- package/runtime/string.md +76 -6
- package/runtime/unsafe/constants.gr +30 -13
- package/runtime/unsafe/constants.md +80 -0
- package/runtime/unsafe/conv.gr +55 -28
- package/runtime/unsafe/conv.md +41 -9
- package/runtime/unsafe/memory.gr +10 -30
- package/runtime/unsafe/memory.md +15 -19
- package/runtime/unsafe/tags.gr +37 -21
- package/runtime/unsafe/tags.md +88 -8
- package/runtime/unsafe/wasmf32.gr +30 -36
- package/runtime/unsafe/wasmf32.md +64 -56
- package/runtime/unsafe/wasmf64.gr +30 -36
- package/runtime/unsafe/wasmf64.md +64 -56
- package/runtime/unsafe/wasmi32.gr +49 -66
- package/runtime/unsafe/wasmi32.md +102 -94
- package/runtime/unsafe/wasmi64.gr +52 -79
- package/runtime/unsafe/wasmi64.md +108 -100
- package/runtime/utils/printing.gr +13 -15
- package/runtime/utils/printing.md +11 -3
- package/runtime/wasi.gr +294 -295
- package/runtime/wasi.md +62 -42
- package/set.gr +574 -64
- package/set.md +634 -54
- package/stack.gr +181 -64
- package/stack.md +271 -42
- package/string.gr +453 -533
- package/string.md +241 -151
- package/uint16.gr +369 -0
- package/uint16.md +585 -0
- package/uint32.gr +470 -0
- package/uint32.md +737 -0
- package/uint64.gr +471 -0
- package/uint64.md +737 -0
- package/uint8.gr +369 -0
- package/uint8.md +585 -0
- package/uri.gr +1093 -0
- package/uri.md +477 -0
- package/{sys → wasi}/file.gr +914 -500
- package/{sys → wasi}/file.md +454 -50
- package/wasi/process.gr +292 -0
- package/{sys → wasi}/process.md +164 -6
- package/wasi/random.gr +77 -0
- package/wasi/random.md +80 -0
- package/{sys → wasi}/time.gr +15 -22
- package/{sys → wasi}/time.md +5 -5
- package/immutablearray.gr +0 -929
- package/immutablearray.md +0 -1038
- package/immutablemap.gr +0 -493
- package/immutablemap.md +0 -479
- package/immutablepriorityqueue.gr +0 -360
- package/immutablepriorityqueue.md +0 -291
- package/immutableset.gr +0 -498
- package/immutableset.md +0 -449
- package/runtime/debug.gr +0 -2
- package/runtime/debug.md +0 -6
- package/runtime/unsafe/errors.gr +0 -36
- package/runtime/unsafe/errors.md +0 -204
- package/sys/process.gr +0 -254
- package/sys/random.gr +0 -79
- package/sys/random.md +0 -66
package/runtime/atof/slow.gr
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* the Software, and to permit persons to whom the Software
|
|
12
12
|
* is furnished to do so, subject to the following
|
|
13
13
|
* conditions:
|
|
14
|
-
*
|
|
14
|
+
*
|
|
15
15
|
* The above copyright notice and this permission notice
|
|
16
16
|
* shall be included in all copies or substantial portions
|
|
17
17
|
* of the Software.
|
|
18
|
-
*
|
|
18
|
+
*
|
|
19
19
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
20
20
|
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
21
21
|
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
@@ -26,16 +26,19 @@
|
|
|
26
26
|
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
27
27
|
* DEALINGS IN THE SOFTWARE.
|
|
28
28
|
*/
|
|
29
|
+
module Slow
|
|
29
30
|
|
|
30
31
|
//! Slow, fallback algorithm for cases the Eisel-Lemire algorithm cannot round.
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
34
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
35
|
+
from "runtime/unsafe/memory" include Memory
|
|
36
|
+
from "runtime/dataStructures" include DataStructures
|
|
37
|
+
use DataStructures.{ newInt32, newInt64 }
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
from "runtime/atof/common" include Common
|
|
40
|
+
use Common.{
|
|
41
|
+
type BiasedFp,
|
|
39
42
|
fpZero,
|
|
40
43
|
fpInf,
|
|
41
44
|
fpErr,
|
|
@@ -43,8 +46,9 @@ import {
|
|
|
43
46
|
_INFINITE_POWER,
|
|
44
47
|
_MANTISSA_EXPLICIT_BITS_32,
|
|
45
48
|
_MANTISSA_EXPLICIT_BITS_64,
|
|
46
|
-
}
|
|
47
|
-
|
|
49
|
+
}
|
|
50
|
+
from "runtime/atof/decimal" include Decimal
|
|
51
|
+
use Decimal.{ parseDecimal, _DECIMAL_POINT_RANGE }
|
|
48
52
|
|
|
49
53
|
@unsafe
|
|
50
54
|
let _MAX_SHIFT = 60n
|
|
@@ -55,7 +59,7 @@ let mut _POWERS = -1n
|
|
|
55
59
|
|
|
56
60
|
@unsafe
|
|
57
61
|
let get_POWERS = () => {
|
|
58
|
-
|
|
62
|
+
use WasmI32.{ (==) }
|
|
59
63
|
if (_POWERS == -1n) {
|
|
60
64
|
_POWERS = Memory.malloc(130n)
|
|
61
65
|
WasmI32.store8(_POWERS, 0n, 0n)
|
|
@@ -83,7 +87,8 @@ let get_POWERS = () => {
|
|
|
83
87
|
|
|
84
88
|
@unsafe
|
|
85
89
|
let getShift = n => {
|
|
86
|
-
|
|
90
|
+
use WasmI32.{ (<) }
|
|
91
|
+
if (n < _NUM_POWERS) {
|
|
87
92
|
WasmI32.load8U(get_POWERS(), n)
|
|
88
93
|
} else {
|
|
89
94
|
_MAX_SHIFT
|
|
@@ -112,22 +117,14 @@ let getShift = n => {
|
|
|
112
117
|
* available here: <https://arxiv.org/pdf/2101.11408.pdf#section.11>.
|
|
113
118
|
*/
|
|
114
119
|
@unsafe
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
let (&) = WasmI32.and
|
|
119
|
-
let (<) = WasmI32.ltS
|
|
120
|
-
let (>) = WasmI32.gtS
|
|
121
|
-
let (>=) = WasmI32.geS
|
|
122
|
-
let (<=) = WasmI32.leS
|
|
123
|
-
let (>>) = WasmI32.shrU
|
|
124
|
-
let (<<) = WasmI32.shl
|
|
125
|
-
let (==) = WasmI32.eq
|
|
120
|
+
provide let parseLongMantissa = (s: String) => {
|
|
121
|
+
use WasmI32.{ (+), (-), (&), (<), (>), (>=), (<=), (==) }
|
|
122
|
+
use WasmI64.{ (+) as addWasmI64, (<<) }
|
|
126
123
|
|
|
127
124
|
let mut d = parseDecimal(s)
|
|
128
125
|
let digits = WasmI32.fromGrain(d.digits)
|
|
129
|
-
let mut numDigits = WasmI32.load(WasmI32.fromGrain(d.numDigits),
|
|
130
|
-
let mut decimalPoint = WasmI32.load(WasmI32.fromGrain(d.decimalPoint),
|
|
126
|
+
let mut numDigits = WasmI32.load(WasmI32.fromGrain(d.numDigits), 4n)
|
|
127
|
+
let mut decimalPoint = WasmI32.load(WasmI32.fromGrain(d.decimalPoint), 4n)
|
|
131
128
|
|
|
132
129
|
// Short-circuit if the value can only be a literal 0 or infinity.
|
|
133
130
|
if (numDigits == 0n || decimalPoint < -324n) {
|
|
@@ -142,7 +139,7 @@ export let parseLongMantissa = (s: String) => {
|
|
|
142
139
|
let n = decimalPoint
|
|
143
140
|
let shift = getShift(n)
|
|
144
141
|
Decimal.rightShift(d, shift)
|
|
145
|
-
decimalPoint = WasmI32.load(WasmI32.fromGrain(d.decimalPoint),
|
|
142
|
+
decimalPoint = WasmI32.load(WasmI32.fromGrain(d.decimalPoint), 4n)
|
|
146
143
|
if (decimalPoint < 0n - _DECIMAL_POINT_RANGE) {
|
|
147
144
|
done = true
|
|
148
145
|
break
|
|
@@ -169,7 +166,7 @@ export let parseLongMantissa = (s: String) => {
|
|
|
169
166
|
getShift(0n - decimalPoint)
|
|
170
167
|
}
|
|
171
168
|
Decimal.leftShift(d, shift)
|
|
172
|
-
decimalPoint = WasmI32.load(WasmI32.fromGrain(d.decimalPoint),
|
|
169
|
+
decimalPoint = WasmI32.load(WasmI32.fromGrain(d.decimalPoint), 4n)
|
|
173
170
|
if (decimalPoint > _DECIMAL_POINT_RANGE) {
|
|
174
171
|
done = true
|
|
175
172
|
break
|
|
@@ -200,7 +197,7 @@ export let parseLongMantissa = (s: String) => {
|
|
|
200
197
|
if (
|
|
201
198
|
WasmI64.geU(
|
|
202
199
|
mantissa,
|
|
203
|
-
|
|
200
|
+
1N << addWasmI64(_MANTISSA_EXPLICIT_BITS_64, 1N)
|
|
204
201
|
)
|
|
205
202
|
) {
|
|
206
203
|
// Rounding up overflowed to the carry bit, need to
|
|
@@ -216,16 +213,12 @@ export let parseLongMantissa = (s: String) => {
|
|
|
216
213
|
fpInf()
|
|
217
214
|
} else {
|
|
218
215
|
let mut power2 = exp2 - _MINIMUM_EXPONENT
|
|
219
|
-
if (
|
|
220
|
-
WasmI64.ltU(mantissa, WasmI64.shl(1N, _MANTISSA_EXPLICIT_BITS_64))
|
|
221
|
-
) {
|
|
216
|
+
if (WasmI64.ltU(mantissa, 1N << _MANTISSA_EXPLICIT_BITS_64)) {
|
|
222
217
|
power2 -= 1n
|
|
223
218
|
}
|
|
219
|
+
use WasmI64.{ (-), (&) }
|
|
224
220
|
// Zero out all the bits above the explicit mantissa bits.
|
|
225
|
-
mantissa =
|
|
226
|
-
mantissa,
|
|
227
|
-
WasmI64.sub(WasmI64.shl(1N, _MANTISSA_EXPLICIT_BITS_64), 1N)
|
|
228
|
-
)
|
|
221
|
+
mantissa = mantissa & (1N << _MANTISSA_EXPLICIT_BITS_64) - 1N
|
|
229
222
|
{
|
|
230
223
|
f: WasmI32.toGrain(newInt64(mantissa)): Int64,
|
|
231
224
|
e: WasmI32.toGrain(newInt32(power2)): Int32,
|
package/runtime/atof/slow.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Slow
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Values
|
|
6
|
+
|
|
7
|
+
Functions and constants included in the Slow module.
|
|
8
|
+
|
|
1
9
|
### Slow.**parseLongMantissa**
|
|
2
10
|
|
|
3
11
|
```grain
|
|
4
|
-
parseLongMantissa : String
|
|
12
|
+
parseLongMantissa : (s: String) => Common.BiasedFp
|
|
5
13
|
```
|
|
6
14
|
|
package/runtime/atof/table.gr
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
@noPervasives
|
|
2
|
+
module Table
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
5
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
6
|
+
from "runtime/unsafe/wasmf64" include WasmF64
|
|
7
|
+
from "runtime/unsafe/memory" include Memory
|
|
7
8
|
|
|
8
9
|
@unsafe
|
|
9
10
|
let mut _F64_POWERS10_FAST_PATH = -1n
|
|
10
11
|
|
|
11
12
|
@unsafe
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
provide let get_F64_POWERS10_FAST_PATH = () => {
|
|
14
|
+
use WasmI32.{ (==) }
|
|
14
15
|
if (_F64_POWERS10_FAST_PATH == -1n) {
|
|
15
16
|
_F64_POWERS10_FAST_PATH = Memory.malloc(256n) // 32 x 64-bit values
|
|
16
17
|
|
|
@@ -37,15 +38,15 @@ export let get_F64_POWERS10_FAST_PATH = () => {
|
|
|
37
38
|
WasmF64.store(_F64_POWERS10_FAST_PATH, 1e20W, 160n)
|
|
38
39
|
WasmF64.store(_F64_POWERS10_FAST_PATH, 1e21W, 168n)
|
|
39
40
|
WasmF64.store(_F64_POWERS10_FAST_PATH, 1e22W, 176n)
|
|
40
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
41
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
42
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
43
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
44
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
45
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
46
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
47
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
48
|
-
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.
|
|
41
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 184n)
|
|
42
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 192n)
|
|
43
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 200n)
|
|
44
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 208n)
|
|
45
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 216n)
|
|
46
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 224n)
|
|
47
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 232n)
|
|
48
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 240n)
|
|
49
|
+
WasmF64.store(_F64_POWERS10_FAST_PATH, 0.0W, 248n)
|
|
49
50
|
}
|
|
50
51
|
_F64_POWERS10_FAST_PATH
|
|
51
52
|
}
|
|
@@ -54,8 +55,8 @@ export let get_F64_POWERS10_FAST_PATH = () => {
|
|
|
54
55
|
let mut _POWERS5 = -1n
|
|
55
56
|
|
|
56
57
|
@unsafe
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
provide let get_POWERS5 = () => {
|
|
59
|
+
use WasmI32.{ (==) }
|
|
59
60
|
if (_POWERS5 == -1n) {
|
|
60
61
|
_POWERS5 = Memory.malloc(10416n) // 1302 x 64-bit values
|
|
61
62
|
//5^-342
|
package/runtime/atof/table.md
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Table
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Values
|
|
6
|
+
|
|
7
|
+
Functions and constants included in the Table module.
|
|
8
|
+
|
|
1
9
|
### Table.**get_F64_POWERS10_FAST_PATH**
|
|
2
10
|
|
|
3
11
|
```grain
|
|
4
|
-
get_F64_POWERS10_FAST_PATH : ()
|
|
12
|
+
get_F64_POWERS10_FAST_PATH : () => WasmI32
|
|
5
13
|
```
|
|
6
14
|
|
|
7
15
|
### Table.**get_POWERS5**
|
|
8
16
|
|
|
9
17
|
```grain
|
|
10
|
-
get_POWERS5 : ()
|
|
18
|
+
get_POWERS5 : () => WasmI32
|
|
11
19
|
```
|
|
12
20
|
|
package/runtime/atoi/parse.gr
CHANGED
|
@@ -1,24 +1,51 @@
|
|
|
1
|
-
|
|
1
|
+
@noPervasives
|
|
2
|
+
module Parse
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
5
|
+
use WasmI32.{
|
|
6
|
+
(+),
|
|
7
|
+
(-),
|
|
6
8
|
gtU as (>),
|
|
7
9
|
geU as (>=),
|
|
8
10
|
ltU as (<),
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
(>>),
|
|
12
|
+
(==),
|
|
13
|
+
(!=),
|
|
14
|
+
(&),
|
|
15
|
+
}
|
|
16
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
17
|
+
from "runtime/unsafe/memory" include Memory
|
|
18
|
+
from "runtime/unsafe/tags" include Tags
|
|
19
|
+
from "runtime/bigint" include Bigint as BI
|
|
20
|
+
from "runtime/numbers" include Numbers
|
|
21
|
+
use Numbers.{ reducedInteger }
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Represents an error that occurred trying to parse an integer.
|
|
25
|
+
*
|
|
26
|
+
* @since v0.6.0
|
|
27
|
+
*/
|
|
28
|
+
provide enum ParseIntError {
|
|
29
|
+
/**
|
|
30
|
+
* Represents an error caused by trying to parse an empty string.
|
|
31
|
+
*/
|
|
32
|
+
ParseIntEmptyString,
|
|
33
|
+
/**
|
|
34
|
+
* Represents an error caused by trying to parse a string with an invalid character.
|
|
35
|
+
*/
|
|
36
|
+
ParseIntInvalidDigit,
|
|
37
|
+
/**
|
|
38
|
+
* Represents an error caused by trying to parse with an invalid radix.
|
|
39
|
+
*/
|
|
40
|
+
ParseIntInvalidRadix,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
primitive (&&) = "@and"
|
|
44
|
+
primitive (||) = "@or"
|
|
19
45
|
|
|
20
46
|
@unsafe
|
|
21
|
-
|
|
47
|
+
provide let parseInt = (string: String, radix: Number) => {
|
|
48
|
+
use WasmI64.{ (+) as addWasmI64 }
|
|
22
49
|
let _CHAR_0 = 0x30n
|
|
23
50
|
let _CHAR_B = 0x42n
|
|
24
51
|
let _CHAR_b = 0x62n
|
|
@@ -51,146 +78,136 @@ export let parseInt = (string: String, radix: Number) => {
|
|
|
51
78
|
radix < WasmI32.fromGrain(2) ||
|
|
52
79
|
radix > WasmI32.fromGrain(36)
|
|
53
80
|
) {
|
|
54
|
-
Err(
|
|
55
|
-
}
|
|
56
|
-
Err("Invalid input")
|
|
57
|
-
} else {
|
|
58
|
-
let mut char = WasmI32.load8U(offset, 0n)
|
|
59
|
-
|
|
60
|
-
let mut limit = WasmI64.add(_INT_MIN, 1N)
|
|
61
|
-
|
|
62
|
-
// Check for a sign
|
|
63
|
-
let mut negative = false
|
|
64
|
-
if (char == _CHAR_MINUS) {
|
|
65
|
-
negative = true
|
|
66
|
-
offset += 1n
|
|
67
|
-
limit = _INT_MIN
|
|
68
|
-
char = WasmI32.load8U(offset, 0n)
|
|
69
|
-
}
|
|
81
|
+
return Err(ParseIntInvalidRadix)
|
|
82
|
+
}
|
|
70
83
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (char == _CHAR_0 && strLen > 2n) {
|
|
75
|
-
match (WasmI32.load8U(offset, 1n)) {
|
|
76
|
-
c when c == _CHAR_B || c == _CHAR_b => {
|
|
77
|
-
radix = 2N
|
|
78
|
-
offset += 2n
|
|
79
|
-
},
|
|
80
|
-
c when c == _CHAR_O || c == _CHAR_o => {
|
|
81
|
-
radix = 8N
|
|
82
|
-
offset += 2n
|
|
83
|
-
},
|
|
84
|
-
c when c == _CHAR_X || c == _CHAR_x => {
|
|
85
|
-
radix = 16N
|
|
86
|
-
offset += 2n
|
|
87
|
-
},
|
|
88
|
-
_ => void,
|
|
89
|
-
}
|
|
90
|
-
}
|
|
84
|
+
if (WasmI32.eqz(strLen)) {
|
|
85
|
+
return Err(ParseIntEmptyString)
|
|
86
|
+
}
|
|
91
87
|
|
|
92
|
-
|
|
93
|
-
let mut value = 0N
|
|
94
|
-
let mut radixBigInt = 0n
|
|
95
|
-
let mut valueBigInt = 0n
|
|
96
|
-
let mut isBigInt = 0n
|
|
88
|
+
let mut char = WasmI32.load8U(offset, 0n)
|
|
97
89
|
|
|
98
|
-
|
|
99
|
-
let mut error = 1n
|
|
90
|
+
let mut limit = addWasmI64(_INT_MIN, 1N)
|
|
100
91
|
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
// Check for a sign
|
|
93
|
+
let mut negative = false
|
|
94
|
+
if (char == _CHAR_MINUS) {
|
|
95
|
+
negative = true
|
|
96
|
+
offset += 1n
|
|
97
|
+
limit = _INT_MIN
|
|
98
|
+
char = WasmI32.load8U(offset, 0n)
|
|
99
|
+
}
|
|
103
100
|
|
|
104
|
-
|
|
105
|
-
if (char == _CHAR_UNDERSCORE) {
|
|
106
|
-
continue
|
|
107
|
-
}
|
|
101
|
+
let mut radix = WasmI64.extendI32S(radix >> 1n)
|
|
108
102
|
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
// Check if we should override the supplied radix
|
|
104
|
+
if (char == _CHAR_0 && strLen > 2n) {
|
|
105
|
+
match (WasmI32.load8U(offset, 1n)) {
|
|
106
|
+
c when c == _CHAR_B || c == _CHAR_b => {
|
|
107
|
+
radix = 2N
|
|
108
|
+
offset += 2n
|
|
109
|
+
},
|
|
110
|
+
c when c == _CHAR_O || c == _CHAR_o => {
|
|
111
|
+
radix = 8N
|
|
112
|
+
offset += 2n
|
|
113
|
+
},
|
|
114
|
+
c when c == _CHAR_X || c == _CHAR_x => {
|
|
115
|
+
radix = 16N
|
|
116
|
+
offset += 2n
|
|
117
|
+
},
|
|
118
|
+
_ => void,
|
|
119
|
+
}
|
|
120
|
+
}
|
|
111
121
|
|
|
112
|
-
|
|
122
|
+
// We try to avoid allocating a BigInt if it's not needed
|
|
123
|
+
let mut value = 0N
|
|
124
|
+
let mut radixBigInt = 0n
|
|
125
|
+
let mut valueBigInt = 0n
|
|
126
|
+
let mut isBigInt = 0n
|
|
127
|
+
let mut sawDigit = 0n
|
|
113
128
|
|
|
114
|
-
|
|
129
|
+
for (let mut i = offset; i < strEnd; i += 1n) {
|
|
130
|
+
let char = WasmI32.load8U(i, 0n)
|
|
115
131
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
_ => {
|
|
121
|
-
error = 1n
|
|
122
|
-
// invalid digit
|
|
123
|
-
break
|
|
124
|
-
},
|
|
125
|
-
}
|
|
132
|
+
// Ignore underscore characters
|
|
133
|
+
if (char == _CHAR_UNDERSCORE) {
|
|
134
|
+
continue
|
|
135
|
+
}
|
|
126
136
|
|
|
127
|
-
|
|
128
|
-
error = 1n
|
|
129
|
-
// invalid digit
|
|
130
|
-
break
|
|
131
|
-
}
|
|
137
|
+
sawDigit = 1n
|
|
132
138
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
} else {
|
|
139
|
+
let mut digit = 0n
|
|
140
|
+
|
|
141
|
+
match (char) {
|
|
142
|
+
c when c - _CHAR_0 < 10n => digit = char - _CHAR_0,
|
|
143
|
+
c when c - _CHAR_A < 26n => digit = char - _CHAR_A + 10n,
|
|
144
|
+
c when c - _CHAR_a < 26n => digit = char - _CHAR_a + 10n,
|
|
145
|
+
_ => {
|
|
146
|
+
return Err(ParseIntInvalidDigit)
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (digit >= WasmI32.wrapI64(radix)) {
|
|
151
|
+
return Err(ParseIntInvalidDigit)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let digit = WasmI64.extendI32U(digit)
|
|
155
|
+
|
|
156
|
+
if (WasmI32.eqz(isBigInt)) {
|
|
157
|
+
use WasmI64.{ (+) }
|
|
158
|
+
use WasmI64.{ (*), (<) }
|
|
159
|
+
let prevValue = value
|
|
160
|
+
value *= radix
|
|
161
|
+
// Check for overflow
|
|
162
|
+
// 64-bit int min + 1
|
|
163
|
+
if (value < limit + digit) {
|
|
164
|
+
// we overflowed. allocate BigInt and use instead
|
|
165
|
+
isBigInt = 1n
|
|
166
|
+
valueBigInt = BI.makeWrappedUint64(prevValue * -1N)
|
|
167
|
+
radixBigInt = BI.makeWrappedUint64(radix)
|
|
163
168
|
let newvalue = BI.mul(valueBigInt, radixBigInt)
|
|
164
169
|
Memory.decRef(valueBigInt)
|
|
165
170
|
valueBigInt = newvalue
|
|
166
171
|
let newvalue = BI.addInt(valueBigInt, digit)
|
|
167
172
|
Memory.decRef(valueBigInt)
|
|
168
173
|
valueBigInt = newvalue
|
|
174
|
+
} else {
|
|
175
|
+
use WasmI64.{ (-) }
|
|
176
|
+
// To quote the OpenJDK,
|
|
177
|
+
// "Accumulating negatively avoids surprises near MAX_VALUE"
|
|
178
|
+
// The minimum value of a 64-bit integer (-9223372036854775808) can't be
|
|
179
|
+
// represented as a positive number because it would be larger than the
|
|
180
|
+
// maximum 64-bit integer (9223372036854775807), so we'd be unable to
|
|
181
|
+
// parse negatives as positives and multiply by the sign at the end.
|
|
182
|
+
// Instead, we represent all positive numbers as negative numbers since
|
|
183
|
+
// we have one unit more headroom.
|
|
184
|
+
value -= digit
|
|
169
185
|
}
|
|
186
|
+
} else {
|
|
187
|
+
let newvalue = BI.mul(valueBigInt, radixBigInt)
|
|
188
|
+
Memory.decRef(valueBigInt)
|
|
189
|
+
valueBigInt = newvalue
|
|
190
|
+
let newvalue = BI.addInt(valueBigInt, digit)
|
|
191
|
+
Memory.decRef(valueBigInt)
|
|
192
|
+
valueBigInt = newvalue
|
|
170
193
|
}
|
|
194
|
+
}
|
|
195
|
+
use WasmI64.{ (*) }
|
|
196
|
+
// TODO: Verify this is suitable for handling "_"
|
|
197
|
+
if (WasmI32.eqz(sawDigit)) return Err(ParseIntInvalidDigit)
|
|
198
|
+
|
|
199
|
+
if (WasmI32.eqz(isBigInt)) {
|
|
200
|
+
let value = if (negative) value else value * -1N
|
|
201
|
+
let number = WasmI32.toGrain(Memory.incRef(reducedInteger(value))): Number
|
|
202
|
+
return Ok(number)
|
|
203
|
+
}
|
|
171
204
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (WasmI32.eqz(isBigInt)) {
|
|
178
|
-
let value = if (negative) value else WasmI64.mul(value, -1N)
|
|
179
|
-
let number = WasmI32.toGrain(
|
|
180
|
-
Memory.incRef(reducedInteger(value))
|
|
181
|
-
): Number
|
|
182
|
-
Ok(number)
|
|
183
|
-
} else {
|
|
184
|
-
// BigInt number is accumulated in positive form
|
|
185
|
-
if (negative) {
|
|
186
|
-
let newvalue = BI.negate(valueBigInt)
|
|
187
|
-
Memory.decRef(valueBigInt)
|
|
188
|
-
Ok(WasmI32.toGrain(newvalue))
|
|
189
|
-
} else {
|
|
190
|
-
Ok(WasmI32.toGrain(valueBigInt))
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
}
|
|
205
|
+
// BigInt number is accumulated in positive form
|
|
206
|
+
if (negative) {
|
|
207
|
+
let newvalue = BI.negate(valueBigInt)
|
|
208
|
+
Memory.decRef(valueBigInt)
|
|
209
|
+
return Ok(WasmI32.toGrain(newvalue))
|
|
195
210
|
}
|
|
211
|
+
|
|
212
|
+
return Ok(WasmI32.toGrain(valueBigInt))
|
|
196
213
|
}
|
package/runtime/atoi/parse.md
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Parse
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Types
|
|
6
|
+
|
|
7
|
+
Type declarations included in the Parse module.
|
|
8
|
+
|
|
9
|
+
### Parse.**ParseIntError**
|
|
10
|
+
|
|
11
|
+
<details disabled>
|
|
12
|
+
<summary tabindex="-1">Added in <code>0.6.0</code></summary>
|
|
13
|
+
No other changes yet.
|
|
14
|
+
</details>
|
|
15
|
+
|
|
16
|
+
```grain
|
|
17
|
+
enum ParseIntError {
|
|
18
|
+
ParseIntEmptyString,
|
|
19
|
+
ParseIntInvalidDigit,
|
|
20
|
+
ParseIntInvalidRadix,
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Represents an error that occurred trying to parse an integer.
|
|
25
|
+
|
|
26
|
+
Variants:
|
|
27
|
+
|
|
28
|
+
```grain
|
|
29
|
+
ParseIntEmptyString
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Represents an error caused by trying to parse an empty string.
|
|
33
|
+
|
|
34
|
+
```grain
|
|
35
|
+
ParseIntInvalidDigit
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Represents an error caused by trying to parse a string with an invalid character.
|
|
39
|
+
|
|
40
|
+
```grain
|
|
41
|
+
ParseIntInvalidRadix
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Represents an error caused by trying to parse with an invalid radix.
|
|
45
|
+
|
|
46
|
+
## Values
|
|
47
|
+
|
|
48
|
+
Functions and constants included in the Parse module.
|
|
49
|
+
|
|
1
50
|
### Parse.**parseInt**
|
|
2
51
|
|
|
3
52
|
```grain
|
|
4
|
-
parseInt : (String, Number)
|
|
53
|
+
parseInt : (string: String, radix: Number) => Result<Number, ParseIntError>
|
|
5
54
|
```
|
|
6
55
|
|