@grain/stdlib 0.5.4 → 0.5.6

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 +30 -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/number.gr CHANGED
@@ -18,8 +18,9 @@ import {
18
18
  isBoxedNumber,
19
19
  scalbn,
20
20
  } from "runtime/numbers"
21
- import { parseInt } from "runtime/stringUtils"
22
- import { newFloat64, newInt64 } from "runtime/dataStructures"
21
+ import Atoi from "runtime/atoi/parse"
22
+ import Atof from "runtime/atof/parse"
23
+ import { newFloat64, newInt64, allocateString } from "runtime/dataStructures"
23
24
  import Tags from "runtime/unsafe/tags"
24
25
  import Exception from "runtime/exception"
25
26
 
@@ -890,7 +891,80 @@ export let isInfinite = (x: Number) => {
890
891
  *
891
892
  * @since v0.4.5
892
893
  */
893
- export parseInt
894
+ export let parseInt = Atoi.parseInt
895
+
896
+ /**
897
+ * Parses a string representation of a float into a `Number`. Underscores that appear
898
+ * in numeric portions of the input are ignored.
899
+ *
900
+ * @param input: The string to parse
901
+ * @returns `Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise
902
+ *
903
+ * @since v0.5.5
904
+ */
905
+ export let parseFloat = Atof.parseFloat
906
+
907
+ /**
908
+ * Parses a string representation of an integer, float, or rational into a `Number`.
909
+ * Underscores that appear in the numeric portion of the input are ignored.
910
+ *
911
+ * @param input: The string to parse
912
+ * @returns `Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise
913
+ *
914
+ * @since v0.5.5
915
+ */
916
+ @unsafe
917
+ export let parse = input => {
918
+ match (parseInt(input, 10)) {
919
+ Ok(number) => Ok(number),
920
+ Err(msg) =>
921
+ match (parseFloat(input)) {
922
+ Ok(number) => Ok(number),
923
+ Err(_) => {
924
+ // Split the input on a `/` and attempt to parse a rational
925
+ let (+) = WasmI32.add
926
+ let (-) = WasmI32.sub
927
+ let (<) = WasmI32.ltU
928
+ let (==) = WasmI32.eq
929
+
930
+ // Search for `/`
931
+ let input = WasmI32.fromGrain(input)
932
+ let len = WasmI32.load(input, 4n)
933
+ let mut slashIdx = -1n
934
+ for (let mut i = 0n; i < len; i += 1n) {
935
+ if (WasmI32.load8U(input + i, 8n) == 0x2fn) {
936
+ slashIdx = i
937
+ break
938
+ }
939
+ }
940
+
941
+ if (slashIdx == -1n) {
942
+ Err(msg)
943
+ } else {
944
+ let numeratorLen = slashIdx
945
+ let denominatorLen = len - slashIdx - 1n
946
+
947
+ let numerator = allocateString(numeratorLen)
948
+ Memory.copy(numerator + 8n, input + 8n, numeratorLen)
949
+ let numerator = WasmI32.toGrain(numerator): String
950
+
951
+ let denominator = allocateString(denominatorLen)
952
+ Memory.copy(
953
+ denominator + 8n,
954
+ input + 8n + slashIdx + 1n,
955
+ denominatorLen
956
+ )
957
+ let denominator = WasmI32.toGrain(denominator): String
958
+
959
+ match ((parseInt(numerator, 10), parseInt(denominator, 10))) {
960
+ (Ok(numerator), Ok(denominator)) => Ok(numerator / denominator),
961
+ (Err(msg), _) | (_, Err(msg)) => Err(msg),
962
+ }
963
+ }
964
+ },
965
+ },
966
+ }
967
+ }
894
968
 
895
969
  /**
896
970
  * Computes how many times pi has to be subtracted to achieve the required bounds for sin.
@@ -974,11 +1048,12 @@ export let tan = (radians: Number) => {
974
1048
  // https://en.wikipedia.org/wiki/Lanczos_approximation
975
1049
  /**
976
1050
  * Computes the gamma function of a value using Lanczos approximation.
977
- * Fails when the given value is zero.
978
1051
  *
979
1052
  * @param z: The value to interpolate
980
1053
  * @returns The gamma of the given value
981
1054
  *
1055
+ * @throws InvalidArgument(String): When `z` is zero
1056
+ *
982
1057
  * @since v0.5.4
983
1058
  */
984
1059
  export let rec gamma = z => {
@@ -1026,11 +1101,12 @@ export let rec gamma = z => {
1026
1101
 
1027
1102
  /**
1028
1103
  * Computes the product of consecutive integers for an integer input and computes the gamma function for non-integer inputs.
1029
- * Fails if the input is a negative number.
1030
1104
  *
1031
1105
  * @param n: The value to factorialize
1032
1106
  * @returns The factorial of the given value
1033
1107
  *
1108
+ * @throws InvalidArgument(String): When `n` is negative
1109
+ *
1034
1110
  * @since v0.5.4
1035
1111
  */
1036
1112
  export let rec factorial = n => {
package/number.md CHANGED
@@ -729,6 +729,58 @@ Returns:
729
729
  |----|-----------|
730
730
  |`Result<Number, String>`|`Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise|
731
731
 
732
+ ### Number.**parseFloat**
733
+
734
+ <details disabled>
735
+ <summary tabindex="-1">Added in <code>0.5.5</code></summary>
736
+ No other changes yet.
737
+ </details>
738
+
739
+ ```grain
740
+ parseFloat : String -> Result<Number, String>
741
+ ```
742
+
743
+ Parses a string representation of a float into a `Number`. Underscores that appear
744
+ in numeric portions of the input are ignored.
745
+
746
+ Parameters:
747
+
748
+ |param|type|description|
749
+ |-----|----|-----------|
750
+ |`input`|`String`|The string to parse|
751
+
752
+ Returns:
753
+
754
+ |type|description|
755
+ |----|-----------|
756
+ |`Result<Number, String>`|`Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise|
757
+
758
+ ### Number.**parse**
759
+
760
+ <details disabled>
761
+ <summary tabindex="-1">Added in <code>0.5.5</code></summary>
762
+ No other changes yet.
763
+ </details>
764
+
765
+ ```grain
766
+ parse : String -> Result<Number, String>
767
+ ```
768
+
769
+ Parses a string representation of an integer, float, or rational into a `Number`.
770
+ Underscores that appear in the numeric portion of the input are ignored.
771
+
772
+ Parameters:
773
+
774
+ |param|type|description|
775
+ |-----|----|-----------|
776
+ |`input`|`String`|The string to parse|
777
+
778
+ Returns:
779
+
780
+ |type|description|
781
+ |----|-----------|
782
+ |`Result<Number, String>`|`Ok(value)` containing the parsed number on a successful parse or `Err(msg)` containing an error message string otherwise|
783
+
732
784
  ### Number.**sin**
733
785
 
734
786
  <details>
@@ -830,7 +882,6 @@ gamma : Number -> Number
830
882
  ```
831
883
 
832
884
  Computes the gamma function of a value using Lanczos approximation.
833
- Fails when the given value is zero.
834
885
 
835
886
  Parameters:
836
887
 
@@ -844,6 +895,12 @@ Returns:
844
895
  |----|-----------|
845
896
  |`Number`|The gamma of the given value|
846
897
 
898
+ Throws:
899
+
900
+ `InvalidArgument(String)`
901
+
902
+ * When `z` is zero
903
+
847
904
  ### Number.**factorial**
848
905
 
849
906
  <details disabled>
@@ -856,7 +913,6 @@ factorial : Number -> Number
856
913
  ```
857
914
 
858
915
  Computes the product of consecutive integers for an integer input and computes the gamma function for non-integer inputs.
859
- Fails if the input is a negative number.
860
916
 
861
917
  Parameters:
862
918
 
@@ -870,6 +926,12 @@ Returns:
870
926
  |----|-----------|
871
927
  |`Number`|The factorial of the given value|
872
928
 
929
+ Throws:
930
+
931
+ `InvalidArgument(String)`
932
+
933
+ * When `n` is negative
934
+
873
935
  ### Number.**toRadians**
874
936
 
875
937
  <details disabled>
package/option.gr CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * @module Option: Utilities for working with the Option data type.
3
- *
3
+ *
4
4
  * The Option type is an enum that represents the possibility of something being present (with the `Some` variant), or not (with the `None` variant). There’s no standalone `null` or `nil` type in Grain; use an Option where you would normally reach for `null` or `nil`.
5
- *
5
+ *
6
6
  * @example import Option from "option"
7
- *
7
+ *
8
8
  * @example let hasValue = Some(1234) // Creates an Option containing 1234
9
9
  * @example let noValue = None // Creates an Option containing nothing
10
- *
10
+ *
11
11
  * @since v0.2.0
12
12
  */
13
13
 
@@ -20,7 +20,7 @@
20
20
  *
21
21
  * @param option: The option to check
22
22
  * @returns `true` if the Option is the `Some` variant or `false` otherwise
23
- *
23
+ *
24
24
  * @since v0.2.0
25
25
  */
26
26
  export let isSome = option => {
@@ -35,7 +35,7 @@ export let isSome = option => {
35
35
  *
36
36
  * @param option: The option to check
37
37
  * @returns `true` if the Option is the `None` variant or `false` otherwise
38
- *
38
+ *
39
39
  * @since v0.2.0
40
40
  */
41
41
  export let isNone = option => {
@@ -51,7 +51,7 @@ export let isNone = option => {
51
51
  * @param value: The value to search for
52
52
  * @param option: The option to search
53
53
  * @returns `true` if the Option is equivalent to `Some(value)` or `false` otherwise
54
- *
54
+ *
55
55
  * @since v0.2.0
56
56
  */
57
57
  export let contains = (value, option) => {
@@ -68,7 +68,9 @@ export let contains = (value, option) => {
68
68
  * @param msg: The message to use upon failure
69
69
  * @param option: The option to extract a value from
70
70
  * @returns The unwrapped value if the Option is the `Some` variant
71
- *
71
+ *
72
+ * @throws Failure(String): When the `option` is `None`
73
+ *
72
74
  * @since v0.2.0
73
75
  */
74
76
  export let expect = (msg, option) => {
@@ -79,12 +81,14 @@ export let expect = (msg, option) => {
79
81
  }
80
82
 
81
83
  /**
82
- * Extracts the value inside a `Some` option, otherwise
84
+ * Extracts the value inside a `Some` option, otherwise
83
85
  * throws an exception containing a default message.
84
86
  *
85
87
  * @param option: The option to extract the value from
86
88
  * @returns The unwrapped value if the Option is the `Some` variant
87
- *
89
+ *
90
+ * @throws Failure(String): When the `option` is `None`
91
+ *
88
92
  * @since v0.2.0
89
93
  */
90
94
  export let unwrap = option => {
@@ -97,7 +101,7 @@ export let unwrap = option => {
97
101
  * @param default: The default value
98
102
  * @param option: The option to unwrap
99
103
  * @returns The unwrapped value if the Option is the `Some` variant or the default value otherwise
100
- *
104
+ *
101
105
  * @since v0.2.0
102
106
  */
103
107
  export let unwrapWithDefault = (default, option) => {
@@ -113,7 +117,7 @@ export let unwrapWithDefault = (default, option) => {
113
117
  * @param fn: The function to call on the value of a `Some` variant
114
118
  * @param option: The option to map
115
119
  * @returns A new `Some` variant produced by the mapping function if the variant was `Some` or the unmodified `None` otherwise
116
- *
120
+ *
117
121
  * @since v0.2.0
118
122
  */
119
123
  export let map = (fn, option) => {
@@ -131,7 +135,7 @@ export let map = (fn, option) => {
131
135
  * @param default: A fallback value for a `None` variant
132
136
  * @param option: The option to map
133
137
  * @returns The value produced by the mapping function if the Option is of the `Some` variant or the default value otherwise
134
- *
138
+ *
135
139
  * @since v0.2.0
136
140
  */
137
141
  export let mapWithDefault = (fn, default, option) => {
@@ -150,7 +154,7 @@ export let mapWithDefault = (fn, default, option) => {
150
154
  * @param defaultFn: The default function
151
155
  * @param option: The option to map
152
156
  * @returns The value produced by one of the mapping functions
153
- *
157
+ *
154
158
  * @since v0.2.0
155
159
  */
156
160
  export let mapWithDefaultFn = (fn, defaultFn, option) => {
@@ -166,7 +170,7 @@ export let mapWithDefaultFn = (fn, defaultFn, option) => {
166
170
  * @param fn: The function to call on the value of a `Some` variant
167
171
  * @param option: The option to map
168
172
  * @returns A new Option produced by the mapping function if the variant was `Some` or the unmodified `None` otherwise
169
- *
173
+ *
170
174
  * @since v0.2.0
171
175
  */
172
176
  export let flatMap = (fn, option) => {
@@ -183,7 +187,7 @@ export let flatMap = (fn, option) => {
183
187
  * @param fn: The predicate function to indicate if the option should remain `Some`
184
188
  * @param option: The option to inspect
185
189
  * @returns `Some(value)` if the variant was `Some` and the predicate returns `true` or `None` otherwise
186
- *
190
+ *
187
191
  * @since v0.2.0
188
192
  */
189
193
  export let filter = (fn, option) => {
@@ -204,7 +208,7 @@ export let filter = (fn, option) => {
204
208
  * @param optionA: The first option to combine
205
209
  * @param optionB: The second option to combine
206
210
  * @returns `Some((valueA, valueB))` if both Options are `Some` variants or `None` otherwise
207
- *
211
+ *
208
212
  * @since v0.2.0
209
213
  */
210
214
  export let zip = (optionA, optionB) => {
@@ -221,7 +225,7 @@ export let zip = (optionA, optionB) => {
221
225
  * @param optionA: The first option to combine
222
226
  * @param optionB: The second option to combine
223
227
  * @returns `Some(newValue)` if both Options are `Some` variants or `None` otherwise
224
- *
228
+ *
225
229
  * @since v0.2.0
226
230
  */
227
231
  export let zipWith = (fn, optionA, optionB) => {
@@ -236,7 +240,7 @@ export let zipWith = (fn, optionA, optionB) => {
236
240
  *
237
241
  * @param option: The option to flatten
238
242
  * @returns `Some(innerValue)` if all nested options were the `Some` variant or `None` otherwise
239
- *
243
+ *
240
244
  * @example Option.flatten(Some(Some(1))) == Some(1)
241
245
  *
242
246
  * @since v0.2.0
@@ -253,7 +257,7 @@ export let flatten = option => {
253
257
  *
254
258
  * @param option: The option to convert
255
259
  * @returns `[value]` if the Option was the `Some` variant or `[]` otherwise
256
- *
260
+ *
257
261
  * @since v0.2.0
258
262
  */
259
263
  export let toList = option => {
@@ -268,7 +272,7 @@ export let toList = option => {
268
272
  *
269
273
  * @param option: The option to convert
270
274
  * @returns `[> value]` if the Option was the `Some` variant or `[> ]` otherwise
271
- *
275
+ *
272
276
  * @since v0.2.0
273
277
  */
274
278
  export let toArray = option => {
@@ -284,7 +288,7 @@ export let toArray = option => {
284
288
  * @param err: The error to use if the option is `None`
285
289
  * @param option: The option to convert
286
290
  * @returns `Ok(value)` if the Option is `Some(value)` or `Err(err)` if the Option is `None`
287
- *
291
+ *
288
292
  * @since v0.2.0
289
293
  */
290
294
  export let toResult = (err, option) => {
@@ -299,7 +303,7 @@ export let toResult = (err, option) => {
299
303
  *
300
304
  * @param fn: The function to call on the value of a `Some` variant
301
305
  * @param option: The option to inspect
302
- *
306
+ *
303
307
  * @since v0.2.0
304
308
  */
305
309
  export let sideEffect = (fn, option) => {
@@ -316,7 +320,7 @@ export let sideEffect = (fn, option) => {
316
320
  * @param fn: The function to call on the value of a `Some` variant
317
321
  * @param option: The option to inspect
318
322
  * @returns The unmodified option
319
- *
323
+ *
320
324
  * @since v0.2.0
321
325
  */
322
326
  export let peek = (fn, option) => {
@@ -330,7 +334,7 @@ export let peek = (fn, option) => {
330
334
  * @param optionA: The first option
331
335
  * @param optionB: The second option
332
336
  * @returns The first Option if it is the `Some` variant or the second Option otherwise
333
- *
337
+ *
334
338
  * @since v0.2.0
335
339
  */
336
340
  export let or = (optionA, optionB) => {
@@ -346,7 +350,7 @@ export let or = (optionA, optionB) => {
346
350
  * @param optionA: The first option
347
351
  * @param optionB: The second option
348
352
  * @returns The second Option if both are the `Some` variant or the first Option otherwise
349
- *
353
+ *
350
354
  * @since v0.2.0
351
355
  */
352
356
  export let and = (optionA, optionB) => {
package/option.md CHANGED
@@ -130,6 +130,12 @@ Returns:
130
130
  |----|-----------|
131
131
  |`a`|The unwrapped value if the Option is the `Some` variant|
132
132
 
133
+ Throws:
134
+
135
+ `Failure(String)`
136
+
137
+ * When the `option` is `None`
138
+
133
139
  ### Option.**unwrap**
134
140
 
135
141
  <details disabled>
@@ -156,6 +162,12 @@ Returns:
156
162
  |----|-----------|
157
163
  |`a`|The unwrapped value if the Option is the `Some` variant|
158
164
 
165
+ Throws:
166
+
167
+ `Failure(String)`
168
+
169
+ * When the `option` is `None`
170
+
159
171
  ### Option.**unwrapWithDefault**
160
172
 
161
173
  <details disabled>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grain/stdlib",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "The standard library for the Grain language.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://grain-lang.org",