@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/runtime/gc.gr CHANGED
@@ -25,23 +25,38 @@ import WasmI32, {
25
25
  sub as (-),
26
26
  mul as (*),
27
27
  and as (&),
28
- eq as (==)
28
+ eq as (==),
29
29
  } from "runtime/unsafe/wasmi32"
30
30
 
31
31
  // Using foreigns directly here to avoid cyclic dependency
32
- import foreign wasm fd_write : (WasmI32, WasmI32, WasmI32, WasmI32) -> WasmI32 from "wasi_snapshot_preview1"
32
+ import foreign wasm fd_write: (
33
+ WasmI32,
34
+ WasmI32,
35
+ WasmI32,
36
+ WasmI32,
37
+ ) -> WasmI32 from "wasi_snapshot_preview1"
33
38
 
34
- primitive (&&) : (Bool, Bool) -> Bool = "@and"
35
- primitive (||) : (Bool, Bool) -> Bool = "@or"
36
- primitive throw : Exception -> a = "@throw"
37
- primitive ignore : a -> Void = "@ignore"
38
- primitive box : a -> Box<a> = "@box"
39
- primitive unbox : Box<a> -> a = "@unbox"
39
+ primitive (&&): (Bool, Bool) -> Bool = "@and"
40
+ primitive (||): (Bool, Bool) -> Bool = "@or"
41
+ primitive throw: Exception -> a = "@throw"
42
+ primitive ignore: a -> Void = "@ignore"
43
+ primitive box: a -> Box<a> = "@box"
44
+ primitive unbox: Box<a> -> a = "@unbox"
40
45
 
41
46
  exception DecRefError
42
47
 
43
- export let decimalCount32 = box((n: WasmI32) => 0n)
44
- export let utoa32Buffered = box((a: WasmI32, b: WasmI32, c: WasmI32) => void)
48
+ let decimalCount32Dummy = (n: WasmI32) => 0n
49
+ let utoa32BufferedDummy = (a: WasmI32, b: WasmI32, c: WasmI32) => void
50
+
51
+ // When these boxes are backpatched, the reference count of each function will
52
+ // fall to zero which would cause them to be freed. We can't free anything that
53
+ // got allocated in runtime mode (since that memory space is not managed by the
54
+ // GC, so here we prevent that by manually setting a higher refcount.
55
+ WasmI32.store(WasmI32.fromGrain(decimalCount32Dummy) - 8n, 2n, 0n)
56
+ WasmI32.store(WasmI32.fromGrain(utoa32BufferedDummy) - 8n, 2n, 0n)
57
+
58
+ export let decimalCount32 = box(decimalCount32Dummy)
59
+ export let utoa32Buffered = box(utoa32BufferedDummy)
45
60
 
46
61
  let mut _DEBUG = false
47
62
 
@@ -154,7 +169,10 @@ export let free = (userPtr: WasmI32) => {
154
169
  }
155
170
 
