@grain/stdlib 0.5.4 → 0.5.5

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 (59) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/array.gr +60 -57
  3. package/array.md +24 -6
  4. package/buffer.gr +71 -1
  5. package/buffer.md +142 -0
  6. package/bytes.gr +52 -3
  7. package/bytes.md +117 -0
  8. package/char.gr +21 -18
  9. package/char.md +18 -3
  10. package/immutablepriorityqueue.gr +13 -13
  11. package/int32.gr +39 -37
  12. package/int32.md +6 -0
  13. package/int64.gr +39 -37
  14. package/int64.md +6 -0
  15. package/list.gr +31 -22
  16. package/list.md +39 -10
  17. package/map.gr +19 -28
  18. package/number.gr +81 -5
  19. package/number.md +64 -2
  20. package/option.gr +30 -26
  21. package/option.md +12 -0
  22. package/package.json +1 -1
  23. package/path.gr +787 -0
  24. package/path.md +727 -0
  25. package/pervasives.gr +3 -4
  26. package/pervasives.md +6 -1
  27. package/queue.gr +11 -9
  28. package/queue.md +2 -0
  29. package/regex.gr +76 -3
  30. package/regex.md +70 -0
  31. package/result.gr +24 -20
  32. package/result.md +12 -0
  33. package/runtime/atof/common.gr +198 -0
  34. package/runtime/atof/common.md +243 -0
  35. package/runtime/atof/decimal.gr +663 -0
  36. package/runtime/atof/decimal.md +59 -0
  37. package/runtime/atof/lemire.gr +264 -0
  38. package/runtime/atof/lemire.md +6 -0
  39. package/runtime/atof/parse.gr +615 -0
  40. package/runtime/atof/parse.md +12 -0
  41. package/runtime/atof/slow.gr +238 -0
  42. package/runtime/atof/slow.md +6 -0
  43. package/runtime/atof/table.gr +2016 -0
  44. package/runtime/atof/table.md +12 -0
  45. package/runtime/{stringUtils.gr → atoi/parse.gr} +1 -1
  46. package/runtime/{stringUtils.md → atoi/parse.md} +1 -1
  47. package/runtime/bigint.gr +3 -3
  48. package/runtime/equal.gr +1 -1
  49. package/runtime/numberUtils.gr +2 -2
  50. package/runtime/numberUtils.md +6 -0
  51. package/runtime/numbers.gr +4 -4
  52. package/runtime/unsafe/conv.gr +21 -41
  53. package/runtime/unsafe/conv.md +0 -3
  54. package/runtime/unsafe/printWasm.gr +4 -40
  55. package/runtime/utils/printing.gr +3 -3
  56. package/stack.gr +4 -2
  57. package/stack.md +2 -0
  58. package/string.gr +1 -1
  59. package/sys/time.gr +4 -4
package/pervasives.gr CHANGED
@@ -473,10 +473,11 @@ export primitive ignore: a -> Void = "@ignore"
473
473
 
