@grain/stdlib 0.5.13 → 0.6.1

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.
Files changed (155) hide show
  1. package/CHANGELOG.md +201 -0
  2. package/LICENSE +1 -1
  3. package/README.md +25 -2
  4. package/array.gr +1512 -199
  5. package/array.md +2032 -94
  6. package/bigint.gr +239 -140
  7. package/bigint.md +450 -106
  8. package/buffer.gr +595 -102
  9. package/buffer.md +903 -145
  10. package/bytes.gr +401 -110
  11. package/bytes.md +551 -63
  12. package/char.gr +228 -49
  13. package/char.md +373 -7
  14. package/exception.gr +26 -12
  15. package/exception.md +29 -5
  16. package/float32.gr +130 -109
  17. package/float32.md +185 -57
  18. package/float64.gr +112 -99
  19. package/float64.md +185 -57
  20. package/hash.gr +62 -40
  21. package/hash.md +27 -3
  22. package/int16.gr +430 -0
  23. package/int16.md +618 -0
  24. package/int32.gr +200 -269
  25. package/int32.md +254 -289
  26. package/int64.gr +142 -225
  27. package/int64.md +254 -289
  28. package/int8.gr +511 -0
  29. package/int8.md +786 -0
  30. package/json.gr +2071 -0
  31. package/json.md +646 -0
  32. package/list.gr +120 -68
  33. package/list.md +125 -80
  34. package/map.gr +560 -57
  35. package/map.md +672 -56
  36. package/marshal.gr +239 -227
  37. package/marshal.md +36 -4
  38. package/number.gr +626 -676
  39. package/number.md +738 -153
  40. package/option.gr +33 -35
  41. package/option.md +58 -42
  42. package/package.json +2 -2
  43. package/path.gr +148 -187
  44. package/path.md +47 -96
  45. package/pervasives.gr +75 -416
  46. package/pervasives.md +85 -180
  47. package/priorityqueue.gr +433 -74
  48. package/priorityqueue.md +422 -54
  49. package/queue.gr +362 -80
  50. package/queue.md +433 -38
  51. package/random.gr +67 -75
  52. package/random.md +68 -40
  53. package/range.gr +135 -63
  54. package/range.md +198 -43
  55. package/rational.gr +284 -0
  56. package/rational.md +545 -0
  57. package/regex.gr +933 -1066
  58. package/regex.md +59 -60
  59. package/result.gr +23 -25
  60. package/result.md +54 -39
  61. package/runtime/atof/common.gr +78 -82
  62. package/runtime/atof/common.md +22 -10
  63. package/runtime/atof/decimal.gr +102 -127
  64. package/runtime/atof/decimal.md +28 -7
  65. package/runtime/atof/lemire.gr +56 -71
  66. package/runtime/atof/lemire.md +9 -1
  67. package/runtime/atof/parse.gr +83 -110
  68. package/runtime/atof/parse.md +12 -2
  69. package/runtime/atof/slow.gr +28 -35
  70. package/runtime/atof/slow.md +9 -1
  71. package/runtime/atof/table.gr +19 -18
  72. package/runtime/atof/table.md +10 -2
  73. package/runtime/atoi/parse.gr +153 -136
  74. package/runtime/atoi/parse.md +50 -1
  75. package/runtime/bigint.gr +410 -517
  76. package/runtime/bigint.md +71 -57
  77. package/runtime/compare.gr +176 -85
  78. package/runtime/compare.md +31 -1
  79. package/runtime/dataStructures.gr +144 -32
  80. package/runtime/dataStructures.md +267 -31
  81. package/runtime/debugPrint.gr +34 -15
  82. package/runtime/debugPrint.md +37 -5
  83. package/runtime/equal.gr +53 -52
  84. package/runtime/equal.md +30 -1
  85. package/runtime/exception.gr +38 -47
  86. package/runtime/exception.md +10 -8
  87. package/runtime/gc.gr +23 -152
  88. package/runtime/gc.md +13 -17
  89. package/runtime/malloc.gr +31 -31
  90. package/runtime/malloc.md +11 -3
  91. package/runtime/numberUtils.gr +193 -174
  92. package/runtime/numberUtils.md +29 -9
  93. package/runtime/numbers.gr +1695 -1021
  94. package/runtime/numbers.md +1098 -134
  95. package/runtime/string.gr +543 -245
  96. package/runtime/string.md +76 -6
  97. package/runtime/unsafe/constants.gr +30 -13
  98. package/runtime/unsafe/constants.md +80 -0
  99. package/runtime/unsafe/conv.gr +55 -28
  100. package/runtime/unsafe/conv.md +41 -9
  101. package/runtime/unsafe/memory.gr +10 -30
  102. package/runtime/unsafe/memory.md +15 -19
  103. package/runtime/unsafe/tags.gr +37 -21
  104. package/runtime/unsafe/tags.md +88 -8
  105. package/runtime/unsafe/wasmf32.gr +30 -36
  106. package/runtime/unsafe/wasmf32.md +64 -56
  107. package/runtime/unsafe/wasmf64.gr +30 -36
  108. package/runtime/unsafe/wasmf64.md +64 -56
  109. package/runtime/unsafe/wasmi32.gr +49 -66
  110. package/runtime/unsafe/wasmi32.md +102 -94
  111. package/runtime/unsafe/wasmi64.gr +52 -79
  112. package/runtime/unsafe/wasmi64.md +108 -100
  113. package/runtime/utils/printing.gr +13 -15
  114. package/runtime/utils/printing.md +11 -3
  115. package/runtime/wasi.gr +294 -295
  116. package/runtime/wasi.md +62 -42
  117. package/set.gr +574 -64
  118. package/set.md +634 -54
  119. package/stack.gr +181 -64
  120. package/stack.md +271 -42
  121. package/string.gr +453 -533
  122. package/string.md +241 -151
  123. package/uint16.gr +369 -0
  124. package/uint16.md +585 -0
  125. package/uint32.gr +470 -0
  126. package/uint32.md +737 -0
  127. package/uint64.gr +471 -0
  128. package/uint64.md +737 -0
  129. package/uint8.gr +369 -0
  130. package/uint8.md +585 -0
  131. package/uri.gr +1093 -0
  132. package/uri.md +477 -0
  133. package/{sys → wasi}/file.gr +914 -500
  134. package/{sys → wasi}/file.md +454 -50
  135. package/wasi/process.gr +292 -0
  136. package/{sys → wasi}/process.md +164 -6
  137. package/wasi/random.gr +77 -0
  138. package/wasi/random.md +80 -0
  139. package/{sys → wasi}/time.gr +15 -22
  140. package/{sys → wasi}/time.md +5 -5
  141. package/immutablearray.gr +0 -929
  142. package/immutablearray.md +0 -1038
  143. package/immutablemap.gr +0 -493
  144. package/immutablemap.md +0 -479
  145. package/immutablepriorityqueue.gr +0 -360
  146. package/immutablepriorityqueue.md +0 -291
  147. package/immutableset.gr +0 -498
  148. package/immutableset.md +0 -449
  149. package/runtime/debug.gr +0 -2
  150. package/runtime/debug.md +0 -6
  151. package/runtime/unsafe/errors.gr +0 -36
  152. package/runtime/unsafe/errors.md +0 -204
  153. package/sys/process.gr +0 -254
  154. package/sys/random.gr +0 -79
  155. package/sys/random.md +0 -66