156
171
  export let incRef = (userPtr: WasmI32) => {
157
- if (WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) && WasmI32.ne(userPtr, 0n)) {
172
+ if (
173
+ WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) &&
174
+ WasmI32.ne(userPtr, 0n)
175
+ ) {
158
176
  // if (_DEBUG) {
159
177
  // logIncRef(userPtr, getRefCount(userPtr))
160
178
  // void;
@@ -165,7 +183,10 @@ export let incRef = (userPtr: WasmI32) => {
165
183
  }
166
184
 
167
185
  let rec decRef = (userPtr: WasmI32, ignoreZeros: Bool) => {
168
- if (WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) && WasmI32.ne(userPtr, 0n)) {
186
+ if (
187
+ WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) &&
188
+ WasmI32.ne(userPtr, 0n)
189
+ ) {
169
190
  let refCount = getRefCount(userPtr)
170
191
  // if (_DEBUG) {
171
192
  // logDecRef(userPtr, refCount, ignoreZeros)
@@ -194,43 +215,52 @@ let rec decRef = (userPtr: WasmI32, ignoreZeros: Bool) => {
194
215
  }
195
216
  }, decRefChildren = (userPtr: WasmI32) => {
196
217
  match (WasmI32.load(userPtr, 0n)) {
218
+ t when t == Tags._GRAIN_BOXED_NUM_HEAP_TAG => {
219
+ let tag = WasmI32.load(userPtr, 4n)
220
+ if (userPtr == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) {
221
+ // decRef underlying BigInts
222
+ ignore(decRef(WasmI32.load(userPtr, 8n), false))
223
+ ignore(decRef(WasmI32.load(userPtr, 12n), false))
224
+ }
225
+ },
197
226
  t when t == Tags._GRAIN_ADT_HEAP_TAG => {
198
227
  let arity = WasmI32.load(userPtr, 16n)
199
228
  let maxOffset = arity * 4n
200
- for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i = i + 4n) {
229
+ for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
201
230
  ignore(decRef(WasmI32.load(userPtr + i, 20n), false))
202
231
  }
203
232
  },
204
233
  t when t == Tags._GRAIN_RECORD_HEAP_TAG => {
205
234
  let arity = WasmI32.load(userPtr, 12n)
206
235
  let maxOffset = arity * 4n
207
- for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i = i + 4n) {
236
+ for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
208
237
  ignore(decRef(WasmI32.load(userPtr + i, 16n), false))
209
238
  }
210
239
  },
211
- t when t == Tags._GRAIN_ARRAY_HEAP_TAG || t == Tags._GRAIN_TUPLE_HEAP_TAG => {
240
+ t when (
241
+ t == Tags._GRAIN_ARRAY_HEAP_TAG || t == Tags._GRAIN_TUPLE_HEAP_TAG
242
+ ) => {
212
243
  let arity = WasmI32.load(userPtr, 4n)
213
244
  let maxOffset = arity * 4n
214
- for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i = i + 4n) {
245
+ for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
215
246
  ignore(decRef(WasmI32.load(userPtr + i, 8n), false))
216
247
  }
217
248
  },
218
249
  t when t == Tags._GRAIN_LAMBDA_HEAP_TAG => {
219
250
  let arity = WasmI32.load(userPtr, 12n)
220
251
  let maxOffset = arity * 4n
221
- for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i = i + 4n) {
252
+ for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
222
253
  ignore(decRef(WasmI32.load(userPtr + i, 16n), false))
223
254
  }
224
255
  },
225
256
  _ => {
226
257
  // No travelsal necessary for other tags
227
258
  void
228
- }
259
+ },
229
260
  }
230
261
  }
231
262
 
232
- export let decRefIgnoreZeros = (userPtr) => decRef(userPtr, true)
233
- export let decRef = (userPtr) => decRef(userPtr, false)
263
+ export let decRef = userPtr => decRef(userPtr, false)
234
264
 
235
265
  // For debugging:
236
266
 
package/runtime/gc.md ADDED
@@ -0,0 +1,36 @@
1
+ ### Gc.**decimalCount32**
2
+
3
+ ```grain
4
+ decimalCount32 : Box<WasmI32 -> WasmI32>
5
+ ```
6
+
7
+ ### Gc.**utoa32Buffered**
8
+
9
+ ```grain
10
+ utoa32Buffered : Box<(WasmI32, WasmI32, WasmI32) -> Void>
11
+ ```
12
+
13
+ ### Gc.**malloc**
14
+
15
+ ```grain
16
+ malloc : WasmI32 -> WasmI32
17
+ ```
18
+
19
+ ### Gc.**free**
20
+
21
+ ```grain
22
+ free : WasmI32 -> Void
23
+ ```
24
+
25
+ ### Gc.**incRef**
26
+
27
+ ```grain
28
+ incRef : WasmI32 -> WasmI32
29
+ ```
30
+
31
+ ### Gc.**decRef**
32
+
33
+ ```grain
34
+ decRef : WasmI32 -> WasmI32
35
+ ```
36
+
package/runtime/malloc.gr CHANGED
@@ -17,18 +17,20 @@ import WasmI32, {
17
17
  shl as (<<),
18
18
  shrU as (>>),
19
19
  eq as (==),
20
- ne as (!=)
20
+ ne as (!=),
21
21
  } from "runtime/unsafe/wasmi32"
22
22
  import Exception from "runtime/exception"
23
23
 
24
24
  primitive memorySize: () -> WasmI32 = "@wasm.memory_size"