474
474
  /**
475
475
  * Assert that the given Boolean condition is `true`.
476
- * Throws an `AssertionError` if the condition is `false`.
477
476
  *
478
477
  * @param condition: The condition to assert
479
478
  *
479
+ * @throws AssertionError: When the `condition` is false
480
+ *
480
481
  * @example assert 3 > 2
481
482
  * @example assert true
482
483
  *
@@ -578,7 +579,7 @@ export let cons = (a, b) =>
578
579
  export let empty = [] // <- for parity with `cons`, but should be deleted as well
579
580
 
580
581
  // Setup exception printing
581
- @disableGC
582
+ @unsafe
582
583
  let rec setupExceptions = () => {
583
584
  Exception.dangerouslyRegisterPrinter(e => {
584
585
  match (e) {
@@ -589,8 +590,6 @@ let rec setupExceptions = () => {
589
590
  })
590
591
 
591
592
  Exception.dangerouslyRegisterBasePrinter(e => Some(toString(e)))
592
- Memory.decRef(WasmI32.fromGrain(setupExceptions))
593
- void
594
593
  }
595
594
 
596
595
  setupExceptions()
package/pervasives.md CHANGED
@@ -942,7 +942,6 @@ assert : Bool -> Void
942
942
  ```
943
943
 
944
944
  Assert that the given Boolean condition is `true`.
945
- Throws an `AssertionError` if the condition is `false`.
946
945
 
947
946
  Parameters:
948
947
 
@@ -950,6 +949,12 @@ Parameters:
950
949
  |-----|----|-----------|
951
950
  |`condition`|`Bool`|The condition to assert|
952
951
 
952
+ Throws:
953
+
954
+ `AssertionError`
955
+
956
+ * When the `condition` is false
957
+
953
958
  Examples:
954
959
 
955
960
  ```grain
package/queue.gr CHANGED
@@ -2,6 +2,8 @@
2
2
  * @module Queue: An immutable queue implementation. A queue is a FIFO (first-in-first-out) data structure where new values are added to the end and retrieved or removed from the beginning.
3
3
  * @example import Queue from "queue"
4
4
  * @since v0.2.0
5
+ *
6
+ * @deprecated This module will be renamed to ImmutableQueue in the v0.6.0 release of Grain.
5
7
  */
6
8
  import List from "list"
7
9
 