@@ -1,5 +1,3 @@
1
- /* grainc-flags --no-pervasives */
2
-
3
1
  // This module was based on Rust's dec2flt
4
2
  // https://github.com/rust-lang/rust/blob/1cbc45942d5c0f6eb5d94e3b10762ba541958035/library/core/src/num/dec2flt/lemire.rs
5
3
  // Rust's MIT license is provided below:
@@ -13,11 +11,11 @@
13
11
  * the Software, and to permit persons to whom the Software
14
12
  * is furnished to do so, subject to the following
15
13
  * conditions:
16
- *
14
+ *
17
15
  * The above copyright notice and this permission notice
18
16
  * shall be included in all copies or substantial portions
19
17
  * of the Software.
20
- *
18
+ *
21
19
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22
20
  * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
23
21
  * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
@@ -28,14 +26,19 @@
28
26
  * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
27
  * DEALINGS IN THE SOFTWARE.
30
28
  */
29
+ @noPervasives
30
+ module Lemire
31
31
 
32
- import WasmI32 from "runtime/unsafe/wasmi32"
33
- import WasmI64 from "runtime/unsafe/wasmi64"
32
+ from "runtime/unsafe/wasmi32" include WasmI32
33
+ from "runtime/unsafe/wasmi64" include WasmI64
34
34
 
35
- import { newInt32, newInt64, newFloat64 } from "runtime/dataStructures"
36
- import { get_POWERS5 } from "./table"
35
+ from "runtime/dataStructures" include DataStructures
36
+ use DataStructures.{ newInt32, newInt64, newFloat64 }
37
+ from "runtime/atof/table" include Table
38
+ use Table.{ get_POWERS5 }
37
39
 