25
- primitive memoryGrow: (WasmI32) -> WasmI32 = "@wasm.memory_grow"
25
+ primitive memoryGrow: WasmI32 -> WasmI32 = "@wasm.memory_grow"
26
26
 
27
- primitive (!) : Bool -> Bool = "@not"
28
- primitive (&&) : (Bool, Bool) -> Bool = "@and"
29
- primitive (||) : (Bool, Bool) -> Bool = "@or"
27
+ primitive (!): Bool -> Bool = "@not"
28
+ primitive (&&): (Bool, Bool) -> Bool = "@and"
29
+ primitive (||): (Bool, Bool) -> Bool = "@or"
30
30
 
31
- primitive throw : Exception -> a = "@throw"
31
+ primitive throw: Exception -> a = "@throw"
32
+
33
+ primitive heapBase: WasmI32 = "@heap.base"
32
34
 
33
35
  /* UNDERSTANDING THE STRUCTURE OF THE FREE LIST
34
36
  * The original K&R definition for the free list entry type was the following:
@@ -80,7 +82,7 @@ export let _RESERVED_RUNTIME_SPACE = 0x4000n
80
82
  * The base the heap. The block at this address will be size 0 and
81
83
  * serve as the root of the free list.
82
84
  */
83
- let _BASE = _RESERVED_RUNTIME_SPACE
85
+ let _BASE = heapBase + _RESERVED_RUNTIME_SPACE
84
86
 
85
87
  /**
86
88
  * The start pointer of the heap.
@@ -114,8 +116,8 @@ let setSize = (ptr: WasmI32, val: WasmI32) => {
114
116
  /**
115
117
  * Requests that the heap be grown by the given number of bytes.
116
118
  *
117
- * @param nbytes: WasmI32 - The number of bytes requested
118
- * @return WasmI32 - If unsuccessful, -1. Otherwise, the pointer to the beginning of the extended region.
119
+ * @param nbytes: The number of bytes requested
120
+ * @returns The pointer to the beginning of the extended region if successful or -1 otherwise
119
121
  */