@@ -20,7 +22,7 @@ record Queue<a> {
20
22
 
21
23
  /**
22
24
  * An empty queue.
23
- *
25
+ *
24
26
  * @since v0.5.4
25
27
  */
26
28
  export let empty = {
@@ -30,11 +32,11 @@ export let empty = {
30
32
 
31
33
  /**
32
34
  * Creates an empty queue.
33
- *
35
+ *
34
36
  * @returns An empty queue
35
- *
37
+ *
36
38
  * @deprecated This will be removed in the v0.6.0 release of Grain.
37
- *
39
+ *
38
40
  * @since v0.2.0
39
41
  */
40
42
  export let make = () => {
@@ -43,7 +45,7 @@ export let make = () => {
43
45
 
44
46
  /**
45
47
  * Checks if the given queue contains any values.
46
- *
48
+ *
47
49
  * @param queue: The queue to check
48
50
  * @returns `true` if the given queue is empty or `false` otherwise
49
51
  *
@@ -58,7 +60,7 @@ export let isEmpty = queue => {
58
60
 
59
61
  /**
60
62
  * Returns the value at the beginning of the queue. It is not removed from the queue.
61
- *
63
+ *
62
64
  * @param queue: The queue to inspect
63
65
  * @returns `Some(value)` containing the value at the beginning of the queue, or `None` if the queue is empty
64
66
  *
@@ -76,7 +78,7 @@ export let peek = queue => {
76
78
 
77
79
  /**
78
80
  * Adds a value to the end of the queue.
79
- *
81
+ *
80
82
  * @param value: The value to append
81
83
  * @param queue: The queue to update
82
84
  * @returns An updated queue
@@ -95,7 +97,7 @@ export let push = (value, queue) => {
95
97
 
96
98
  /**
97
99
  * Dequeues the next value in the queue.
98
- *
100
+ *
99
101
  * @param queue: The queue to change
100
102
  * @returns An updated queue
101
103
  *
@@ -119,7 +121,7 @@ export let pop = queue => {
119
121
 
120
122
  /**
121
123
  * Get the number of values in a queue.
122
- *
124
+ *
123
125
  * @param queue: The queue to inspect
124
126
  * @returns The number of values in the queue
125
127
  *
package/queue.md CHANGED
@@ -2,6 +2,8 @@
2
2
  title: Queue
3
3
  ---
4
4
 
5
+ > **Deprecated:** This module will be renamed to ImmutableQueue in the v0.6.0 release of Grain.
6
+
5
7
  An immutable queue implementation. A queue is a FIFO (first-in-first-out) data structure where new values are added to the end and retrieved or removed from the beginning.
6
8
 
7
9
  <details disabled>
package/regex.gr CHANGED
@@ -458,7 +458,10 @@ enum ParsedRegularExpression {
458
458
  ), // regex, n-start, num-n, needs-backtrack
459
459
  REReference(Number, Bool), // n, case-sensitive
460
460
  RERange(RERange),
461
- REUnicodeCategories(List<UnicodeCategory>, Bool), // symlist, true=match/false=does-not-match
461
+ REUnicodeCategories(
462
+ List<UnicodeCategory>,
463
+ Bool
464
+ ), // symlist, true=match/false=does-not-match
462
465
  }
463
466
 
464
467
  let needsBacktrack = (rx: ParsedRegularExpression) => {
@@ -3626,7 +3629,7 @@ export record MatchResult {
3626
3629
  /**
3627
3630
  * Returns the contents of the given group
3628
3631
  */
3629
- group: Number -> Option<String>,
3632
+ group: Number -> Option<String>,
3630
3633
  /**
3631
3634
  * Returns the position of the given group
3632
3635
  */
@@ -3973,7 +3976,6 @@ let regexReplaceHelp =
3973
3976
  all: Bool,
3974
3977
  ) => {
3975
3978
  let buf = makeMatchBuffer(toSearch)
3976
- let mut out = []
3977
3979
  let rec loop = searchPos => {
3978
3980
  let state = Array.make(rx.reNumGroups, None)
3979
3981
  let inStart = max(0, searchPos - rx.reMaxLookbehind)
@@ -4067,3 +4069,74 @@ export let replaceAll =
4067
4069
  ) => {
4068
4070
  regexReplaceHelp(rx, toSearch, replacement, true)
4069
4071
  }
4072
+
4073
+ let regexSplitHelp = (rx: RegularExpression, str: String, all: Bool) => {
4074
+ // Get list of matches
4075
+ let regexMatches = if (all) {
4076
+ findAll(rx, str)
4077
+ } else {
4078
+ match (find(rx, str)) {
4079
+ None => [],
4080
+ Some(m) => [m],
4081
+ }
4082
+ }
4083
+ // Perform replacements
4084
+ let mut out = []
4085
+ let mut currentLocation = 0
4086
+ List.forEach(regexMatch => {
4087
+ let locations = regexMatch.allGroupPositions()
4088
+ Array.forEachi((pos, i) => {
4089
+ match (pos) {
4090
+ Some((start, end)) => {
4091
+ if (i == 0) {
4092
+ // Add the string between this match and the last match
4093
+ out = [String.slice(currentLocation, start, str), ...out]
4094
+ } else {
4095
+ // This adds the groups back in
4096
+ out = [String.slice(start, end, str), ...out]
4097
+ }
4098
+ if (end > currentLocation) currentLocation = end
4099
+ },
4100
+ None => void,
4101
+ }
4102
+ }, locations)
4103
+ }, regexMatches)
4104
+ out = [String.slice(currentLocation, String.length(str), str), ...out]
4105
+ List.reverse(out)
4106
+ }
4107
+
4108
+ /**
4109
+ * Splits the given string at the first match for the given regular expression.
4110
+ *
4111
+ * If the regex pattern contains capture groups, the content of the groups
4112
+ * will be included in the output list.
4113
+ *
4114
+ * @param rx: The regular expression to match
4115
+ * @param str: The string to split
4116
+ * @returns A list of the split segments
4117
+ *
4118
+ * @example assert Regex.split(Result.unwrap(Regex.make(",")), "a,b,c") == [ "a", "b,c" ]
4119
+ *
4120
+ * @since v0.5.5
4121
+ */
4122
+ export let split = (rx: RegularExpression, str: String) => {
4123
+ regexSplitHelp(rx, str, false)
4124
+ }
4125
+
4126
+ /**
4127
+ * Splits the given string at every match for the given regular expression.
4128
+ *
4129
+ * If the regex pattern contains capture groups, the content of the groups
4130
+ * will be included in the output list.
4131
+ *
4132
+ * @param rx: The regular expression to match
4133
+ * @param str: The string to split
4134
+ * @returns A list of the split segments
4135
+ *
4136
+ * @example assert Regex.splitAll(Result.unwrap(Regex.make(",")), "a,b,c") == [ "a", "b", "c" ]
4137
+ *
4138
+ * @since v0.5.5
4139
+ */
4140
+ export let splitAll = (rx: RegularExpression, str: String) => {
4141
+ regexSplitHelp(rx, str, true)
4142
+ }
package/regex.md CHANGED
@@ -447,3 +447,73 @@ Examples:
447
447
  assert Regex.replaceAll(Result.unwrap(Regex.make("o")), "skoot", "r") == "skrrt"
448
448
  ```
449
449
 
450
+ ### Regex.**split**
451
+
452
+ <details disabled>
453
+ <summary tabindex="-1">Added in <code>0.5.5</code></summary>
454
+ No other changes yet.
455
+ </details>
456
+
457
+ ```grain
458
+ split : (RegularExpression, String) -> List<String>
459
+ ```
460
+
461
+ Splits the given string at the first match for the given regular expression.
462
+
463
+ If the regex pattern contains capture groups, the content of the groups
464
+ will be included in the output list.
465
+
466
+ Parameters:
467
+
468
+ |param|type|description|
469
+ |-----|----|-----------|
470
+ |`rx`|`RegularExpression`|The regular expression to match|
471
+ |`str`|`String`|The string to split|
472
+
473
+ Returns:
474
+
475
+ |type|description|
476
+ |----|-----------|
477
+ |`List<String>`|A list of the split segments|
478
+
479
+ Examples:
480
+
481
+ ```grain
482
+ assert Regex.split(Result.unwrap(Regex.make(",")), "a,b,c") == [ "a", "b,c" ]
483
+ ```
484
+
485
+ ### Regex.**splitAll**
486
+
487
+ <details disabled>
488
+ <summary tabindex="-1">Added in <code>0.5.5</code></summary>
489
+ No other changes yet.
490
+ </details>
491
+
492
+ ```grain
493
+ splitAll : (RegularExpression, String) -> List<String>
494
+ ```
495
+
496
+ Splits the given string at every match for the given regular expression.
497
+
498
+ If the regex pattern contains capture groups, the content of the groups
499
+ will be included in the output list.
500
+
501
+ Parameters:
502
+
503
+ |param|type|description|
504
+ |-----|----|-----------|
505
+ |`rx`|`RegularExpression`|The regular expression to match|
506
+ |`str`|`String`|The string to split|
507
+
508
+ Returns:
509
+
510
+ |type|description|
511
+ |----|-----------|
512
+ |`List<String>`|A list of the split segments|
513
+
514
+ Examples:
515
+
516
+ ```grain
517
+ assert Regex.splitAll(Result.unwrap(Regex.make(",")), "a,b,c") == [ "a", "b", "c" ]
518
+ ```
519
+
package/result.gr CHANGED
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * @module Result: Utilities for working with the Result data type.
3
- *
3
+ *
4
4
  * The Result type is an enum that represents the possibility of a success case (with the `Ok` variant),
5
5
  * or an error case (with the `Err` variant). Use a Result as the return type of a function that may return an error.
6
- *
6
+ *
7
7
  * @example import Result from "result"
8
- *
9
- *
8
+ *
9
+ *
10
10
  * @example let success = Ok((x) => 1 + x) // Creates a successful Result containing (x) => 1 + x
11
11
  * @example let failure = Err("Something bad happened") // Creates an unsuccessful Result containing "Something bad happened"
12
- *
12
+ *
13
13
  * @since v0.2.0
14
14
  */
15
15
 
@@ -22,7 +22,7 @@
22
22
  *
23
23
  * @param result: The result to check
24
24
  * @returns `true` if the Result is the `Ok` variant or `false` otherwise
25
- *
25
+ *
26
26
  * @since v0.2.0
27
27
  */
28
28
  export let isOk = result => {
@@ -37,7 +37,7 @@ export let isOk = result => {
37
37
  *
38
38
  * @param result: The result to check
39
39
  * @returns `true` if the Result is the `Err` variant or `false` otherwise
40
- *
40
+ *
41
41
  * @since v0.2.0
42
42
  */
43
43
  export let isErr = result => !isOk(result)
@@ -47,7 +47,7 @@ export let isErr = result => !isOk(result)
47
47
  *
48
48
  * @param result: The result to convert
49
49
  * @returns `Some(value)` if the Result is `Ok(value)` or `None` if the Result is an `Err`
50
- *
50
+ *
51
51
  * @since v0.2.0
52
52
  */
53
53
  export let toOption = result => {
@@ -63,7 +63,7 @@ export let toOption = result => {
63
63
  * @param fn: The function to call on the value of an `Ok` variant
64
64
  * @param result: The result to map
65
65
  * @returns A new Result produced by the mapping function if the variant was `Ok` or the unmodified `Err` otherwise
66
- *
66
+ *
67
67
  * @since v0.2.0
68
68
  */
69
69
  export let flatMap = (fn, result) => {
@@ -79,7 +79,7 @@ export let flatMap = (fn, result) => {
79
79
  * @param fn: The function to call on the value of an `Err` variant
80
80
  * @param result: The result to map
81
81
  * @returns A new Result produced by the mapping function if the variant was `Err` or the unmodified `Ok` otherwise
82
- *
82
+ *
83
83
  * @since v0.2.0
84
84
  */
85
85
  export let flatMapErr = (fn, result) => {
@@ -95,7 +95,7 @@ export let flatMapErr = (fn, result) => {
95
95
  * @param fn: The function to call on the value of an `Ok` variant
96
96
  * @param result: The result to map
97
97
  * @returns A new `Ok` variant produced by the mapping function if the variant was `Ok` or the unmodified `Err` otherwise
98
- *
98
+ *
99
99
  * @since v0.2.0
100
100
  */
101
101
  export let map = (fn, result) => {
@@ -111,7 +111,7 @@ export let map = (fn, result) => {
111
111
  * @param fn: The function to call on the value of an `Err` variant
112
112
  * @param result: The result to map
113
113
  * @returns A new `Err` variant produced by the mapping function if the variant was `Err` or the unmodified `Ok` otherwise
114
- *
114
+ *
115
115
  * @since v0.2.0
116
116
  */
117
117
  export let mapErr = (fn, result) => {
@@ -129,8 +129,8 @@ export let mapErr = (fn, result) => {
129
129
  * @param def: A fallback value for an `Err` variant
130
130
  * @param result: The result to map
131
131
  * @returns The value produced by the mapping function if the result is of the `Ok` variant or the default value otherwise
132
- *
133
- * @since v0.2.0
132
+ *
133
+ * @since v0.2.0
134
134
  */
135
135
  export let mapWithDefault = (fn, def, result) => {
136
136
  match (result) {
@@ -148,7 +148,7 @@ export let mapWithDefault = (fn, def, result) => {
148
148
  * @param fnErr: The function to call on the value of an `Err` variant
149
149
  * @param result: The result to map
150
150
  * @returns The value produced by one of the mapping functions
151
- *
151
+ *
152
152
  * @since v0.2.0
153
153
  */
154
154
  export let mapWithDefaultFn = (fnOk, fnErr, result) => {
@@ -164,7 +164,7 @@ export let mapWithDefaultFn = (fnOk, fnErr, result) => {
164
164
  * @param result1: The first result
165
165
  * @param result2: The second result
166
166
  * @returns The first Result if it is the `Ok` variant or the second Result otherwise
167
- *
167
+ *
168
168
  * @since v0.2.0
169
169
  */
170
170
  export let or = (result1, result2) => {
@@ -180,7 +180,7 @@ export let or = (result1, result2) => {
180
180
  * @param result1: The first result
181
181
  * @param result2: The second result
182
182
  * @returns The second Result if both are the `Ok` variant or the first Result otherwise
183
- *
183
+ *
184
184
  * @since v0.2.0
185
185
  */
186
186
  export let and = (result1, result2) => {
@@ -198,7 +198,7 @@ export let and = (result1, result2) => {
198
198
  * @param fnOk: The function to call on the value of an `Ok` variant
199
199
  * @param fnErr: The function to call on the value of an `Err` variant
200
200
  * @param result: The result to inspect
201
- *
201
+ *
202
202
  * @since v0.2.0
203
203
  */
204
204
  export let peek = (fnOk, fnErr, result) => {
@@ -213,7 +213,7 @@ export let peek = (fnOk, fnErr, result) => {
213
213
  *
214
214
  * @param fn: The function to call on the value of an `Ok` variant
215
215
  * @param result: The result to inspect
216
- *
216
+ *
217
217
  * @since v0.2.0
218
218
  */
219
219
  export let peekOk = (fn, result) => {
@@ -225,7 +225,7 @@ export let peekOk = (fn, result) => {
225
225
  *
226
226
  * @param fn: The function to call on the value of an `Err` variant
227
227
  * @param result: The result to inspect
228
- *
228
+ *
229
229
  * @since v0.2.0
230
230
  */
231
231
  export let peekErr = (fn, result) => {
@@ -240,6 +240,8 @@ export let peekErr = (fn, result) => {
240
240
  * @param result: The result to extract a value from
241
241
  * @returns The unwrapped value if the Result is the `Ok` variant
242
242
  *
243
+ * @throws Failure(String): When the `result` is `Err`
244
+ *
243
245
  * @example Result.expect("Unexpected error", Ok(1234)) + 42
244
246
  *
245
247
  * @since v0.4.0
@@ -258,6 +260,8 @@ export let expect = (msg, result) => {
258
260
  * @param result: The result to extract a value from
259
261
  * @returns The unwrapped value if the result is the `Ok` variant
260
262
  *
263
+ * @throws Failure(String): When the `result` is `Err`
264
+ *
261
265
  * @example Result.unwrap(Err("This will throw"))
262
266
  *
263
267
  * @since v0.4.0
package/result.md CHANGED
@@ -406,6 +406,12 @@ Returns:
406
406
  |----|-----------|
407
407
  |`a`|The unwrapped value if the Result is the `Ok` variant|
408
408
 
409
+ Throws:
410
+
411
+ `Failure(String)`
412
+
413
+ * When the `result` is `Err`
414
+
409
415
  Examples:
410
416
 
411
417
  ```grain
@@ -438,6 +444,12 @@ Returns:
438
444
  |----|-----------|
439
445
  |`a`|The unwrapped value if the result is the `Ok` variant|
440
446
 
447
+ Throws:
448
+
449
+ `Failure(String)`
450
+
451
+ * When the `result` is `Err`
452
+
441
453
  Examples:
442
454
 
443
455
  ```grain
@@ -0,0 +1,198 @@
1
+ /* grainc-flags --no-pervasives */
2
+
3
+ // This module was based on Rust's dec2flt
4
+ // https://github.com/rust-lang/rust/blob/1cbc45942d5c0f6eb5d94e3b10762ba541958035/library/core/src/num/dec2flt/common.rs
5
+ // Rust's MIT license is provided below:
6
+ /*
7
+ * Permission is hereby granted, free of charge, to any
8
+ * person obtaining a copy of this software and associated
9
+ * documentation files (the "Software"), to deal in the
10
+ * Software without restriction, including without
11
+ * limitation the rights to use, copy, modify, merge,
12
+ * publish, distribute, sublicense, and/or sell copies of
13
+ * the Software, and to permit persons to whom the Software
14
+ * is furnished to do so, subject to the following
15
+ * conditions:
16
+ *
17
+ * The above copyright notice and this permission notice
18
+ * shall be included in all copies or substantial portions
19
+ * of the Software.
20
+ *
21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22
+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
23
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
24
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
25
+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
28
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
+ * DEALINGS IN THE SOFTWARE.
30
+ */
31
+
32
+ import WasmI32 from "runtime/unsafe/wasmi32"
33
+ import WasmI64 from "runtime/unsafe/wasmi64"
34
+ import WasmF64 from "runtime/unsafe/wasmf64"
35
+ import { newInt32, newInt64, newFloat64 } from "runtime/dataStructures"
36
+ import { get_POWERS10 } from "runtime/numberUtils"
37
+ import { get_F64_POWERS10_FAST_PATH, get_POWERS5 } from "./table"
38
+
39
+ primitive (&&): (Bool, Bool) -> Bool = "@and"
40
+ primitive (||): (Bool, Bool) -> Bool = "@or"
41
+ primitive (!): Bool -> Bool = "@not"
42
+
43
+ export record BiasedFp {
44
+ f: Int64,
45
+ mut e: Int32,
46
+ }
47
+
48
+ @unsafe
49
+ export let _MINIMUM_EXPONENT = -1023n
50
+ @unsafe
51
+ export let _MIN_EXPONENT_ROUND_TO_EVEN = -4N
52
+ @unsafe
53
+ export let _MAX_EXPONENT_ROUND_TO_EVEN = 23N
54
+ @unsafe
55
+ export let _MIN_EXPONENT_FAST_PATH = -22n
56
+ @unsafe
57
+ export let _MAX_EXPONENT_FAST_PATH = 22n
58
+ @unsafe
59
+ export let _MAX_EXPONENT_DISGUISED_FAST_PATH = 37n
60
+ @unsafe
61
+ export let _MAX_MANTISSA_FAST_PATH = WasmI64.shl(2N, 52N)
62
+ @unsafe
63
+ export let _MANTISSA_EXPLICIT_BITS_64 = 52N
64
+ @unsafe
65
+ export let _MANTISSA_EXPLICIT_BITS_32 = 52n
66
+ @unsafe
67
+ export let _INFINITE_POWER = 0x7FFn
68
+ @unsafe
69
+ export let _SMALLEST_POWER_OF_TEN = -342N
70
+ @unsafe
71
+ export let _LARGEST_POWER_OF_TEN = 308N
72
+ @unsafe
73
+ export let _SMALLEST_POWER_OF_FIVE = -342N
74
+ @unsafe
75
+ export let _LARGEST_POWER_OF_FIVE = 308N
76
+
77
+ @unsafe
78
+ export let _CHAR_CODE_UNDERSCORE = 0x5fn
79
+ @unsafe
80
+ export let _CHAR_CODE_PLUS = 0x2Bn
81
+ @unsafe
82
+ export let _CHAR_CODE_MINUS = 0x2Dn
83
+ @unsafe
84
+ export let _CHAR_CODE_0 = 0x30n
85
+ @unsafe
86
+ export let _CHAR_CODE_e = 0x65n
87
+ @unsafe
88
+ export let _CHAR_CODE_E = 0x45n
89
+ @unsafe
90
+ export let _CHAR_CODE_DOT = 0x2En
91
+ @unsafe
92
+ export let _CHAR_CODE_A = 0x41n
93
+ @unsafe
94
+ export let _CHAR_CODE_Z = 0x5an
95
+ @unsafe
96
+ export let _CHAR_CODE_a = 0x61n
97
+ @unsafe
98
+ export let _CHAR_CODE_f = 0x66n
99
+ @unsafe
100
+ export let _CHAR_CODE_i = 0x69n
101
+ @unsafe
102
+ export let _CHAR_CODE_n = 0x6en
103
+ @unsafe
104
+ export let _CHAR_CODE_t = 0x74n
105
+ @unsafe
106
+ export let _CHAR_CODE_y = 0x79n
107
+
108
+ export let fpZero = () => { f: 0L, e: 0l }
109
+ @unsafe
110
+ export let fpInf = () =>
111
+ {
112
+ f: 0L,
113
+ e: WasmI32.toGrain(newInt32(_INFINITE_POWER)): Int32,
114
+ }
115
+ export let fpErr = () => { f: 0L, e: -1l }
116
+ export let fpNan = () => { f: 1L, e: -1l }
117
+
118
+ @unsafe
119
+ export let getPowers10 = (i: WasmI32) => {
120
+ WasmI32.load(get_POWERS10(), WasmI32.mul(4n, i))
121
+ }
122
+
123
+ @unsafe
124
+ export let getPowers10FastPath = (i: WasmI32) => {
125
+ WasmF64.load(get_F64_POWERS10_FAST_PATH(), WasmI32.mul(8n, i))
126
+ }
127
+
128
+ // https://stdrs.dev/nightly/x86_64-unknown-linux-gnu/src/core/num/dec2flt/common.rs.html#165
129
+ @unsafe
130
+ export let is8Digits = (value: WasmI64) => {
131
+ let (+) = WasmI64.add
132
+ let (-) = WasmI64.sub
133
+ let (|) = WasmI64.or
134
+ let (&) = WasmI64.and
135
+ let (==) = WasmI64.eq
136
+
137
+ let a = value + 0x4646_4646_4646_4646N
138
+ let b = value - 0x3030_3030_3030_3030N
139
+ let c = (a | b) & 0x8080_8080_8080_8080N
140
+
141
+ c == 0N
142
+ }
143
+
144
+ // From Rust:
145
+ // Calculate a base 2 exponent from a decimal exponent.
146
+ // This uses a pre-computed integer approximation for
147
+ // log2(10), where 217706 / 2^16 is accurate for the
148
+ // entire range of non-finite decimal exponents.
149
+ @unsafe
150
+ export let power = (q: WasmI32) => {
151
+ let (+) = WasmI32.add
152
+ let (*) = WasmI32.mul
153
+ let (>>) = WasmI32.shrS
154
+
155
+ ((q * (152_170n + 65536n)) >> 16n) + 63n
156
+ }
157
+
158
+ @unsafe
159
+ export let fullMultiplication = (a: WasmI64, b: WasmI64) => {
160
+ // Adapted from https://www.codeproject.com/Tips/618570/UInt-Multiplication-Squaring
161
+ let (+) = WasmI64.add
162
+ let (*) = WasmI64.mul
163
+ let (&) = WasmI64.and
164
+ let (>>) = WasmI64.shrU
165
+ let (<<) = WasmI64.shl
166
+
167
+ let aLo = a & 0xffffffffN
168
+ let bLo = b & 0xffffffffN
169
+ let aLoxbLo = aLo * bLo
170
+ let w3 = aLoxbLo & 0xffffffffN
171
+ let k = aLoxbLo >> 32N
172
+
173
+ let aHi = a >> 32N
174
+ let mid = aHi * bLo + k
175
+ let k = mid & 0xffffffffN
176
+ let w1 = mid >> 32N
177
+
178
+ let bHi = b >> 32N
179
+ let mid = aLo * bHi + k
180
+ let k = mid >> 32N
181
+
182
+ let hi = aHi * bHi + w1 + k
183
+ let lo = (mid << 32N) + w3
184
+
185
+ (WasmI32.toGrain(newInt64(lo)): Int64, WasmI32.toGrain(newInt64(hi)): Int64)
186
+ }
187
+
188
+ @unsafe
189
+ export let biasedFpToNumber = (fp, negative) => {
190
+ let f = WasmI64.load(WasmI32.fromGrain(fp.f), 8n)
191
+ let e = WasmI64.extendI32S(WasmI32.load(WasmI32.fromGrain(fp.e), 8n))
192
+ let word = WasmI64.or(f, WasmI64.shl(e, _MANTISSA_EXPLICIT_BITS_64))
193
+ let mut float = WasmF64.reinterpretI64(word)
194
+ if (negative) {
195
+ float = WasmF64.neg(float)
196
+ }
197
+ WasmI32.toGrain(newFloat64(float)): Number
198
+ }