@grain/stdlib 0.4.4 → 0.5.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.
Files changed (97) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +1 -1
  3. package/array.gr +92 -73
  4. package/array.md +18 -18
  5. package/bigint.gr +497 -0
  6. package/bigint.md +811 -0
  7. package/buffer.gr +56 -217
  8. package/buffer.md +24 -17
  9. package/bytes.gr +103 -205
  10. package/bytes.md +19 -0
  11. package/char.gr +152 -166
  12. package/char.md +200 -0
  13. package/exception.md +6 -0
  14. package/float32.gr +159 -82
  15. package/float32.md +315 -0
  16. package/float64.gr +163 -82
  17. package/float64.md +315 -0
  18. package/hash.gr +53 -49
  19. package/int32.gr +479 -230
  20. package/int32.md +937 -0
  21. package/int64.gr +479 -230
  22. package/int64.md +937 -0
  23. package/list.gr +530 -116
  24. package/list.md +1141 -0
  25. package/map.gr +302 -121
  26. package/map.md +525 -0
  27. package/number.gr +51 -57
  28. package/number.md +37 -3
  29. package/option.gr +25 -25
  30. package/option.md +1 -1
  31. package/package.json +3 -3
  32. package/pervasives.gr +504 -52
  33. package/pervasives.md +1116 -0
  34. package/queue.gr +8 -1
  35. package/queue.md +10 -0
  36. package/random.gr +196 -0
  37. package/random.md +179 -0
  38. package/range.gr +26 -26
  39. package/regex.gr +1833 -842
  40. package/regex.md +11 -11
  41. package/result.md +1 -1
  42. package/runtime/bigint.gr +2045 -0
  43. package/runtime/bigint.md +326 -0
  44. package/runtime/dataStructures.gr +99 -279
  45. package/runtime/dataStructures.md +391 -0
  46. package/runtime/debug.gr +0 -1
  47. package/runtime/debug.md +6 -0
  48. package/runtime/equal.gr +40 -37
  49. package/runtime/equal.md +6 -0
  50. package/runtime/exception.gr +28 -15
  51. package/runtime/exception.md +30 -0
  52. package/runtime/gc.gr +50 -20
  53. package/runtime/gc.md +36 -0
  54. package/runtime/malloc.gr +32 -22
  55. package/runtime/malloc.md +55 -0
  56. package/runtime/numberUtils.gr +297 -142
  57. package/runtime/numberUtils.md +54 -0
  58. package/runtime/numbers.gr +1204 -453
  59. package/runtime/numbers.md +300 -0
  60. package/runtime/string.gr +193 -228
  61. package/runtime/string.md +24 -0
  62. package/runtime/stringUtils.gr +62 -38
  63. package/runtime/stringUtils.md +6 -0
  64. package/runtime/unsafe/constants.gr +17 -0
  65. package/runtime/unsafe/constants.md +72 -0
  66. package/runtime/unsafe/conv.gr +10 -10
  67. package/runtime/unsafe/conv.md +71 -0
  68. package/runtime/unsafe/errors.md +204 -0
  69. package/runtime/unsafe/memory.gr +14 -3
  70. package/runtime/unsafe/memory.md +54 -0
  71. package/runtime/unsafe/printWasm.gr +4 -4
  72. package/runtime/unsafe/printWasm.md +24 -0
  73. package/runtime/unsafe/tags.gr +11 -10
  74. package/runtime/unsafe/tags.md +120 -0
  75. package/runtime/unsafe/wasmf32.gr +9 -2
  76. package/runtime/unsafe/wasmf32.md +168 -0
  77. package/runtime/unsafe/wasmf64.gr +9 -2
  78. package/runtime/unsafe/wasmf64.md +168 -0
  79. package/runtime/unsafe/wasmi32.gr +65 -47
  80. package/runtime/unsafe/wasmi32.md +282 -0
  81. package/runtime/unsafe/wasmi64.gr +78 -50
  82. package/runtime/unsafe/wasmi64.md +300 -0
  83. package/runtime/utils/printing.gr +62 -0
  84. package/runtime/utils/printing.md +18 -0
  85. package/runtime/wasi.gr +200 -46
  86. package/runtime/wasi.md +839 -0
  87. package/set.gr +125 -121
  88. package/set.md +24 -21
  89. package/stack.gr +29 -29
  90. package/stack.md +4 -6
  91. package/string.gr +434 -415
  92. package/string.md +3 -3
  93. package/sys/file.gr +477 -482
  94. package/sys/process.gr +33 -47
  95. package/sys/random.gr +48 -20
  96. package/sys/random.md +38 -0
  97. package/sys/time.gr +12 -28
