@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/int64.gr CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @module Int64: Utilities for working with the Int64 type.
3
3
  * @example import Int64 from "int64"
4
- *
4
+ *
5
5
  * @since v0.2.0
6
6
  */
7
7
  import WasmI32 from "runtime/unsafe/wasmi32"
@@ -24,7 +24,7 @@ import {
24
24
  *
25
25
  * @param number: The value to convert
26
26
  * @returns The Number represented as an Int64
27
- *
27
+ *
28
28
  * @since v0.2.0
29
29
  */
30
30
  export fromNumber
@@ -34,7 +34,7 @@ export fromNumber
34
34
  *
35
35
  * @param value: The value to convert
36
36
  * @returns The Int64 represented as a Number
37
- *
37
+ *
38
38
  * @since v0.2.0
39
39
  */
40
40
  export toNumber
@@ -48,7 +48,7 @@ export toNumber
48
48
  *
49
49
  * @param value: The value to increment
50
50
  * @returns The incremented value
51
- *
51
+ *
52
52
  * @since v0.2.0
53
53
  */
54
54
  @unsafe
@@ -63,7 +63,7 @@ export let incr = (value: Int64) => {
63
63
  *
64
64
  * @param value: The value to decrement
65
65
  * @returns The decremented value
66
- *
66
+ *
67
67
  * @since v0.2.0
68
68
  */
69
69
  @unsafe
@@ -79,7 +79,7 @@ export let decr = (value: Int64) => {
79
79
  * @param x: The first operand
80
80
  * @param y: The second operand
81
81
  * @returns The sum of the two operands
82
- *
82
+ *
83
83
  * @since v0.2.0
84
84
  */
85
85
  @unsafe
@@ -96,7 +96,7 @@ export let add = (x: Int64, y: Int64) => {
96
96
  * @param x: The first operand
97
97
  * @param y: The second operand
98
98
  * @returns The difference of the two operands
99
- *
99
+ *
100
100
  * @since v0.2.0
101
101
  */
102
102
  @unsafe
@@ -113,7 +113,7 @@ export let sub = (x: Int64, y: Int64) => {
113
113
  * @param x: The first operand
114
114
  * @param y: The second operand
115
115
  * @returns The product of the two operands
116
- *
116
+ *
117
117
  * @since v0.2.0
118
118
  */
119
119
  @unsafe
@@ -130,7 +130,7 @@ export let mul = (x: Int64, y: Int64) => {
130
130
  * @param x: The first operand
131
131
  * @param y: The second operand
132
132
  * @returns The quotient of its operands
133
- *
133
+ *
134
134
  * @since v0.2.0
135
135
  */
136
136
  @unsafe
@@ -147,7 +147,7 @@ export let div = (x: Int64, y: Int64) => {
147
147
  * @param x: The first operand
148
148
  * @param y: The second operand
149
149
  * @returns The quotient of its operands
150
- *
150
+ *
151
151
  * @since v0.2.0
152
152
  */
153
153
  @unsafe
@@ -164,7 +164,7 @@ export let divU = (x: Int64, y: Int64) => {
164
164
  * @param x: The first operand
165
165
  * @param y: The second operand
166
166
  * @returns The remainder of its operands
167
- *
167
+ *
168
168
  * @since v0.2.0
169
169
  */
170
170
  @unsafe
@@ -181,7 +181,7 @@ export let rem = (x: Int64, y: Int64) => {
181
181
  * @param x: The first operand
182
182
  * @param y: The second operand
183
183
  * @returns The remainder of its operands
184
- *
184
+ *
185
185
  * @since v0.2.0
186
186
  */
187
187
  @unsafe
@@ -199,13 +199,15 @@ let abs = n => {
199
199
  }
200
200
 
201
201
  /**
202
- * Computes the remainder of the division of the first operand by the second.
202
+ * Computes the remainder of the division of the first operand by the second.
203
203
  * The result will have the sign of the second operand.
204
204
  *
205
205
  * @param x: The first operand
206
206
  * @param y: The second operand
207
207
  * @returns The modulus of its operands
208
- *
208
+ *
209
+ * @throws ModuloByZero: When `y` is zero
210
+ *
209
211
  * @since v0.2.0
210
212
  */
211
213
  @unsafe
@@ -243,7 +245,7 @@ export let mod = (x: Int64, y: Int64) => {
243
245
  * @param value: The value to rotate
244
246
  * @param amount: The number of bits to rotate by
245
247
  * @returns The rotated value
246
- *
248
+ *
247
249
  * @since v0.4.0
248
250
  */
249
251
  @unsafe
@@ -260,7 +262,7 @@ export let rotl = (value: Int64, amount: Int64) => {
260
262
  * @param value: The value to rotate
261
263
  * @param amount: The number of bits to rotate by
262
264
  * @returns The rotated value
263
- *
265
+ *
264
266
  * @since v0.4.0
265
267
  */
266
268
  @unsafe
@@ -277,7 +279,7 @@ export let rotr = (value: Int64, amount: Int64) => {
277
279
  * @param value: The value to shift
278
280
  * @param amount: The number of bits to shift by
279
281
  * @returns The shifted value
280
- *
282
+ *
281
283
  * @since v0.2.0
282
284
  */
283
285
  @unsafe
@@ -294,7 +296,7 @@ export let shl = (value: Int64, amount: Int64) => {
294
296
  * @param value: The value to shift
295
297
  * @param amount: The amount to shift by
296
298
  * @returns The shifted value
297
- *
299
+ *
298
300
  * @since v0.2.0
299
301
  */
300
302
  @unsafe
@@ -311,7 +313,7 @@ export let shr = (value: Int64, amount: Int64) => {
311
313
  * @param value: The value to shift
312
314
  * @param amount: The amount to shift by
313
315
  * @returns The shifted value
314
- *
316
+ *
315
317
  * @since v0.2.0
316
318
  */
317
319
  @unsafe
@@ -332,7 +334,7 @@ export let shrU = (value: Int64, amount: Int64) => {
332
334
  * @param x: The first value
333
335
  * @param y: The second value
334
336
  * @returns `true` if the first value is equal to the second value or `false` otherwise
335
- *
337
+ *
336
338
  * @since v0.4.0
337
339
  */
338
340
  @unsafe
@@ -348,7 +350,7 @@ export let eq = (x: Int64, y: Int64) => {
348
350
  * @param x: The first value
349
351
  * @param y: The second value
350
352
  * @returns `true` if the first value is not equal to the second value or `false` otherwise
351
- *
353
+ *
352
354
  * @since v0.4.0
353
355
  */
354
356
  @unsafe
@@ -363,7 +365,7 @@ export let ne = (x: Int64, y: Int64) => {
363
365
  *
364
366
  * @param value: The value to inspect
365
367
  * @returns `true` if the first value is equal to zero or `false` otherwise
366
- *
368
+ *
367
369
  * @since v0.4.0
368
370
  */
369
371
  @unsafe
@@ -378,7 +380,7 @@ export let eqz = (value: Int64) => {
378
380
  * @param x: The first value
379
381
  * @param y: The second value
380
382
  * @returns `true` if the first value is less than the second value or `false` otherwise
381
- *
383
+ *
382
384
  * @since v0.2.0
383
385
  */
384
386
  @unsafe
@@ -398,7 +400,7 @@ export let lt = (x: Int64, y: Int64) => {
398
400
  * @since v0.5.0
399
401
  */
400
402
  @unsafe
401
- export let rec ltU = (x: Int64, y: Int64) => {
403
+ export let ltU = (x: Int64, y: Int64) => {
402
404
  let xv = WasmI64.load(WasmI32.fromGrain(x), 8n)
403
405
  let yv = WasmI64.load(WasmI32.fromGrain(y), 8n)
404
406
  WasmI64.ltU(xv, yv)
@@ -410,7 +412,7 @@ export let rec ltU = (x: Int64, y: Int64) => {
410
412
  * @param x: The first value
411
413
  * @param y: The second value
412
414
  * @returns `true` if the first value is greater than the second value or `false` otherwise
413
- *
415
+ *
414
416
  * @since v0.2.0
415
417
  */
416
418
  @unsafe
@@ -430,7 +432,7 @@ export let gt = (x: Int64, y: Int64) => {
430
432
  * @since v0.5.0
431
433
  */
432
434
  @unsafe
433
- export let rec gtU = (x: Int64, y: Int64) => {
435
+ export let gtU = (x: Int64, y: Int64) => {
434
436
  let xv = WasmI64.load(WasmI32.fromGrain(x), 8n)
435
437
  let yv = WasmI64.load(WasmI32.fromGrain(y), 8n)
436
438
  WasmI64.gtU(xv, yv)
@@ -442,7 +444,7 @@ export let rec gtU = (x: Int64, y: Int64) => {
442
444
  * @param x: The first value
443
445
  * @param y: The second value
444
446
  * @returns `true` if the first value is less than or equal to the second value or `false` otherwise
445
- *
447
+ *
446
448
  * @since v0.2.0
447
449
  */
448
450
  @unsafe
@@ -462,7 +464,7 @@ export let lte = (x: Int64, y: Int64) => {
462
464
  * @since v0.5.0
463
465
  */
464
466
  @unsafe
465
- export let rec lteU = (x: Int64, y: Int64) => {
467
+ export let lteU = (x: Int64, y: Int64) => {
466
468
  let xv = WasmI64.load(WasmI32.fromGrain(x), 8n)
467
469
  let yv = WasmI64.load(WasmI32.fromGrain(y), 8n)
468
470
  WasmI64.leU(xv, yv)
@@ -474,7 +476,7 @@ export let rec lteU = (x: Int64, y: Int64) => {
474
476
  * @param x: The first value
475
477
  * @param y: The second value
476
478
  * @returns `true` if the first value is greater than or equal to the second value or `false` otherwise
477
- *
479
+ *
478
480
  * @since v0.2.0
479
481
  */
480
482
  @unsafe
@@ -494,7 +496,7 @@ export let gte = (x: Int64, y: Int64) => {
494
496
  * @since v0.5.0
495
497
  */
496
498
  @unsafe
497
- export let rec gteU = (x: Int64, y: Int64) => {
499
+ export let gteU = (x: Int64, y: Int64) => {
498
500
  let xv = WasmI64.load(WasmI32.fromGrain(x), 8n)
499
501
  let yv = WasmI64.load(WasmI32.fromGrain(y), 8n)
500
502
  WasmI64.geU(xv, yv)
@@ -509,7 +511,7 @@ export let rec gteU = (x: Int64, y: Int64) => {
509
511
  *
510
512
  * @param value: The given value
511
513
  * @returns Containing the inverted bits of the given value
512
- *
514
+ *
513
515
  * @since v0.2.0
514
516
  */
515
517
  @unsafe
@@ -525,7 +527,7 @@ export let lnot = (value: Int64) => {
525
527
  * @param x: The first operand
526
528
  * @param y: The second operand
527
529
  * @returns Containing a `1` in each bit position for which the corresponding bits of both operands are `1`
528
- *
530
+ *
529
531
  * @since v0.2.0
530
532
  */
531
533
  @unsafe
@@ -542,7 +544,7 @@ export let land = (x: Int64, y: Int64) => {
542
544
  * @param x: The first operand
543
545
  * @param y: The second operand
544
546
  * @returns Containing a `1` in each bit position for which the corresponding bits of either or both operands are `1`
545
- *
547
+ *
546
548
  * @since v0.2.0
547
549
  */
548
550
  @unsafe
@@ -559,7 +561,7 @@ export let lor = (x: Int64, y: Int64) => {
559
561
  * @param x: The first operand
560
562
  * @param y: The second operand
561
563
  * @returns Containing a `1` in each bit position for which the corresponding bits of either but not both operands are `1`
562
- *
564
+ *
563
565
  * @since v0.2.0
564
566
  */
565
567
  @unsafe
@@ -575,7 +577,7 @@ export let lxor = (x: Int64, y: Int64) => {
575
577
  *
576
578
  * @param value: The value to inspect
577
579
  * @returns The amount of leading zeros
578
- *
580
+ *
579
581
  * @since v0.4.0
580
582
  */
581
583
  @unsafe
@@ -590,7 +592,7 @@ export let clz = (value: Int64) => {
590
592
  *
591
593
  * @param value: The value to inspect
592
594
  * @returns The amount of trailing zeros
593
- *
595
+ *
594
596
  * @since v0.4.0
595
597
  */
596
598
  @unsafe
@@ -605,7 +607,7 @@ export let ctz = (value: Int64) => {
605
607
  *
606
608
  * @param value: The value to inspect
607
609
  * @returns The amount of 1-bits in its operand
608
- *
610
+ *
609
611
  * @since v0.4.0
610
612
  */
611
613
  @unsafe
package/int64.md CHANGED
@@ -330,6 +330,12 @@ Returns:
330
330
  |----|-----------|
331
331
  |`Int64`|The modulus of its operands|
332
332
 
333
+ Throws:
334
+
335
+ `ModuloByZero`
336
+
337
+ * When `y` is zero
338
+
333
339
  ## Bitwise operations
334
340
 
335
341
  Functions for operating on bits of Int64 values.
package/list.gr CHANGED
@@ -230,10 +230,12 @@ export let rec flatMap = (fn, list) => {
230
230
  *
231
231
  * @since v0.1.0
232
232
  */
233
- export let every = (fn, list) => {
234
- reduce((acc, value) => {
235
- acc && fn(value)
236
- }, true, list)
233
+ export let rec every = (fn, list) => {
234
+ match (list) {
235
+ [] => true,
236
+ // The short-circuiting of `&&` makes this tail-recursive
237
+ [first, ...rest] => fn(first) && every(fn, rest),
238
+ }
237
239
  }
238
240
 
239
241
  /**
@@ -246,10 +248,12 @@ export let every = (fn, list) => {
246
248
  *
247
249
  * @since v0.1.0
248
250
  */
249
- export let some = (fn, list) => {
250
- reduce((acc, value) => {
251
- acc || fn(value)
252
- }, false, list)
251
+ export let rec some = (fn, list) => {
252
+ match (list) {
253
+ [] => false,
254
+ // The short-circuiting of `||` makes this tail-recursive
255
+ [first, ...rest] => fn(first) || some(fn, rest),
256
+ }
253
257
  }
254
258
 
255
259
  /**
@@ -433,13 +437,15 @@ export let rec flatten = list => {
433
437
 
434
438
  /**
435
439
  * Inserts a new value into a list at the specified index.
436
- * Fails if the index is out-of-bounds.
437
440
  *
438
441
  * @param value: The value to insert
439
442
  * @param index: The index to update
440
443
  * @param list: The list to update
441
444
  * @returns The new list
442
445
  *
446
+ * @throws Failure(String): When `index` is negative
447
+ * @throws Failure(String): When `index` is more than 0 and greater than the list size
448
+ *
443
449
  * @since v0.1.0
444
450
  */
445
451
  export let rec insert = (value, index, list) => {
@@ -477,12 +483,14 @@ export let count = (fn, list) => {
477
483
 
478
484
  /**
479
485
  * Split a list into two, with the first list containing the required number of elements.
480
- * Fails if the input list doesn't contain at least the required amount of elements.
481
486
  *
482
487
  * @param count: The number of elements required
483
488
  * @param list: The list to split
484
489
  * @returns Two lists where the first contains exactly the required amount of elements and the second contains any remaining elements
485
490
  *
491
+ * @throws Failure(String): When `count` is negative
492
+ * @throws Failure(String): When the list doesn't contain at least the required amount of elements
493
+ *
486
494
  * @since v0.1.0
487
495
  */
488
496
  export let part = (count, list) => {
@@ -509,14 +517,14 @@ export let part = (count, list) => {
509
517
  * If value is negative, list elements will be rotated by the
510
518
  * specified amount to the right. See examples.
511
519
  *
512
- * Fails if the input list doesn't contain at least the required amount of elements.
513
- *
514
520
  * @param count: The number of elements to rotate by
515
521
  * @param list: The list to be rotated
516
522
  *
517
523
  * @example List.rotate(2, [1, 2, 3, 4, 5]) // [3, 4, 5, 1, 2]
518
524
  * @example List.rotate(-1, [1, 2, 3, 4, 5]) // [5, 1, 2, 3, 4]
519
525
  *
526
+ * @throws Failure(String): When the list doesn't contain at least the required amount of elements
527
+ *
520
528
  * @since v0.1.0
521
529
  */
522
530
  export let rotate = (count, list) => {
@@ -552,7 +560,7 @@ export let unique = list => {
552
560
  * Produces a new list filled with tuples of elements from both given lists.
553
561
  * The first tuple will contain the first item of each list, the second tuple
554
562
  * will contain the second item of each list, and so on.
555
- *
563
+ *
556
564
  * Calling this function with lists of different sizes will cause the returned
557
565
  * list to have the length of the smaller list.
558
566
  *
@@ -562,7 +570,7 @@ export let unique = list => {
562
570
  *
563
571
  * @example List.zip([1, 2, 3], [4, 5, 6]) // [(1, 4), (2, 5), (3, 6)]
564
572
  * @example List.zip([1, 2, 3], [4, 5]) // [(1, 4), (2, 5)]
565
- *
573
+ *
566
574
  * @since v0.5.3
567
575
  */
568
576
  export let zip = (list1, list2) => {
@@ -582,7 +590,7 @@ export let zip = (list1, list2) => {
582
590
  * applying the function to the first elements of each list, the second element
583
591
  * will contain the result of applying the function to the second elements of
584
592
  * each list, and so on.
585
- *
593
+ *
586
594
  * Calling this function with lists of different sizes will cause the returned
587
595
  * list to have the length of the smaller list.
588
596
  *
@@ -593,7 +601,7 @@ export let zip = (list1, list2) => {
593
601
  *
594
602
  * @example List.zipWith((a, b) => a + b, [1, 2, 3], [4, 5, 6]) // [5, 7, 9]
595
603
  * @example List.zipWith((a, b) => a * b, [1, 2, 3], [4, 5]) // [4, 10]
596
- *
604
+ *
597
605
  * @since v0.5.3
598
606
  */
599
607
  export let zipWith = (fn, list1, list2) => {
@@ -625,12 +633,12 @@ export let unzip = list => {
625
633
  * Produces a new list with the specified number of elements removed from
626
634
  * the beginning of the input list.
627
635
  *
628
- * Fails if the specified amount is a negative number.
629
- *
630
636
  * @param count: The amount of elements to remove
631
637
  * @param list: The input list
632
638
  * @returns The new list without the dropped elements
633
639
  *
640
+ * @throws Failure(String): When `count` is negative
641
+ *
634
642
  * @since v0.2.0
635
643
  */
636
644
  export let rec drop = (count, list) => {
@@ -667,12 +675,12 @@ export let rec dropWhile = (fn, list) => {
667
675
  * Produces a new list with–at most—the specified amount elements from
668
676
  * the beginning of the input list.
669
677
  *
670
- * Fails if the specified amount is a negative number.
671
- *
672
678
  * @param count: The amount of elements to keep
673
679
  * @param list: The input list
674
680
  * @returns The new list containing the taken elements
675
681
  *
682
+ * @throws Failure(String): When `count` is negative
683
+ *
676
684
  * @since v0.2.0
677
685
  */
678
686
  export let rec take = (count, list) => {
@@ -769,13 +777,14 @@ export let product = (list1, list2) => {
769
777
  * Provides the subset of a list given zero-based start index and amount of elements
770
778
  * to include.
771
779
  *
772
- * Fails if the start index or amount of elements are negative numbers.
773
- *
774
780
  * @param start: The index of the list where the subset will begin (inclusive)
775
781
  * @param length: The amount of elements to be included in the subset
776
782
  * @param list: The input list
777
783
  * @returns The subset of the list
778
784
  *
785
+ * @throws Failure(String): When `start` is negative
786
+ * @throws Failure(String): When `length` is negative
787
+ *
779
788
  * @since v0.2.0
780
789
  */
781
790
  export let sub = (start, length, list) => {
package/list.md CHANGED
@@ -674,7 +674,6 @@ insert : (a, Number, List<a>) -> List<a>
674
674
  ```
675
675
 
676
676
  Inserts a new value into a list at the specified index.
677
- Fails if the index is out-of-bounds.
678
677
 
679
678
  Parameters:
680
679
 
@@ -690,6 +689,13 @@ Returns:
690
689
  |----|-----------|
691
690
  |`List<a>`|The new list|
692
691
 
692
+ Throws:
693
+
694
+ `Failure(String)`
695
+
696
+ * When `index` is negative
697
+ * When `index` is more than 0 and greater than the list size
698
+
693
699
  ### List.**count**
694
700
 
695
701
  <details>
@@ -735,7 +741,6 @@ part : (Number, List<a>) -> (List<a>, List<a>)
735
741
  ```
736
742
 
737
743
  Split a list into two, with the first list containing the required number of elements.
738
- Fails if the input list doesn't contain at least the required amount of elements.
739
744
 
740
745
  Parameters:
741
746
 
@@ -750,6 +755,13 @@ Returns:
750
755
  |----|-----------|
751
756
  |`(List<a>, List<a>)`|Two lists where the first contains exactly the required amount of elements and the second contains any remaining elements|
752
757
 
758
+ Throws:
759
+
760
+ `Failure(String)`
761
+
762
+ * When `count` is negative
763
+ * When the list doesn't contain at least the required amount of elements
764
+
753
765
  ### List.**rotate**
754
766
 
755
767
  <details disabled>
@@ -766,8 +778,6 @@ Rotates list elements by the specified amount to the left.
766
778
  If value is negative, list elements will be rotated by the
767
779
  specified amount to the right. See examples.
768
780
 
769
- Fails if the input list doesn't contain at least the required amount of elements.
770
-
771
781
  Parameters:
772
782
 
773
783
  |param|type|description|
@@ -775,6 +785,12 @@ Parameters:
775
785
  |`count`|`Number`|The number of elements to rotate by|
776
786
  |`list`|`List<a>`|The list to be rotated|
777
787
 
788
+ Throws:
789
+
790
+ `Failure(String)`
791
+
792
+ * When the list doesn't contain at least the required amount of elements
793
+
778
794
  Examples:
779
795
 
780
796
  ```grain
@@ -943,8 +959,6 @@ drop : (Number, List<a>) -> List<a>
943
959
  Produces a new list with the specified number of elements removed from
944
960
  the beginning of the input list.
945
961
 
946
- Fails if the specified amount is a negative number.
947
-
948
962
  Parameters:
949
963
 
950
964
  |param|type|description|
@@ -958,6 +972,12 @@ Returns:
958
972
  |----|-----------|
959
973
  |`List<a>`|The new list without the dropped elements|
960
974
 
975
+ Throws:
976
+
977
+ `Failure(String)`
978
+
979
+ * When `count` is negative
980
+
961
981
  ### List.**dropWhile**
962
982
 
963
983
  <details disabled>
@@ -1000,8 +1020,6 @@ take : (Number, List<a>) -> List<a>
1000
1020
  Produces a new list with–at most—the specified amount elements from
1001
1021
  the beginning of the input list.
1002
1022
 
1003
- Fails if the specified amount is a negative number.
1004
-
1005
1023
  Parameters:
1006
1024
 
1007
1025
  |param|type|description|
@@ -1015,6 +1033,12 @@ Returns:
1015
1033
  |----|-----------|
1016
1034
  |`List<a>`|The new list containing the taken elements|
1017
1035
 
1036
+ Throws:
1037
+
1038
+ `Failure(String)`
1039
+
1040
+ * When `count` is negative
1041
+
1018
1042
  ### List.**takeWhile**
1019
1043
 
1020
1044
  <details disabled>
@@ -1152,8 +1176,6 @@ sub : (Number, Number, List<a>) -> List<a>
1152
1176
  Provides the subset of a list given zero-based start index and amount of elements
1153
1177
  to include.
1154
1178
 
1155
- Fails if the start index or amount of elements are negative numbers.
1156
-
1157
1179
  Parameters:
1158
1180
 
1159
1181
  |param|type|description|
@@ -1168,6 +1190,13 @@ Returns:
1168
1190
  |----|-----------|
1169
1191
  |`List<a>`|The subset of the list|
1170
1192
 
1193
+ Throws:
1194
+
1195
+ `Failure(String)`
1196
+
1197
+ * When `start` is negative
1198
+ * When `length` is negative
1199
+
1171
1200
  ### List.**join**
1172
1201
 
1173
1202
  <details disabled>
package/map.gr CHANGED
@@ -9,7 +9,7 @@ import Array from "array"
9
9
  import { hash } from "hash"
10
10
  import Memory from "runtime/unsafe/memory"
11
11
  import WasmI32 from "runtime/unsafe/wasmi32"
12
- import { allocateArray } from "runtime/dataStructures"
12
+ import { allocateArray, untagSimpleNumber } from "runtime/dataStructures"
13
13
 
14
14
  // TODO: Consider implementing this as List<(Box<k>, Box<v>)>
15
15
  record Bucket<k, v> {
@@ -418,19 +418,6 @@ export let fromList = list => {
418
418
  map
419
419
  }
420
420
 
421
- let setInArray = array => {
422
- @disableGC
423
- let rec iter = (i, key, value) => {
424
- array[i] = (key, value)
425
- // no decRef on key and value, since they are stored in array
426
- Memory.decRef(WasmI32.fromGrain(iter))
427
- Memory.incRef(WasmI32.fromGrain((+)))
428
- Memory.incRef(WasmI32.fromGrain(i))
429
- i + 1
430
- }
431
- iter
432
- }
433
-
434
421
  /**
435
422
  * Converts a map into an array of its key-value pairs.
436
423
  *
@@ -439,20 +426,24 @@ let setInArray = array => {
439
426
  *
440
427
  * @since v0.2.0
441
428
  */
442
- @disableGC
443
- export let rec toArray = map => {
444
- let length = WasmI32.shrS(WasmI32.fromGrain(map.size), 1n)
445
- let array = WasmI32.toGrain(allocateArray(length)): Array<a>
446
- Memory.incRef(WasmI32.fromGrain(setInArray))
447
- Memory.incRef(WasmI32.fromGrain(array))
448
- let setInArray = setInArray(array)
449
- Memory.incRef(WasmI32.fromGrain(reduce))
450
- Memory.incRef(WasmI32.fromGrain(setInArray))
451
- Memory.incRef(WasmI32.fromGrain(map))
452
- reduce(setInArray, 0, map)
453
- Memory.decRef(WasmI32.fromGrain(setInArray))
454
- Memory.decRef(WasmI32.fromGrain(map))
455
- Memory.decRef(WasmI32.fromGrain(toArray))
429
+ @unsafe
430
+ export let toArray: Map<a, b> -> Array<(a, b)> = map => {
431
+ let length = untagSimpleNumber(map.size)
432
+ let array = WasmI32.toGrain(allocateArray(length))
433
+ @unsafe
434
+ let reducer = (i, key, value) => {
435
+ // Assign the values into the array.
436
+ // We store them directly to prevent GC on uninitialized array data.
437
+ let array = WasmI32.fromGrain(array)
438
+ let item = (key, value)
439
+ WasmI32.store(
440
+ WasmI32.add(array, WasmI32.mul(untagSimpleNumber(i), 4n)),
441
+ Memory.incRef(WasmI32.fromGrain(item)),
442
+ 8n
443
+ )
444
+ i + 1
445
+ }
446
+ reduce(reducer, 0, map)
456
447
  array
457
448
  }
458
449