38
- import {
40
+ from "runtime/atof/common" include Common
41
+ use Common.{
39
42
  _SMALLEST_POWER_OF_FIVE,
40
43
  _LARGEST_POWER_OF_FIVE,
41
44
  _INFINITE_POWER,
@@ -48,15 +51,15 @@ import {
48
51
  _MAX_EXPONENT_ROUND_TO_EVEN,
49
52
  fullMultiplication,
50
53
  power,
51
- BiasedFp,
54
+ type BiasedFp,
52
55
  fpZero,
53
56
  fpInf,
54
57
  fpErr,
55
- } from "./common"
58
+ }
56
59
 
57
- primitive (&&): (Bool, Bool) -> Bool = "@and"
58
- primitive (||): (Bool, Bool) -> Bool = "@or"
59
- primitive (!): Bool -> Bool = "@not"
60
+ primitive (&&) = "@and"
61
+ primitive (||) = "@or"
62
+ primitive (!) = "@not"
60
63
 
61
64
  // From Rust:
62
65
  // This will compute or rather approximate w * 5**q and return a pair of 64-bit words
@@ -64,18 +67,11 @@ primitive (!): Bool -> Bool = "@not"
64
67
  // bits and the low part corresponding to the least significant bits.
65
68
  @unsafe
66
69
  let computeProductApprox = (q: WasmI64, w: WasmI64, precision: WasmI64) => {
67
- let (==) = WasmI64.eq
68
- let (&) = WasmI64.and
69
- let (>) = WasmI64.gtU
70
- let (<) = WasmI64.ltU
71
- let (>=) = WasmI64.geS
72
- let (<=) = WasmI64.leS
73
- let (>>) = WasmI64.shrU
74
- let (-) = WasmI64.sub
75
- let (+) = WasmI64.add
70
+ use WasmI64.{ (==), (&), gtU as (>), ltU as (<), (>=), (<=), (>>>), (-), (+) }
71
+ use WasmI32.{ (*) }
76
72
 
77
73
  let mask = if (precision < 64N) {
78
- 0xFFFF_FFFF_FFFF_FFFFN >> precision
74
+ 0xFFFF_FFFF_FFFF_FFFFN >>> precision
79
75
  } else {
80
76
  0xFFFF_FFFF_FFFF_FFFFN
81
77
  }
@@ -85,10 +81,11 @@ let computeProductApprox = (q: WasmI64, w: WasmI64, precision: WasmI64) => {
85
81
  // That means whenever we need to round ties to even, we always have
86
82
  // an exact value.
87
83
  let index = q - _SMALLEST_POWER_OF_FIVE
88
- let n = WasmI32.mul(16n, WasmI32.wrapI64(index))
89
- let lo5 = WasmI64.load(get_POWERS5(), n),
90
- hi5 = WasmI64.load(get_POWERS5(), WasmI32.add(n, 8n))
91
-
84
+ let n = 16n * WasmI32.wrapI64(index)
85
+ use WasmI32.{ (+) }
86
+ let lo5 = WasmI64.load(get_POWERS5(), n)
87
+ and hi5 = WasmI64.load(get_POWERS5(), n + 8n)
88
+ use WasmI64.{ (+) }
92
89
  // From Rust:
93
90
  // Only need one multiplication as long as there is 1 zero but
94
91
  // in the explicit mantissa bits, +1 for the hidden bit, +1 to
@@ -120,16 +117,8 @@ let computeProductApprox = (q: WasmI64, w: WasmI64, precision: WasmI64) => {
120
117
  // Returns the significant bits and a biased binary exponent that can be directly shifted into exponent bits:
121
118
  // (u64, i32)
122
119
  @unsafe
123
- export let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
124
- let (==) = WasmI64.eq
125
- let (<) = WasmI64.ltS
126
- let (<=) = WasmI64.leS
127
- let (>) = WasmI64.gtS
128
- let (>=) = WasmI64.geS
129
- let (<<) = WasmI64.shl
130
- let (>>) = WasmI64.shrS
131
- let (&) = WasmI64.and
132
- let (+) = WasmI64.add
120
+ provide let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
121
+ use WasmI64.{ (==), (<), (<=), (>), (>=), (<<), (>>), (&), (+), (>>>) }
133
122
 
134
123
  let w = mantissa
135
124
  let q = exponent
@@ -163,33 +152,30 @@ export let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
163
152
  match (lo == 0xFFFF_FFFF_FFFF_FFFFN && !(q >= -27N && q <= 55N)) {
164
153
  true => fpErr(),
165
154
  false => {
166
- let upperbit = WasmI32.wrapI64(WasmI64.shrU(hi, 63N))
167
- let mut mantissa = WasmI64.shrU(
168
- hi,
169
- WasmI64.extendI32S(
170
- {
171
- let (+) = WasmI32.add
172
- let (-) = WasmI32.sub
173
- upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
174
- }
175
- )
176
- )
155
+ let upperbit = WasmI32.wrapI64(hi >>> 63N)
156
+ let mut mantissa = hi >>> WasmI64.extendI32S({
157
+ use WasmI32.{ (+), (-) }
158
+ upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
159
+ })
177
160
  let mut power2 = {
178
- let (+) = WasmI32.add
179
- let (-) = WasmI32.sub
161
+ use WasmI32.{ (+), (-) }
180
162
  let q = WasmI32.wrapI64(q)
181
163
  let lz = WasmI32.wrapI64(lz)
182
164
  power(q) + upperbit - lz - _MINIMUM_EXPONENT
183
165
  }
184
- if (WasmI32.leS(power2, 0n)) {
166
+
167
+ use WasmI32.{ (<=) }
168
+ if (power2 <= 0n) {
169
+ use WasmI32.{ (+), (*), (>=) }
185
170
  // -power2 + 1 >= 64
186
- if (WasmI32.geS(WasmI32.add(WasmI32.mul(-1n, power2), 1n), 64n)) {
171
+ if (-1n * power2 + 1n >= 64n) {
187
172
  // Have more than 64 bits below the minimum exponent, must be 0.
188
173
  fpZero()
189
174
  } else {
175
+ use WasmI64.{ (>=) }
190
176
  // Have a subnormal value.
191
- mantissa = mantissa >>
192
- WasmI64.extendI32S(WasmI32.add(WasmI32.mul(-1n, power2), 1n))
177
+ mantissa = mantissa >> WasmI64.extendI32S(-1n * power2 + 1n)
178
+ use WasmI64.{ (+) }
193
179
  mantissa += mantissa & 1N
194
180
  mantissa = mantissa >> 1N
195
181
  power2 = if (mantissa >= 1N << _MANTISSA_EXPLICIT_BITS_64) {
@@ -204,6 +190,7 @@ export let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
204
190
  }
205
191
  }
206
192
  } else {
193
+ use WasmI64.{ (<=) }
207
194
  // Need to handle rounding ties. Normally, we need to round up,
208
195
  // but if we fall right in between and and we have an even basis, we
209
196
  // need to round down.
@@ -220,38 +207,36 @@ export let computeFloat = (exponent: WasmI64, mantissa: WasmI64) => {
220
207
  q >= _MIN_EXPONENT_ROUND_TO_EVEN &&
221
208
  q <= _MAX_EXPONENT_ROUND_TO_EVEN &&
222
209
  (mantissa & 3N) == 1N &&
223
- mantissa <<
224
- WasmI64.extendI32S(
225
- {
226
- let (+) = WasmI32.add
227
- let (-) = WasmI32.sub
228
- upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
229
- }
230
- ) ==
231
- hi
210
+ mantissa << WasmI64.extendI32S({
211
+ use WasmI32.{ (+), (-) }
212
+ upperbit + 64n - _MANTISSA_EXPLICIT_BITS_32 - 3n
213
+ }) == hi
232
214
  ) {
215
+ use WasmI64.{ (^) }
233
216
  // Zero the lowest bit, so we don't round up.
234
217
  // mantissa &= !1N;
235
- mantissa = mantissa & WasmI64.xor(1N, -1N)
218
+ mantissa = mantissa & (1N ^ -1N)
236
219
  }
237
220
  // Round-to-even, then shift the significant digits into place.
238
221
  mantissa += mantissa & 1N
239
- mantissa = WasmI64.shrU(mantissa, 1N)
222
+ use WasmI64.{ (>>>) }
223
+ mantissa = mantissa >>> 1N
240
224
  if (WasmI64.geU(mantissa, 2N << _MANTISSA_EXPLICIT_BITS_64)) {
225
+ use WasmI32.{ (+) }
241
226
  // Rounding up overflowed, so the carry bit is set. Set the
242
227
  // mantissa to 1 (only the implicit, hidden bit is set) and
243
228
  // increase the exponent.
244
229
  mantissa = 1N << _MANTISSA_EXPLICIT_BITS_64
245
- power2 = WasmI32.add(power2, 1n)
230
+ power2 += 1n
246
231
  }
232
+ use WasmI32.{ (>=) }
233
+ use WasmI64.{ (^) }
247
234
  // Zero out the hidden bit.
248
- mantissa = mantissa &
249
- WasmI64.xor(1N << _MANTISSA_EXPLICIT_BITS_64, -1N)
250
- if (WasmI32.geS(power2, _INFINITE_POWER)) {
235
+ mantissa = mantissa & (1N << _MANTISSA_EXPLICIT_BITS_64 ^ -1N)
236
+ if (power2 >= _INFINITE_POWER) {
251
237
  // Exponent is above largest normal value, must be infinite.
252
238
  fpInf()
253
239
  } else {
254
-
255
240
  {
256
241
  f: WasmI32.toGrain(newInt64(mantissa)): Int64,
257
242
  e: WasmI32.toGrain(newInt32(power2)): Int32,
@@ -1,6 +1,14 @@
1
+ ---
2
+ title: Lemire
3
+ ---
4
+
5
+ ## Values
6
+
7
+ Functions and constants included in the Lemire module.
8
+
1
9
  ### Lemire.**computeFloat**
2
10
 
3
11
  ```grain
4
- computeFloat : (WasmI64, WasmI64) -> %Common.BiasedFp
12
+ computeFloat : (exponent: WasmI64, mantissa: WasmI64) => Common.BiasedFp
5
13
  ```
6
14
 
@@ -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,13 +26,16 @@
26
26
  * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
27
  * DEALINGS IN THE SOFTWARE.
28
28
  */
29
+ module Parse
29
30
 
30
- import WasmI32 from "runtime/unsafe/wasmi32"
31
- import WasmI64 from "runtime/unsafe/wasmi64"
32
- import WasmF64 from "runtime/unsafe/wasmf64"
33
- import { newInt32, newInt64, newFloat64 } from "runtime/dataStructures"
31
+ from "runtime/unsafe/wasmi32" include WasmI32
32
+ from "runtime/unsafe/wasmi64" include WasmI64
33
+ from "runtime/unsafe/wasmf64" include WasmF64
34
+ from "runtime/dataStructures" include DataStructures
35
+ use DataStructures.{ newInt32, newInt64, newFloat64 }
34
36
 
35
- import {
37
+ from "runtime/atof/common" include Common
38
+ use Common.{
36
39
  _CHAR_CODE_UNDERSCORE,
37
40
  _CHAR_CODE_PLUS,
38
41
  _CHAR_CODE_MINUS,
@@ -58,41 +61,32 @@ import {
58
61
  biasedFpToNumber,
59
62
  fpNan,
60
63
  fpInf,
61
- } from "./common"
64
+ }
62
65
 
63
- import { computeFloat } from "./lemire"
64
- import { parseLongMantissa } from "./slow"
66
+ from "runtime/atof/lemire" include Lemire
67
+ use Lemire.{ computeFloat }
68
+ from "runtime/atof/slow" include Slow
69
+ use Slow.{ parseLongMantissa }
65
70
 
66
71
  // Try to parse 8 digits at a time:
67
72
  // https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
68
73
  @unsafe
69
74
  let parse8Digits = (digits: WasmI64) => {
70
- let (+) = WasmI64.add
71
- let (-) = WasmI64.sub
72
- let (*) = WasmI64.mul
73
- let (>>) = WasmI64.shrU
74
- let (&) = WasmI64.and
75
- let (|) = WasmI64.or
76
- let (==) = WasmI64.eq
75
+ use WasmI64.{ (+), (-), (*), (>>>), (&), (|), (==) }
77
76
 
78
77
  let _MASK = 0x0000_00FF_0000_00FFN
79
78
 
80
79
  let a = digits - 0x3030_3030_3030_3030N
81
- let b = a * 10N + (a >> 8N)
80
+ let b = a * 10N + (a >>> 8N)
82
81
  let c = (b & _MASK) * 0x000F_4240_0000_0064N
83
- let d = (b >> 16N & _MASK) * 0x0000_2710_0000_0001N
82
+ let d = (b >>> 16N & _MASK) * 0x0000_2710_0000_0001N
84
83
 
85
- (c + d) >> 32N
84
+ (c + d) >>> 32N
86
85
  }
87
86
 
88
87
  @unsafe
89
88
  let parseScientificExponent = (ptr: WasmI32, offset: WasmI32, len: WasmI32) => {
90
- let (+) = WasmI32.add
91
- let (-) = WasmI32.sub
92
- let (>=) = WasmI32.geU
93
- let (<) = WasmI32.ltU
94
- let (==) = WasmI32.eq
95
- let (!=) = WasmI32.ne
89
+ use WasmI32.{ (+), (-), (*), geU as (>=), ltU as (<), (==), (!=) }
96
90
 
97
91
  let mut offset = offset
98
92
  let mut exponent = 0n
@@ -119,8 +113,9 @@ let parseScientificExponent = (ptr: WasmI32, offset: WasmI32, len: WasmI32) => {
119
113
  let char = WasmI32.load8U(ptr, offset)
120
114
  let digit = char - 0x30n
121
115
  if (digit >= 0n && digit < 10n) {
122
- if (WasmI32.ltS(exponent, 0x10000n)) {
123
- exponent = WasmI32.add(digit, WasmI32.mul(10n, exponent))
116
+ use WasmI32.{ (<) }
117
+ if (exponent < 0x10000n) {
118
+ exponent = digit + 10n * exponent
124
119
  }
125
120
  offset += 1n
126
121
  } else if (char == _CHAR_CODE_UNDERSCORE) {
@@ -132,7 +127,7 @@ let parseScientificExponent = (ptr: WasmI32, offset: WasmI32, len: WasmI32) => {
132
127
  if (offset != len) {
133
128
  Err("Invalid exponent")
134
129
  } else if (negative) {
135
- Ok(WasmI32.toGrain(newInt32(WasmI32.sub(0n, exponent))): Int32)
130
+ Ok(WasmI32.toGrain(newInt32(0n - exponent)): Int32)
136
131
  } else {
137
132
  Ok(WasmI32.toGrain(newInt32(exponent)): Int32)
138
133
  }
@@ -141,13 +136,8 @@ let parseScientificExponent = (ptr: WasmI32, offset: WasmI32, len: WasmI32) => {
141
136
 
142
137
  @unsafe
143
138
  let parseFloatToParts = (string: String) => {
144
- let (+) = WasmI32.add
145
- let (-) = WasmI32.sub
146
- let (>) = WasmI32.gtU
147
- let (>=) = WasmI32.geU
148
- let (<) = WasmI32.ltU
149
- let (==) = WasmI32.eq
150
- let (!=) = WasmI32.ne
139
+ use WasmI32.{ (+), (-), gtU as (>), geU as (>=), ltU as (<), (==), (!=) }
140
+ use WasmI64.{ (+) as addWasmI64, (*) }
151
141
 
152
142
  let ptr = WasmI32.fromGrain(string)
153
143
  match (WasmI32.load(ptr, 4n)) {
@@ -183,10 +173,7 @@ let parseFloatToParts = (string: String) => {
183
173
  let char = WasmI32.load8U(ptr, i)
184
174
  let digit = char - _CHAR_CODE_0
185
175
  if (digit >= 0n && digit < 10n) {
186
- mantissa = WasmI64.add(
187
- WasmI64.mul(mantissa, 10N),
188
- WasmI64.extendI32U(digit)
189
- )
176
+ mantissa = addWasmI64(mantissa * 10N, WasmI64.extendI32U(digit))
190
177
  numDigits += 1n
191
178
  i += 1n
192
179
  } else if (char == _CHAR_CODE_UNDERSCORE) {
@@ -207,10 +194,7 @@ let parseFloatToParts = (string: String) => {
207
194
  while (WasmI32.leU(i + 8n, len)) {
208
195
  let digits = WasmI64.load(ptr, i)
209
196
  if (is8Digits(digits)) {
210
- mantissa = WasmI64.add(
211
- parse8Digits(digits),
212
- WasmI64.mul(mantissa, 100000000N)
213
- )
197
+ mantissa = addWasmI64(parse8Digits(digits), mantissa * 100000000N)
214
198
  i += 8n
215
199
  numDigitsAfterDot += 8n
216
200
  } else {
@@ -222,10 +206,7 @@ let parseFloatToParts = (string: String) => {
222
206
  let char = WasmI32.load8U(ptr, i)
223
207
  let digit = char - _CHAR_CODE_0
224
208
  if (digit >= 0n && digit < 10n) {
225
- mantissa = WasmI64.add(
226
- WasmI64.extendI32U(digit),
227
- WasmI64.mul(mantissa, 10N)
228
- )
209
+ mantissa = addWasmI64(WasmI64.extendI32U(digit), mantissa * 10N)
229
210
  i += 1n
230
211
  numDigitsAfterDot += 1n
231
212
  } else if (char == _CHAR_CODE_UNDERSCORE) {
@@ -242,7 +223,7 @@ let parseFloatToParts = (string: String) => {
242
223
  numDigits += numDigitsAfterDot
243
224
 
244
225
  match (numDigits) {
245
- n when n == 0n => Err("Invalid float"),
226
+ 0n => Err("Invalid float"),
246
227
  _ => {
247
228
  let _MAX_MANTISSA_DIGITS = 19n // 10^19 fits in uint64
248
229
  let _MIN_19DIGIT_INT = 100_0000_0000_0000_0000N
@@ -266,7 +247,7 @@ let parseFloatToParts = (string: String) => {
266
247
  Ok(exponentNumber) => {
267
248
  let exponentNumber = WasmI32.load(
268
249
  WasmI32.fromGrain(exponentNumber),
269
- 8n
250
+ 4n
270
251
  )
271
252
  exponent += exponentNumber
272
253
 
@@ -278,14 +259,15 @@ let parseFloatToParts = (string: String) => {
278
259
  while (i < len) {
279
260
  let c = WasmI32.load8U(ptr, i)
280
261
  if (c == _CHAR_CODE_DOT || c == _CHAR_CODE_0) {
262
+ use WasmI32.{ (<), (>) }
281
263
  let n = c - (_CHAR_CODE_0 - 1n)
282
- numDigits -= if (WasmI32.ltS(n, 0n)) {
283
- 0n
284
- } else if (WasmI32.gtS(n, 255n)) {
285
- 255n
286
- } else {
287
- n
288
- }
264
+ numDigits -= if (n < 0n) {
265
+ 0n
266
+ } else if (n > 255n) {
267
+ 255n
268
+ } else {
269
+ n
270
+ }
289
271
  i += 1n
290
272
  } else if (c == _CHAR_CODE_UNDERSCORE) {
291
273
  continue
@@ -296,7 +278,8 @@ let parseFloatToParts = (string: String) => {
296
278
 
297
279
  // Attempt to parse 19 digits, the most that can fit in an i64
298
280
  let mut digitsParsed = 0n
299
- if (WasmI32.gtS(numDigits, 0n)) {
281
+ use WasmI32.{ (>) }
282
+ if (numDigits > 0n) {
300
283
  manyDigits = true
301
284
  mantissa = 0N
302
285
 
@@ -306,8 +289,8 @@ let parseFloatToParts = (string: String) => {
306
289
  let char = WasmI32.load8U(ptr, i)
307
290
  let digit = char - _CHAR_CODE_0
308
291
  if (digit >= 0n && digit < 10n) {
309
- mantissa = WasmI64.add(
310
- WasmI64.mul(mantissa, 10N),
292
+ mantissa = addWasmI64(
293
+ mantissa * 10N,
311
294
  WasmI64.extendI32U(digit)
312
295
  )
313
296
  i += 1n
@@ -339,8 +322,8 @@ let parseFloatToParts = (string: String) => {
339
322
  let char = WasmI32.load8U(ptr, i)
340
323
  let digit = char - _CHAR_CODE_0
341
324
  if (digit < 10n) {
342
- mantissa = WasmI64.add(
343
- WasmI64.mul(mantissa, 10N),
325
+ mantissa = addWasmI64(
326
+ mantissa * 10N,
344
327
  WasmI64.extendI32U(digit)
345
328
  )
346
329
  i += 1n
@@ -365,7 +348,7 @@ let parseFloatToParts = (string: String) => {
365
348
  WasmI32.toGrain(newInt64(mantissa)): Int64,
366
349
  negative,
367
350
  manyDigits,
368
- )
351
+ ),
369
352
  )
370
353
  } else {
371
354
  Ok(
@@ -374,7 +357,7 @@ let parseFloatToParts = (string: String) => {
374
357
  WasmI32.toGrain(newInt64(mantissa)): Int64,
375
358
  negative,
376
359
  manyDigits,
377
- )
360
+ ),
378
361
  )
379
362
  }
380
363
  },
@@ -388,12 +371,7 @@ let parseFloatToParts = (string: String) => {
388
371
 
389
372
  @unsafe
390
373
  let parseInfNan = s => {
391
- let (+) = WasmI32.add
392
- let (-) = WasmI32.sub
393
- let (<) = WasmI32.ltS
394
- let (>=) = WasmI32.geS
395
- let (<=) = WasmI32.leS
396
- let (==) = WasmI32.eq
374
+ use WasmI32.{ (+), (-), (<), (>=), (<=), (==) }
397
375
 
398
376
  let ptr = WasmI32.fromGrain(s)
399
377
  match (WasmI32.load(ptr, 4n)) {
@@ -448,7 +426,9 @@ let parseInfNan = s => {
448
426
  ) {
449
427
  Ok((fpNan(), negative))
450
428
  } else if (
451
- c1 == _CHAR_CODE_i && c2 == _CHAR_CODE_n && c3 == _CHAR_CODE_f
429
+ c1 == _CHAR_CODE_i &&
430
+ c2 == _CHAR_CODE_n &&
431
+ c3 == _CHAR_CODE_f
452
432
  ) {
453
433
  if (len - i == 3n) {
454
434
  Ok((fpInf(), negative))
@@ -497,15 +477,14 @@ let parseInfNan = s => {
497
477
  }
498
478
 
499
479
  @unsafe
500
- export let isFastPath =
501
- (
502
- exponent: WasmI32,
503
- mantissa: WasmI64,
504
- negative: Bool,
505
- manyDigits: Bool,
506
- ) => {
507
- let (<=) = WasmI32.leS
508
- let (<<) = WasmI64.shl
480
+ provide let isFastPath = (
481
+ exponent: WasmI32,
482
+ mantissa: WasmI64,
483
+ negative: Bool,
484
+ manyDigits: Bool,
485
+ ) => {
486
+ use WasmI32.{ (<=) }
487
+ use WasmI64.{ (<<) }
509
488
 
510
489
  _MIN_EXPONENT_FAST_PATH <= exponent &&
511
490
  exponent <= _MAX_EXPONENT_DISGUISED_FAST_PATH &&
@@ -514,53 +493,48 @@ export let isFastPath =
514
493
  }
515
494
 
516
495
  @unsafe
517
- export let parseFloat = (string: String) => {
518
- let (!=) = WasmI32.ne
519
-
496
+ provide let parseFloat = (string: String) => {
497
+ use WasmI32.{ (!=), (*) }
520
498
  match (parseFloatToParts(string)) {
521
499
  Ok((exponent, mantissa, negative, manyDigits)) => {
522
- let exponent = WasmI32.load(WasmI32.fromGrain(exponent), 8n)
500
+ use WasmI64.{ (+), (>) }
501
+ let exponent = WasmI32.load(WasmI32.fromGrain(exponent), 4n)
523
502
  let mantissa = WasmI64.load(WasmI32.fromGrain(mantissa), 8n)
524
503
  let floatOpt = if (isFastPath(exponent, mantissa, negative, manyDigits)) {
525
- let (<=) = WasmI32.leS
504
+ use WasmI32.{ (<=) }
526
505
  if (exponent <= _MAX_EXPONENT_FAST_PATH) {
527
506
  // normal fast path
528
- let (*) = WasmF64.mul
529
- let (/) = WasmF64.div
530
- let (<) = WasmI32.leS
531
-
507
+ use WasmF64.{ (/), (*) }
508
+ use WasmI32.{ (<) }
532
509
  let mantissa = WasmF64.convertI64U(mantissa)
533
510
  let n = if (exponent < 0n) {
534
- mantissa / getPowers10FastPath(WasmI32.mul(exponent, -1n))
511
+ use WasmI32.{ (*) }
512
+ mantissa / getPowers10FastPath(exponent * -1n)
535
513
  } else {
536
514
  mantissa * getPowers10FastPath(exponent)
537
515
  }
538
516
  if (negative) {
539
- Some(WasmI32.toGrain(newFloat64(n * -1.W)): Number)
517
+ Some(WasmI32.toGrain(newFloat64(n * -1.0W)): Number)
540
518
  } else {
541
519
  Some(WasmI32.toGrain(newFloat64(n)): Number)
542
520
  }
543
521
  } else {
544
522
  // disguised fast path
545
- let (-) = WasmI32.sub
546
- let (*) = WasmF64.mul
547
- let (>) = WasmI64.gtS
523
+ use WasmI32.{ (-) }
524
+ use WasmI64.{ (*), (<=) }
548
525
 
549
526
  let shift = exponent - _MAX_EXPONENT_FAST_PATH
550
527
 
551
- let mantissa = WasmI64.mul(
552
- mantissa,
553
- WasmI64.extendI32U(getPowers10(shift))
554
- )
528
+ let mantissa = mantissa * WasmI64.extendI32U(getPowers10(shift))
555
529
  if (mantissa > _MAX_MANTISSA_FAST_PATH) {
556
530
  None
557
531
  } else {
558
- assert WasmI64.leS(mantissa, _MAX_MANTISSA_FAST_PATH)
532
+ use WasmF64.{ (*) }
559
533
 
560
534
  let mantissa = WasmF64.convertI64U(mantissa)
561
535
  let n = mantissa * getPowers10FastPath(_MAX_EXPONENT_FAST_PATH)
562
536
  if (negative) {
563
- Some(WasmI32.toGrain(newFloat64(n * -1.W)): Number)
537
+ Some(WasmI32.toGrain(newFloat64(n * -1.0W)): Number)
564
538
  } else {
565
539
  Some(WasmI32.toGrain(newFloat64(n)): Number)
566
540
  }
@@ -573,6 +547,7 @@ export let parseFloat = (string: String) => {
573
547
  match (floatOpt) {
574
548
  Some(n) => Ok(n),
575
549
  None => {
550
+ use WasmI32.{ (<), (>=) }
576
551
  // From Rust:
577
552
  // If significant digits were truncated, then we can have rounding error
578
553
  // only if `mantissa + 1` produces a different result. We also avoid
@@ -581,23 +556,21 @@ export let parseFloat = (string: String) => {
581
556
 
582
557
  let mut fp = computeFloat(WasmI64.extendI32S(exponent), mantissa)
583
558
  let f = WasmI64.load(WasmI32.fromGrain(fp.f), 8n)
584
- let e = WasmI32.load(WasmI32.fromGrain(fp.e), 8n)
585
- if (manyDigits && WasmI32.geS(e, 0n)) {
586
- let fp2 = computeFloat(
587
- WasmI64.extendI32S(exponent),
588
- WasmI64.add(mantissa, 1N)
589
- )
559
+ let e = WasmI32.load(WasmI32.fromGrain(fp.e), 4n)
560
+ if (manyDigits && e >= 0n) {
561
+ use WasmI64.{ (!=) as neWasmI64 }
562
+ let fp2 = computeFloat(WasmI64.extendI32S(exponent), mantissa + 1N)
590
563
  let f2 = WasmI64.load(WasmI32.fromGrain(fp2.f), 8n)
591
- let e2 = WasmI32.load(WasmI32.fromGrain(fp2.e), 8n)
592
- if (e != e2 || WasmI64.ne(f, f2)) {
564
+ let e2 = WasmI32.load(WasmI32.fromGrain(fp2.e), 4n)
565
+ if (e != e2 || neWasmI64(f, f2)) {
593
566
  fp.e = -1l
594
567
  }
595
568
  }
596
569
 
597
570
  // Unable to correctly round the float using the Eisel-Lemire algorithm.
598
571
  // Fallback to a slower, but always correct algorithm.
599
- let e = WasmI32.load(WasmI32.fromGrain(fp.e), 8n)
600
- if (WasmI32.ltS(e, 0n)) {
572
+ let e = WasmI32.load(WasmI32.fromGrain(fp.e), 4n)
573
+ if (e < 0n) {
601
574
  fp = parseLongMantissa(string)
602
575
  }
603
576
 
@@ -1,12 +1,22 @@
1
+ ---
2
+ title: Parse
3
+ ---
4
+
5
+ ## Values
6
+
7
+ Functions and constants included in the Parse module.
8
+
1
9
  ### Parse.**isFastPath**
2
10
 
3
11
  ```grain
4
- isFastPath : (WasmI32, WasmI64, Bool, Bool) -> Bool
12
+ isFastPath :
13
+ (exponent: WasmI32, mantissa: WasmI64, negative: Bool, manyDigits: Bool) =>
14
+ Bool
5
15
  ```
6
16
 
7
17
  ### Parse.**parseFloat**
8
18
 
9
19
  ```grain
10
- parseFloat : String -> Result<Number, String>
20
+ parseFloat : (string: String) => Result<Number, String>
11
21
  ```
12
22