package/queue.gr CHANGED
@@ -5,7 +5,14 @@
5
5
  */
6
6
  import List from "list"
7
7
 
8
- record Queue<a> { forwards: List<a>, backwards: List<a> }
8
+ /**
9
+ * @section Types: Type declarations included in the Queue module.
10
+ */
11
+
12
+ record Queue<a> {
13
+ forwards: List<a>,
14
+ backwards: List<a>,
15
+ }
9
16
 
10
17
  /**
11
18
  * @section Values: Functions for working with queues.
package/queue.md CHANGED
@@ -13,6 +13,16 @@ No other changes yet.
13
13
  import Queue from "queue"
14
14
  ```
15
15
 
16
+ ## Types
17
+
18
+ Type declarations included in the Queue module.
19
+
20
+ ### Queue.**Queue**
21
+
22
+ ```grain
23
+ type Queue<a>
24
+ ```
25
+
16
26
  ## Values
17
27
 
18
28
  Functions for working with queues.
package/random.gr ADDED
@@ -0,0 +1,196 @@
1
+ /**
2
+ * @module Random: Pseudo-random number generation.
3
+ * @example import Random from "random"
4
+ * @since v0.5.0
5
+ */
6
+ import WasiRandom from "sys/random"
7
+ import Result from "result"
8
+ import Int32 from "int32"
9
+ import Int64 from "int64"
10
+ import WasmI32 from "runtime/unsafe/wasmi32"
11
+ import WasmI64 from "runtime/unsafe/wasmi64"
12
+ import Memory from "runtime/unsafe/memory"
13
+ import DS from "runtime/dataStructures"
14
+
15
+ /**
16
+ * @section Types: Type declarations included in the Random module.
17
+ */
18
+
19
+ record Random {
20
+ seed: Int64,
21
+ mut counter: Int64,
22
+ mut initialized: Bool,
23
+ }
24
+
25
+ /**
26
+ * @section Values: Functions for working with pseudo-random number generators.
27
+ */
28
+
29
+ let incCounter = random => {
30
+ random.counter = Int64.incr(random.counter)
31
+ }
32
+
33
+ // https://arxiv.org/pdf/2004.06278v3.pdf
34
+ @unsafe
35
+ let squares = (ctr: Int64, key: Int64) => {
36
+ // Implemented with @unsafe to boost efficiency
37
+ // and have fine-grained control over overflow semantics
38
+ let ctr = WasmI64.load(WasmI32.fromGrain(ctr), 8n)
39
+ let key = WasmI64.load(WasmI32.fromGrain(key), 8n)
40
+ let mut x = WasmI64.mul(ctr, key)
41
+ let mut y = x
42
+ let mut z = WasmI64.add(y, key)
43
+ // round 1
44
+ x = WasmI64.add(WasmI64.mul(x, x), y)
45
+ x = WasmI64.or(WasmI64.shrU(x, 32N), WasmI64.shl(x, 32N))
46
+ // round 2
47
+ x = WasmI64.add(WasmI64.mul(x, x), z)
48
+ x = WasmI64.or(WasmI64.shrU(x, 32N), WasmI64.shl(x, 32N))
49
+ // round 3
50
+ x = WasmI64.add(WasmI64.mul(x, x), y)
51
+ x = WasmI64.or(WasmI64.shrU(x, 32N), WasmI64.shl(x, 32N))
52
+ let ret = WasmI32.wrapI64(
53
+ WasmI64.shrU(WasmI64.add(WasmI64.mul(x, x), z), 32N)
54
+ )
55
+ WasmI32.toGrain(DS.newInt32(ret)): Int32
56
+ }
57
+
58
+ /**
59
+ * Creates a new pseudo-random number generator with the given seed.
60
+ *
61
+ * @param seed: The seed for the pseudo-random number generator
62
+ * @returns The pseudo-random number generator
63
+ *
64
+ * @since v0.5.0
65
+ */
66
+ export let make = seed => {
67
+ { seed, counter: 0L, initialized: false }
68
+ }
69
+
70
+ /**
71
+ * Creates a new pseudo-random number generator with a random seed.
72
+ *
73
+ * @returns `Ok(generator)` of a pseudo-random number generator if successful or `Err(exception)` otherwise
74
+ *
75
+ * @since v0.5.0
76
+ */
77
+ export let makeUnseeded = () => {
78
+ // TODO: Should we just .expect this result for UX's sake?
79
+ Result.map(seed => {
80
+ { seed, counter: 0L, initialized: false }
81
+ }, WasiRandom.randomInt64())
82
+ }
83
+
84
+ /**
85
+ * [Internal note]
86
+ * For low seed numbers, we sometimes need to churn through
87
+ * some iterations to start getting interesting numbers. Taking
88
+ * a cue from the API in https://pypi.org/project/squares-rng/ ,
89
+ * we churn through until we generate an int with a MSB of 1.
90
+ * Then, to avoid making all of the first generated numbers negative,
91
+ * we do another increment at the end.
92
+ */
93
+ let checkInitialized = (random: Random) => {
94
+ if (!random.initialized) {
95
+ while (Int32.gt(Int32.clz(squares(random.counter, random.seed)), 0l)) {
96
+ incCounter(random)
97
+ }
98
+ // now that it's initialized, increment it again to make it a little more random
99
+ incCounter(random)
100
+ random.initialized = true
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Generates a random 32-bit integer from the given pseudo-random number generator.
106
+ *
107
+ * @param random: The pseudo-random number generator to use
108
+ * @returns The randomly generated number
109
+ *
110
+ * @since v0.5.0
111
+ */
112
+ export let nextInt32 = (random: Random) => {
113
+ checkInitialized(random)
114
+ let ret = squares(random.counter, random.seed)
115
+ incCounter(random)
116
+ ret
117
+ }
118
+
119
+ /**
120
+ * Generates a random 64-bit integer from the given pseudo-random number generator.
121
+ *
122
+ * @param random: The pseudo-random number generator to use
123
+ * @returns The randomly generated number
124
+ *
125
+ * @since v0.5.0
126
+ */
127
+ export let nextInt64 = (random: Random) => {
128
+ checkInitialized(random)
129
+ let ret1 = Int64.fromNumber(
130
+ Int32.toNumber(squares(random.counter, random.seed))
131
+ )
132
+ incCounter(random)
133
+ let ret2 = Int64.fromNumber(
134
+ Int32.toNumber(squares(random.counter, random.seed))
135
+ )
136
+ incCounter(random)
137
+ Int64.lor(Int64.shl(ret1, 32L), ret2)
138
+ }
139
+
140
+ /**
141
+ * Generates a random 32-bit integer from the given pseudo-random number generator
142
+ * from a uniform distribution in the given range.
143
+ *
144
+ * @param random: The pseudo-random number generator to use
145
+ * @param low: The lower bound of the range (inclusive)
146
+ * @param high: The upper bound of the range (exclusive)
147
+ * @returns The randomly generated number
148
+ *
149
+ * @since v0.5.0
150
+ */
151
+ export let nextInt32InRange = (random: Random, low: Int32, high: Int32) => {
152
+ // Algorithm source: https://www.pcg-random.org/posts/bounded-rands.html#bitmask-with-rejection-unbiased-apples-method
153
+ let (+) = Int32.add
154
+ let (-) = Int32.sub
155
+ let (*) = Int32.mul
156
+ let (/) = Int32.divU
157
+ let (&) = Int32.land
158
+ let (>) = Int32.gtU
159
+ let range = high - low - 1l
160
+ let mask = Int32.shrU(Int32.lnot(0l), Int32.clz(Int32.lor(range, 1l)))
161
+ let mut x = nextInt32(random) & mask
162
+ let mut iters = 0l
163
+ while (x > range) {
164
+ x = nextInt32(random) & mask
165
+ iters += 1l
166
+ }
167
+ x + low
168
+ }
169
+
170
+ /**
171
+ * Generates a random 64-bit integer from the given pseudo-random number generator
172
+ * from a uniform distribution in the given range.
173
+ *
174
+ * @param random: The pseudo-random number generator to use
175
+ * @param low: The lower bound of the range (inclusive)
176
+ * @param high: The upper bound of the range (exclusive)
177
+ * @returns The randomly generated number
178
+ *
179
+ * @since v0.5.0
180
+ */
181
+ export let nextInt64InRange = (random: Random, low: Int64, high: Int64) => {
182
+ // Algorithm source: https://www.pcg-random.org/posts/bounded-rands.html#bitmask-with-rejection-unbiased-apples-method
183
+ let (+) = Int64.add
184
+ let (-) = Int64.sub
185
+ let (*) = Int64.mul
186
+ let (/) = Int64.divU
187
+ let (&) = Int64.land
188
+ let (>) = Int64.gtU
189
+ let range = high - low - 1L
190
+ let mask = Int64.shrU(Int64.lnot(0L), Int64.clz(Int64.lor(range, 1L)))
191
+ let mut x = nextInt64(random) & mask
192
+ while (x > range) {
193
+ x = nextInt64(random) & mask
194
+ }
195
+ x + low
196
+ }
package/random.md ADDED
@@ -0,0 +1,179 @@
1
+ ---
2
+ title: Random
3
+ ---
4
+
5
+ Pseudo-random number generation.
6
+
7
+ <details disabled>
8
+ <summary tabindex="-1">Added in <code>next</code></summary>
9
+ No other changes yet.
10
+ </details>
11
+
12
+ ```grain
13
+ import Random from "random"
14
+ ```
15
+
16
+ ## Types
17
+
18
+ Type declarations included in the Random module.
19
+
20
+ ### Random.**Random**
21
+
22
+ ```grain
23
+ type Random
24
+ ```
25
+
26
+ ## Values
27
+
28
+ Functions for working with pseudo-random number generators.
29
+
30
+ ### Random.**make**
31
+
32
+ <details disabled>
33
+ <summary tabindex="-1">Added in <code>next</code></summary>
34
+ No other changes yet.
35
+ </details>
36
+
37
+ ```grain
38
+ make : Int64 -> Random
39
+ ```
40
+
41
+ Creates a new pseudo-random number generator with the given seed.
42
+
43
+ Parameters:
44
+
45
+ |param|type|description|
46
+ |-----|----|-----------|
47
+ |`seed`|`Int64`|The seed for the pseudo-random number generator|
48
+
49
+ Returns:
50
+
51
+ |type|description|
52
+ |----|-----------|
53
+ |`Random`|The pseudo-random number generator|
54
+
55
+ ### Random.**makeUnseeded**
56
+
57
+ <details disabled>
58
+ <summary tabindex="-1">Added in <code>next</code></summary>
59
+ No other changes yet.
60
+ </details>
61
+
62
+ ```grain
63
+ makeUnseeded : () -> Result<Random, Exception>
64
+ ```
65
+
66
+ Creates a new pseudo-random number generator with a random seed.
67
+
68
+ Returns:
69
+
70
+ |type|description|
71
+ |----|-----------|
72
+ |`Result<Random, Exception>`|`Ok(generator)` of a pseudo-random number generator if successful or `Err(exception)` otherwise|
73
+
74
+ ### Random.**nextInt32**
75
+
76
+ <details disabled>
77
+ <summary tabindex="-1">Added in <code>next</code></summary>
78
+ No other changes yet.
79
+ </details>
80
+
81
+ ```grain
82
+ nextInt32 : Random -> Int32
83
+ ```
84
+
85
+ Generates a random 32-bit integer from the given pseudo-random number generator.
86
+
87
+ Parameters:
88
+
89
+ |param|type|description|
90
+ |-----|----|-----------|
91
+ |`random`|`Random`|The pseudo-random number generator to use|
92
+
93
+ Returns:
94
+
95
+ |type|description|
96
+ |----|-----------|
97
+ |`Int32`|The randomly generated number|
98
+
99
+ ### Random.**nextInt64**
100
+
101
+ <details disabled>
102
+ <summary tabindex="-1">Added in <code>next</code></summary>
103
+ No other changes yet.
104
+ </details>
105
+
106
+ ```grain
107
+ nextInt64 : Random -> Int64
108
+ ```
109
+
110
+ Generates a random 64-bit integer from the given pseudo-random number generator.
111
+
112
+ Parameters:
113
+
114
+ |param|type|description|
115
+ |-----|----|-----------|
116
+ |`random`|`Random`|The pseudo-random number generator to use|
117
+
118
+ Returns:
119
+
120
+ |type|description|
121
+ |----|-----------|
122
+ |`Int64`|The randomly generated number|
123
+
124
+ ### Random.**nextInt32InRange**
125
+
126
+ <details disabled>
127
+ <summary tabindex="-1">Added in <code>next</code></summary>
128
+ No other changes yet.
129
+ </details>
130
+
131
+ ```grain
132
+ nextInt32InRange : (Random, Int32, Int32) -> Int32
133
+ ```
134
+
135
+ Generates a random 32-bit integer from the given pseudo-random number generator
136
+ from a uniform distribution in the given range.
137
+
138
+ Parameters:
139
+
140
+ |param|type|description|
141
+ |-----|----|-----------|
142
+ |`random`|`Random`|The pseudo-random number generator to use|
143
+ |`low`|`Int32`|The lower bound of the range (inclusive)|
144
+ |`high`|`Int32`|The upper bound of the range (exclusive)|
145
+
146
+ Returns:
147
+
148
+ |type|description|
149
+ |----|-----------|
150
+ |`Int32`|The randomly generated number|
151
+
152
+ ### Random.**nextInt64InRange**
153
+
154
+ <details disabled>
155
+ <summary tabindex="-1">Added in <code>next</code></summary>
156
+ No other changes yet.
157
+ </details>
158
+
159
+ ```grain
160
+ nextInt64InRange : (Random, Int64, Int64) -> Int64
161
+ ```
162
+
163
+ Generates a random 64-bit integer from the given pseudo-random number generator
164
+ from a uniform distribution in the given range.
165
+
166
+ Parameters:
167
+
168
+ |param|type|description|
169
+ |-----|----|-----------|
170
+ |`random`|`Random`|The pseudo-random number generator to use|
171
+ |`low`|`Int64`|The lower bound of the range (inclusive)|
172
+ |`high`|`Int64`|The upper bound of the range (exclusive)|
173
+
174
+ Returns:
175
+
176
+ |type|description|
177
+ |----|-----------|
178
+ |`Int64`|The randomly generated number|
179
+
package/range.gr CHANGED
@@ -38,7 +38,7 @@ export let inRange = (value, range) => {
38
38
  Inclusive(upper, lower) when value >= lower && value <= upper => true,
39
39
  Exclusive(lower, upper) when value >= lower && value < upper => true,
40
40
  Exclusive(upper, lower) when value >= lower && value < upper => true,
41
- _ => false
41
+ _ => false,
42
42
  }
43
43
  }
44
44
 
@@ -52,34 +52,34 @@ export let inRange = (value, range) => {
52
52
  *
53
53
  * @since v0.3.0
54
54
  */
55
- export let forEach = (fn: (Number) -> Void, range) => {
55
+ export let forEach = (fn: Number -> Void, range) => {
56
56
  match (range) {
57
57
  Inclusive(lower, upper) when lower <= upper => {
58
- let mut idx = lower;
58
+ let mut idx = lower
59
59
  while (idx <= upper) {
60
- fn(idx);
61
- idx += 1;
60
+ fn(idx)
61
+ idx += 1
62
62
  }
63
63
  },
64
64
  Inclusive(upper, lower) => {
65
- let mut idx = upper;
65
+ let mut idx = upper
66
66
  while (idx >= lower) {
67
- fn(idx);
68
- idx -= 1;
67
+ fn(idx)
68
+ idx -= 1
69
69
  }
70
70
  },
71
71
  Exclusive(lower, upper) when lower <= upper => {
72
- let mut idx = lower;
72
+ let mut idx = lower
73
73
  while (idx < upper) {
74
- fn(idx);
75
- idx += 1;
74
+ fn(idx)
75
+ idx += 1
76
76
  }
77
77
  },
78
78
  Exclusive(upper, lower) => {
79
- let mut idx = upper;
79
+ let mut idx = upper
80
80
  while (idx > lower) {
81
- fn(idx);
82
- idx -= 1;
81
+ fn(idx)
82
+ idx -= 1
83
83
  }
84
84
  },
85
85
  }
@@ -100,31 +100,31 @@ export let map = (fn, range) => {
100
100
  let mut result = []
101
101
  match (range) {
102
102
  Inclusive(lower, upper) when lower <= upper => {
103
- let mut idx = upper;
103
+ let mut idx = upper
104
104
  while (idx >= lower) {
105
- result = [fn(idx), ...result];
106
- idx -= 1;
105
+ result = [fn(idx), ...result]
106
+ idx -= 1
107
107
  }
108
108
  },
109
109
  Inclusive(upper, lower) => {
110
- let mut idx = lower;
110
+ let mut idx = lower
111
111
  while (idx <= upper) {
112
- result = [fn(idx), ...result];
113
- idx += 1;
112
+ result = [fn(idx), ...result]
113
+ idx += 1
114
114
  }
115
115
  },
116
116
  Exclusive(lower, upper) when lower <= upper => {
117
- let mut idx = upper - 1;
117
+ let mut idx = upper - 1
118
118
  while (idx >= lower) {
119
- result = [fn(idx), ...result];
120
- idx -= 1;
119
+ result = [fn(idx), ...result]
120
+ idx -= 1
121
121
  }
122
122
  },
123
123
  Exclusive(upper, lower) => {
124
- let mut idx = lower + 1;
124
+ let mut idx = lower + 1
125
125
  while (idx <= upper) {
126
- result = [fn(idx), ...result];
127
- idx += 1;
126
+ result = [fn(idx), ...result]
127
+ idx += 1
128
128
  }
129
129
  },
130
130
  }