120
122
  let growHeap = (nbytes: WasmI32) => {
121
123
  let mut reqSize = 0n
@@ -130,7 +132,7 @@ let growHeap = (nbytes: WasmI32) => {
130
132
  // so we need to request more anyway.
131
133
  reqSize = nbytes - heapSize
132
134
  reqSize = reqSize >> 16n
133
- reqSize = reqSize + 1n
135
+ reqSize += 1n
134
136
  reqResult = memoryGrow(reqSize)
135
137
  if (reqResult == -1n) {
136
138
  -1n
@@ -147,7 +149,7 @@ let growHeap = (nbytes: WasmI32) => {
147
149
 
148
150
  reqSize = nbytes
149
151
  reqSize = reqSize >> 16n
150
- reqSize = reqSize + 1n
152
+ reqSize += 1n
151
153
 
152
154
  reqResult = memoryGrow(reqSize)
153
155
  if (reqResult == -1n) {
@@ -162,7 +164,7 @@ let growHeap = (nbytes: WasmI32) => {
162
164
  /**
163
165
  * Frees the given allocated pointer.
164
166
  *
165
- * @param ap: WasmI32 - The pointer to free
167
+ * @param ap: The pointer to free
166
168
  */
167
169
  export let free = (ap: WasmI32) => {
168
170
  let mut blockPtr = ap - 8n // 8 bytes for malloc header
@@ -174,7 +176,10 @@ export let free = (ap: WasmI32) => {
174
176
  // Find the location to insert this block into the free list
175
177
  while (true) {
176
178
  let nextp = getNext(p)
177
- if ( ((blockPtr > p) && (blockPtr < nextp)) || ((p >= nextp) && ((blockPtr > p) || (blockPtr < nextp))) ) {
179
+ if (
180
+ blockPtr > p && blockPtr < nextp ||
181
+ p >= nextp && (blockPtr > p || blockPtr < nextp)
182
+ ) {
178
183
  break
179
184
  }
180
185
  p = nextp
@@ -207,8 +212,8 @@ export let free = (ap: WasmI32) => {
207
212
  * (if you can't tell from the fact that the name is reminiscient
208
213
  * of the 1970s, the name of this function is taken from K&R).
209
214
  *
210
- * @param nbytes: WasmI32 - The number of bytes to try to grow the heap by
211
- * @return WasmI32 - If successful, a pointer to the start of the free list. If not successful, -1.
215
+ * @param nbytes: The number of bytes to try to grow the heap by
216
+ * @returns A pointer to the start of the free list if successful or -1 otherwise
212
217
  */
213
218
  let morecore = (nbytes: WasmI32) => {
214
219
  let origSize = heapSize
@@ -232,8 +237,8 @@ let morecore = (nbytes: WasmI32) => {
232
237
  /**
233
238
  * Allocates the requested number of bytes, returning a pointer.
234
239
  *
235
- * @param nbytes: WasmI32 - The number of bytes to allocate
236
- * @return WasmI32 - The pointer to the allocated region (8-byte aligned), or -1 if the allocation failed.
240
+ * @param nbytes: The number of bytes to allocate
241
+ * @returns The pointer to the allocated region (8-byte aligned) or -1 if the allocation failed
237
242
  */
238
243
  export let malloc = (nb: WasmI32) => {
239
244
  let mut nbytes = nb
@@ -255,7 +260,12 @@ export let malloc = (nb: WasmI32) => {
255
260
  let mut ret = -1n
256
261
 
257
262
  // Search the freelist for any blocks large enough.
258
- for (let mut p = getNext(prevp); ; {prevp = p; p = getNext(p)}) {
263
+ for (
264
+ let mut p = getNext(prevp); ; {
265
+ prevp = p
266
+ p = getNext(p)
267
+ }
268
+ ) {
259
269
  let size = getSize(p)
260
270
  if (size >= nbytes) {
261
271
  // If this block is big enough, allocate from it.
@@ -266,7 +276,7 @@ export let malloc = (nb: WasmI32) => {
266
276
  // Shrink it as needed
267
277
  let newSize = size - nbytes
268
278
  setSize(p, newSize)
269
- p = p + newSize
279
+ p += newSize
270
280
  setSize(p, nbytes)
271
281
  }
272
282
  // Update the pointer to the free list.
@@ -292,10 +302,10 @@ export let malloc = (nb: WasmI32) => {
292
302
  }
293
303
 
294
304
  /**
295
- * Returns the current free list pointer
296
- * (used for debugging)
305
+ * Returns the current free list pointer.
306
+ * Used for debugging.
297
307
  *
298
- * @return WasmI32 - The free list pointer
308
+ * @returns The free list pointer
299
309
  */
300
310
  export let getFreePtr = () => {
301
311
  freePtr
@@ -0,0 +1,55 @@
1
+ ### Malloc.**_RESERVED_RUNTIME_SPACE**
2
+
3
+ ```grain
4
+ _RESERVED_RUNTIME_SPACE : WasmI32
5
+ ```
6
+
7
+ ### Malloc.**free**
8
+
9
+ ```grain
10
+ free : WasmI32 -> Void
11
+ ```
12
+
13
+ Frees the given allocated pointer.
14
+
15
+ Parameters:
16
+
17
+ |param|type|description|
18
+ |-----|----|-----------|
19
+ |`ap`|`WasmI32`|The pointer to free|
20
+
21
+ ### Malloc.**malloc**
22
+
23
+ ```grain
24
+ malloc : WasmI32 -> WasmI32
25
+ ```
26
+
27
+ Allocates the requested number of bytes, returning a pointer.
28
+
29
+ Parameters:
30
+
31
+ |param|type|description|
32
+ |-----|----|-----------|
33
+ |`nbytes`|`WasmI32`|The number of bytes to allocate|
34
+
35
+ Returns:
36
+
37
+ |type|description|
38
+ |----|-----------|
39
+ |`WasmI32`|The pointer to the allocated region (8-byte aligned) or -1 if the allocation failed|
40
+
41
+ ### Malloc.**getFreePtr**
42
+
43
+ ```grain
44
+ getFreePtr : () -> WasmI32
45
+ ```
46
+
47
+ Returns the current free list pointer.
48
+ Used for debugging.
49
+
50
+ Returns:
51
+
52
+ |type|description|
53
+ |----|-----------|
54
+ |`WasmI32`|The free list pointer|
55
+