@grain/stdlib 0.4.0 → 0.4.4

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.
package/result.md ADDED
@@ -0,0 +1,446 @@
1
+ ---
2
+ title: Result
3
+ ---
4
+
5
+ Utilities for working with the Result data type.
6
+
7
+ The Result type is an enum that represents the possibility of a success case (with the `Ok` variant),
8
+ or an error case (with the `Err` variant). Use a Result as the return type of a function that may return an error.
9
+
10
+ <details disabled>
11
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
12
+ No other changes yet.
13
+ </details>
14
+
15
+ ```grain
16
+ import Result from "result"
17
+ ```
18
+
19
+ ```grain
20
+ let success = Ok((x) => 1 + x) // Creates a successful Result containing (x) => 1 + x
21
+ ```
22
+
23
+ ```grain
24
+ let failure = Err("Something bad happened") // Creates an unsuccessful Result containing "Something bad happened"
25
+ ```
26
+
27
+ ## Values
28
+
29
+ Functions for working with the Result data type.
30
+
31
+ ### Result.**isOk**
32
+
33
+ <details disabled>
34
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
35
+ No other changes yet.
36
+ </details>
37
+
38
+ ```grain
39
+ isOk : Result<a, b> -> Bool
40
+ ```
41
+
42
+ Checks if the Result is the `Ok` variant.
43
+
44
+ Parameters:
45
+
46
+ |param|type|description|
47
+ |-----|----|-----------|
48
+ |`result`|`Result<a, b>`|The result to check|
49
+
50
+ Returns:
51
+
52
+ |type|description|
53
+ |----|-----------|
54
+ |`Bool`|`true` if the Result is the `Ok` variant or `false` otherwise|
55
+
56
+ ### Result.**isErr**
57
+
58
+ <details disabled>
59
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
60
+ No other changes yet.
61
+ </details>
62
+
63
+ ```grain
64
+ isErr : Result<a, b> -> Bool
65
+ ```
66
+
67
+ Checks if the Result is the `Err` variant.
68
+
69
+ Parameters:
70
+
71
+ |param|type|description|
72
+ |-----|----|-----------|
73
+ |`result`|`Result<a, b>`|The result to check|
74
+
75
+ Returns:
76
+
77
+ |type|description|
78
+ |----|-----------|
79
+ |`Bool`|`true` if the Result is the `Err` variant or `false` otherwise|
80
+
81
+ ### Result.**toOption**
82
+
83
+ <details disabled>
84
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
85
+ No other changes yet.
86
+ </details>
87
+
88
+ ```grain
89
+ toOption : Result<a, b> -> Option<a>
90
+ ```
91
+
92
+ Converts the Result to an Option. An error value is discarded and replaced with `None`.
93
+
94
+ Parameters:
95
+
96
+ |param|type|description|
97
+ |-----|----|-----------|
98
+ |`result`|`Result<a, b>`|The result to convert|
99
+
100
+ Returns:
101
+
102
+ |type|description|
103
+ |----|-----------|
104
+ |`Option<a>`|`Some(value)` if the Result is `Ok(value)` or `None` if the Result is an `Err`|
105
+
106
+ ### Result.**flatMap**
107
+
108
+ <details disabled>
109
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
110
+ No other changes yet.
111
+ </details>
112
+
113
+ ```grain
114
+ flatMap : ((a -> Result<b, c>), Result<a, c>) -> Result<b, c>
115
+ ```
116
+
117
+ If the Result is `Ok(value)`, applies the given function to the `value` to produce a new Result.
118
+
119
+ Parameters:
120
+
121
+ |param|type|description|
122
+ |-----|----|-----------|
123
+ |`fn`|`a -> Result<b, c>`|The function to call on the value of an `Ok` variant|
124
+ |`result`|`Result<a, c>`|The result to map|
125
+
126
+ Returns:
127
+
128
+ |type|description|
129
+ |----|-----------|
130
+ |`Result<b, c>`|A new Result produced by the mapping function if the variant was `Ok` or the unmodified `Err` otherwise|
131
+
132
+ ### Result.**flatMapErr**
133
+
134
+ <details disabled>
135
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
136
+ No other changes yet.
137
+ </details>
138
+
139
+ ```grain
140
+ flatMapErr : ((a -> Result<b, c>), Result<b, a>) -> Result<b, c>
141
+ ```
142
+
143
+ If the Result is an `Err(value)`, applies the given function to the `value` to produce a new Result.
144
+
145
+ Parameters:
146
+
147
+ |param|type|description|
148
+ |-----|----|-----------|
149
+ |`fn`|`a -> Result<b, c>`|The function to call on the value of an `Err` variant|
150
+ |`result`|`Result<b, a>`|The result to map|
151
+
152
+ Returns:
153
+
154
+ |type|description|
155
+ |----|-----------|
156
+ |`Result<b, c>`|A new Result produced by the mapping function if the variant was `Err` or the unmodified `Ok` otherwise|
157
+
158
+ ### Result.**map**
159
+
160
+ <details disabled>
161
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
162
+ No other changes yet.
163
+ </details>
164
+
165
+ ```grain
166
+ map : ((a -> b), Result<a, c>) -> Result<b, c>
167
+ ```
168
+
169
+ If the Result is `Ok(value)`, applies the given function to the `value` and wraps the new value in an `Ok` variant.
170
+
171
+ Parameters:
172
+
173
+ |param|type|description|
174
+ |-----|----|-----------|
175
+ |`fn`|`a -> b`|The function to call on the value of an `Ok` variant|
176
+ |`result`|`Result<a, c>`|The result to map|
177
+
178
+ Returns:
179
+
180
+ |type|description|
181
+ |----|-----------|
182
+ |`Result<b, c>`|A new `Ok` variant produced by the mapping function if the variant was `Ok` or the unmodified `Err` otherwise|
183
+
184
+ ### Result.**mapErr**
185
+
186
+ <details disabled>
187
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
188
+ No other changes yet.
189
+ </details>
190
+
191
+ ```grain
192
+ mapErr : ((a -> b), Result<c, a>) -> Result<c, b>
193
+ ```
194
+
195
+ If the Result is `Err(value)`, applies the given function to the `value` and wraps the new value in an `Err` variant.
196
+
197
+ Parameters:
198
+
199
+ |param|type|description|
200
+ |-----|----|-----------|
201
+ |`fn`|`a -> b`|The function to call on the value of an `Err` variant|
202
+ |`result`|`Result<c, a>`|The result to map|
203
+
204
+ Returns:
205
+
206
+ |type|description|
207
+ |----|-----------|
208
+ |`Result<c, b>`|A new `Err` variant produced by the mapping function if the variant was `Err` or the unmodified `Ok` otherwise|
209
+
210
+ ### Result.**mapWithDefault**
211
+
212
+ <details disabled>
213
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
214
+ No other changes yet.
215
+ </details>
216
+
217
+ ```grain
218
+ mapWithDefault : ((a -> b), b, Result<a, c>) -> b
219
+ ```
220
+
221
+ If the Result is `Ok(value)`, applies the given function to the `value` to produce a new value, otherwise uses the default value.
222
+ Useful for unwrapping a successful Result while providing a fallback for any errors that can occur.
223
+
224
+ Parameters:
225
+
226
+ |param|type|description|
227
+ |-----|----|-----------|
228
+ |`fn`|`a -> b`|The function to call on the value of an `Ok` variant|
229
+ |`def`|`b`|A fallback value for an `Err` variant|
230
+ |`result`|`Result<a, c>`|The result to map|
231
+
232
+ Returns:
233
+
234
+ |type|description|
235
+ |----|-----------|
236
+ |`b`|The value produced by the mapping function if the result is of the `Ok` variant or the default value otherwise|
237
+
238
+ ### Result.**mapWithDefaultFn**
239
+
240
+ <details disabled>
241
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
242
+ No other changes yet.
243
+ </details>
244
+
245
+ ```grain
246
+ mapWithDefaultFn : ((a -> b), (c -> b), Result<a, c>) -> b
247
+ ```
248
+
249
+ If the Result is `Ok(value)`, applies the `fnOk` function to the `value` to produce a new value.
250
+ If the Result is `Err(value)`, applies the `fnErr` function to the `value` to produce a new value.
251
+ Useful for unwrapping a Result into a value, whether it is successful or unsuccessful.
252
+
253
+ Parameters:
254
+
255
+ |param|type|description|
256
+ |-----|----|-----------|
257
+ |`fnOk`|`a -> b`|The function to call on the value of an `Ok` variant|
258
+ |`fnErr`|`c -> b`|The function to call on the value of an `Err` variant|
259
+ |`result`|`Result<a, c>`|The result to map|
260
+
261
+ Returns:
262
+
263
+ |type|description|
264
+ |----|-----------|
265
+ |`b`|The value produced by one of the mapping functions|
266
+
267
+ ### Result.**or**
268
+
269
+ <details disabled>
270
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
271
+ No other changes yet.
272
+ </details>
273
+
274
+ ```grain
275
+ ( or ) : (Result<a, b>, Result<a, b>) -> Result<a, b>
276
+ ```
277
+
278
+ Behaves like a logical OR (`||`) where the first Result is only returned if it is the `Ok` variant and falling back to the second Result in all other cases.
279
+
280
+ Parameters:
281
+
282
+ |param|type|description|
283
+ |-----|----|-----------|
284
+ |`result1`|`Result<a, b>`|The first result|
285
+ |`result2`|`Result<a, b>`|The second result|
286
+
287
+ Returns:
288
+
289
+ |type|description|
290
+ |----|-----------|
291
+ |`Result<a, b>`|The first Result if it is the `Ok` variant or the second Result otherwise|
292
+
293
+ ### Result.**and**
294
+
295
+ <details disabled>
296
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
297
+ No other changes yet.
298
+ </details>
299
+
300
+ ```grain
301
+ and : (Result<a, b>, Result<a, b>) -> Result<a, b>
302
+ ```
303
+
304
+ Behaves like a logical AND (`&&`) where the first Result is only returned if it is the `Err` variant and falling back to the second Result in all other cases.
305
+
306
+ Parameters:
307
+
308
+ |param|type|description|
309
+ |-----|----|-----------|
310
+ |`result1`|`Result<a, b>`|The first result|
311
+ |`result2`|`Result<a, b>`|The second result|
312
+
313
+ Returns:
314
+
315
+ |type|description|
316
+ |----|-----------|
317
+ |`Result<a, b>`|The second Result if both are the `Ok` variant or the first Result otherwise|
318
+
319
+ ### Result.**peek**
320
+
321
+ <details disabled>
322
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
323
+ No other changes yet.
324
+ </details>
325
+
326
+ ```grain
327
+ peek : ((a -> b), (c -> d), Result<a, c>) -> Void
328
+ ```
329
+
330
+ If the Result is `Ok(value)`, applies the `fnOk` function to the `value` without producing a new value.
331
+ If the Result is `Err(value)`, applies the `fnErr` function to the `value` without producing a new value.
332
+ Useful for inspecting Results without changing anything.
333
+
334
+ Parameters:
335
+
336
+ |param|type|description|
337
+ |-----|----|-----------|
338
+ |`fnOk`|`a -> b`|The function to call on the value of an `Ok` variant|
339
+ |`fnErr`|`c -> d`|The function to call on the value of an `Err` variant|
340
+ |`result`|`Result<a, c>`|The result to inspect|
341
+
342
+ ### Result.**peekOk**
343
+
344
+ <details disabled>
345
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
346
+ No other changes yet.
347
+ </details>
348
+
349
+ ```grain
350
+ peekOk : ((a -> b), Result<a, c>) -> Void
351
+ ```
352
+
353
+ If the Result is `Ok(value)`, applies the given function to the `value` without producing a new value.
354
+
355
+ Parameters:
356
+
357
+ |param|type|description|
358
+ |-----|----|-----------|
359
+ |`fn`|`a -> b`|The function to call on the value of an `Ok` variant|
360
+ |`result`|`Result<a, c>`|The result to inspect|
361
+
362
+ ### Result.**peekErr**
363
+
364
+ <details disabled>
365
+ <summary tabindex="-1">Added in <code>0.2.0</code></summary>
366
+ No other changes yet.
367
+ </details>
368
+
369
+ ```grain
370
+ peekErr : ((a -> b), Result<c, a>) -> Void
371
+ ```
372
+
373
+ If the Result is `Err(value)`, applies the given function to the `value` without producing a new value.
374
+
375
+ Parameters:
376
+
377
+ |param|type|description|
378
+ |-----|----|-----------|
379
+ |`fn`|`a -> b`|The function to call on the value of an `Err` variant|
380
+ |`result`|`Result<c, a>`|The result to inspect|
381
+
382
+ ### Result.**expect**
383
+
384
+ <details disabled>
385
+ <summary tabindex="-1">Added in <code>0.4.0</code></summary>
386
+ No other changes yet.
387
+ </details>
388
+
389
+ ```grain
390
+ expect : (String, Result<a, b>) -> a
391
+ ```
392
+
393
+ Extracts the value inside an `Ok` result, otherwise throw an
394
+ exception containing the message and contents of the `Err`.
395
+
396
+ Parameters:
397
+
398
+ |param|type|description|
399
+ |-----|----|-----------|
400
+ |`msg`|`String`|The message to prepend if the result contains an `Err`|
401
+ |`result`|`Result<a, b>`|The result to extract a value from|
402
+
403
+ Returns:
404
+
405
+ |type|description|
406
+ |----|-----------|
407
+ |`a`|The unwrapped value if the Result is the `Ok` variant|
408
+
409
+ Examples:
410
+
411
+ ```grain
412
+ Result.expect("Unexpected error", Ok(1234)) + 42
413
+ ```
414
+
415
+ ### Result.**unwrap**
416
+
417
+ <details disabled>
418
+ <summary tabindex="-1">Added in <code>0.4.0</code></summary>
419
+ No other changes yet.
420
+ </details>
421
+
422
+ ```grain
423
+ unwrap : Result<a, b> -> a
424
+ ```
425
+
426
+ Extracts the value inside an `Ok` result, otherwise throw an
427
+ exception containing a default message and contents of the `Err`.
428
+
429
+ Parameters:
430
+
431
+ |param|type|description|
432
+ |-----|----|-----------|
433
+ |`result`|`Result<a, b>`|The result to extract a value from|
434
+
435
+ Returns:
436
+
437
+ |type|description|
438
+ |----|-----------|
439
+ |`a`|The unwrapped value if the result is the `Ok` variant|
440
+
441
+ Examples:
442
+
443
+ ```grain
444
+ Result.unwrap(Err("This will throw"))
445
+ ```
446
+
package/runtime/gc.gr CHANGED
@@ -40,8 +40,8 @@ primitive unbox : Box<a> -> a = "@unbox"
40
40
 
41
41
  exception DecRefError
42
42
 
43
- export let decimalCount32 = box((n) => 0n)
44
- export let utoa32Buffered = box((a, b, c) => void)
43
+ export let decimalCount32 = box((n: WasmI32) => 0n)
44
+ export let utoa32Buffered = box((a: WasmI32, b: WasmI32, c: WasmI32) => void)
45
45
 
46
46
  let mut _DEBUG = false
47
47
 
package/runtime/string.gr CHANGED
@@ -36,6 +36,8 @@ enum StringList { SLEmpty, SLCons(String, StringList) }
36
36
  @disableGC
37
37
  let slConsDisableGc = (a, b) => {
38
38
  Memory.incRef(WasmI32.fromGrain(SLCons))
39
+ Memory.incRef(WasmI32.fromGrain(a))
40
+ // for easier chaining, we don't incRef `b`
39
41
  SLCons(a, b)
40
42
  }
41
43
 
@@ -168,13 +170,16 @@ let join = (list) => {
168
170
  WasmI32.toGrain(str): String
169
171
  }
170
172
 
173
+ @disableGC
171
174
  let reverse = (list) => {
175
+ @disableGC
172
176
  let rec iter = (list, acc) => {
173
177
  match (list) {
174
178
  SLEmpty => acc,
175
- SLCons(first, rest) => iter(rest, SLCons(first, acc))
179
+ SLCons(first, rest) => iter(rest, slConsDisableGc(first, acc))
176
180
  }
177
181
  }
182
+ Memory.incRef(WasmI32.fromGrain(SLEmpty))
178
183
  iter(list, SLEmpty)
179
184
  }
180
185
 
@@ -381,19 +386,24 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
381
386
  variantName
382
387
  } else {
383
388
  let comspace = ", "
389
+ let rparen = ")"
384
390
  Memory.incRef(WasmI32.fromGrain(SLEmpty))
385
- let mut strings = slConsDisableGc(")", SLEmpty)
391
+ let mut strings = slConsDisableGc(rparen, SLEmpty)
386
392
  for (let mut i = variantArity * 4n - 4n; i >= 0n; i -= 4n) {
387
393
  let tmp = toStringHelp(WasmI32.load(ptr + i, 20n), extraIndents, false)
388
394
  strings = slConsDisableGc(tmp, strings)
395
+ Memory.decRef(WasmI32.fromGrain(tmp))
389
396
  if (i > 0n) {
390
- Memory.incRef(WasmI32.fromGrain(comspace))
391
397
  strings = slConsDisableGc(comspace, strings)
392
398
  }
393
399
  }
394
400
  Memory.incRef(WasmI32.fromGrain(variantName))
395
- strings = slConsDisableGc(variantName, slConsDisableGc("(", strings))
401
+ let lparen = "("
402
+ strings = slConsDisableGc(variantName, slConsDisableGc(lparen, strings))
396
403
  let string = join(strings)
404
+ Memory.decRef(WasmI32.fromGrain(variantName))
405
+ Memory.decRef(WasmI32.fromGrain(lparen))
406
+ Memory.decRef(WasmI32.fromGrain(rparen))
397
407
  Memory.decRef(WasmI32.fromGrain(strings))
398
408
  Memory.decRef(WasmI32.fromGrain(comspace))
399
409
  string
@@ -418,28 +428,31 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
418
428
  Memory.fill(spacePadding + 8n, 0x20n, padAmount) // create indentation
419
429
  let spacePadding = WasmI32.toGrain(spacePadding): String
420
430
  Memory.incRef(WasmI32.fromGrain(SLEmpty))
421
- let mut strings = slConsDisableGc("\n", slConsDisableGc(prevSpacePadding, slConsDisableGc("}", SLEmpty)))
431
+ let newline = "\n"
432
+ let rbrace = "}"
433
+ let mut strings = slConsDisableGc(newline, slConsDisableGc(prevSpacePadding, slConsDisableGc(rbrace, SLEmpty)))
422
434
  let colspace = ": "
423
435
  let comlf = ",\n"
424
436
  for (let mut i = recordArity * 4n - 4n; i >= 0n; i -= 4n) {
425
437
  let fieldName = WasmI32.toGrain(WasmI32.load(fields + i, 8n)): String
426
438
  let fieldValue = toStringHelp(WasmI32.load(ptr + i, 16n), extraIndents + 1n, false)
427
- Memory.incRef(WasmI32.fromGrain(spacePadding))
428
- Memory.incRef(WasmI32.fromGrain(fieldName))
429
- Memory.incRef(WasmI32.fromGrain(colspace))
430
439
  strings = slConsDisableGc(spacePadding, slConsDisableGc(fieldName, slConsDisableGc(colspace, slConsDisableGc(fieldValue, strings))))
440
+ Memory.decRef(WasmI32.fromGrain(fieldValue))
431
441
  if (i > 0n) {
432
- Memory.incRef(WasmI32.fromGrain(comlf))
433
442
  strings = slConsDisableGc(comlf, strings)
434
443
  }
435
444
  }
436
- strings = slConsDisableGc("{\n", strings)
445
+ let lbrace = "{\n"
446
+ strings = slConsDisableGc(lbrace, strings)
437
447
  let string = join(strings)
438
448
 
439
449
  Memory.decRef(WasmI32.fromGrain(strings))
440
450
  Memory.decRef(WasmI32.fromGrain(spacePadding))
441
451
  Memory.decRef(WasmI32.fromGrain(colspace))
442
452
  Memory.decRef(WasmI32.fromGrain(comlf))
453
+ Memory.decRef(WasmI32.fromGrain(lbrace))
454
+ Memory.decRef(WasmI32.fromGrain(rbrace))
455
+ Memory.decRef(WasmI32.fromGrain(newline))
443
456
 
444
457
  Memory.free(fields) // Avoid double-free of record field names
445
458
 
@@ -449,20 +462,24 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
449
462
  t when t == Tags._GRAIN_ARRAY_HEAP_TAG => {
450
463
  let arity = WasmI32.load(ptr, 4n)
451
464
  Memory.incRef(WasmI32.fromGrain(SLEmpty))
452
- let mut strings = slConsDisableGc("]", SLEmpty)
465
+ let rbrack = "]"
466
+ let mut strings = slConsDisableGc(rbrack, SLEmpty)
453
467
  let comspace = ", "
454
468
  for (let mut i = arity * 4n - 4n; i >= 0n; i -= 4n) {
455
469
  let item = toStringHelp(WasmI32.load(ptr + i, 8n), extraIndents, false)
456
470
  strings = slConsDisableGc(item, strings)
471
+ Memory.decRef(WasmI32.fromGrain(item))
457
472
  if (i > 0n) {
458
- Memory.incRef(WasmI32.fromGrain(comspace))
459
473
  strings = slConsDisableGc(comspace, strings)
460
474
  }
461
475
  }
462
- strings = slConsDisableGc("[> ", strings)
476
+ let lbrack = "[> "
477
+ strings = slConsDisableGc(lbrack, strings)
463
478
  let string = join(strings)
464
479
  Memory.decRef(WasmI32.fromGrain(strings))
465
480
  Memory.decRef(WasmI32.fromGrain(comspace))
481
+ Memory.decRef(WasmI32.fromGrain(lbrack))
482
+ Memory.decRef(WasmI32.fromGrain(rbrack))
466
483
 
467
484
  string
468
485
  },
@@ -479,9 +496,13 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
479
496
  let numerator = NumberUtils.itoa32(WasmI32.load(ptr, 8n), 10n)
480
497
  let denominator = NumberUtils.itoa32(WasmI32.load(ptr, 12n), 10n)
481
498
  Memory.incRef(WasmI32.fromGrain(SLEmpty))
482
- let strings = slConsDisableGc(numerator, slConsDisableGc("/", slConsDisableGc(denominator, SLEmpty)))
499
+ let slash = "/"
500
+ let strings = slConsDisableGc(numerator, slConsDisableGc(slash, slConsDisableGc(denominator, SLEmpty)))
483
501
  let string = join(strings)
484
502
  Memory.decRef(WasmI32.fromGrain(strings))
503
+ Memory.decRef(WasmI32.fromGrain(numerator))
504
+ Memory.decRef(WasmI32.fromGrain(denominator))
505
+ Memory.decRef(WasmI32.fromGrain(slash))
485
506
  string
486
507
  },
487
508
  t when t == Tags._GRAIN_FLOAT32_BOXED_NUM_TAG => {
@@ -503,30 +524,34 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
503
524
  WasmI32.store(ptr, 0x80000000n | tupleLength, 4n)
504
525
  let comspace = ", "
505
526
  Memory.incRef(WasmI32.fromGrain(SLEmpty))
506
- let mut strings = slConsDisableGc(")", SLEmpty)
527
+ let rparen = ")"
528
+ let mut strings = slConsDisableGc(rparen, SLEmpty)
507
529
  if (tupleLength <= 1n) {
508
530
  // Special case: unary tuple
509
- strings = slConsDisableGc(",", strings)
531
+ let comma = ","
532
+ strings = slConsDisableGc(comma, strings)
533
+ Memory.decRef(WasmI32.fromGrain(comma))
534
+ void
510
535
  }
511
536
  for (let mut i = tupleLength * 4n - 4n; i >= 0n; i -= 4n) {
512
537
  let item = toStringHelp(WasmI32.load(ptr + i, 8n), extraIndents, false)
513
- Memory.incRef(WasmI32.fromGrain(item))
514
- Memory.incRef(WasmI32.fromGrain(strings))
515
538
  strings = slConsDisableGc(item, strings)
539
+ Memory.decRef(WasmI32.fromGrain(item))
516
540
  if (i > 0n) {
517
- Memory.incRef(WasmI32.fromGrain(comspace))
518
- Memory.incRef(WasmI32.fromGrain(strings))
519
541
  strings = slConsDisableGc(comspace, strings)
520
542
  }
521
543
  }
522
544
  WasmI32.store(ptr, tupleLength, 4n)
523
545
 
524
546
  Memory.incRef(WasmI32.fromGrain(strings))
525
- strings = slConsDisableGc("(", strings)
547
+ let lparen = "("
548
+ strings = slConsDisableGc(lparen, strings)
526
549
 
527
550
  let string = join(strings)
528
551
  Memory.decRef(WasmI32.fromGrain(strings))
529
552
  Memory.decRef(WasmI32.fromGrain(comspace))
553
+ Memory.decRef(WasmI32.fromGrain(rparen))
554
+ Memory.decRef(WasmI32.fromGrain(lparen))
530
555
 
531
556
  string
532
557
  }
@@ -567,7 +592,9 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
567
592
  let mut isFirst = true
568
593
 
569
594
  Memory.incRef(WasmI32.fromGrain(SLEmpty))
570
- let mut strings = slConsDisableGc("[", SLEmpty)
595
+ let lbrack = "["
596
+ let commaspace = ", "
597
+ let mut strings = slConsDisableGc(lbrack, SLEmpty)
571
598
 
572
599
  while (true) {
573
600
  let variantId = WasmI32.load(cur, 12n) >> 1n // tagged number
@@ -575,19 +602,24 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
575
602
  break
576
603
  } else {
577
604
  if (!isFirst) {
578
- strings = slConsDisableGc(", ", strings)
605
+ strings = slConsDisableGc(commaspace, strings)
579
606
  }
580
607
  isFirst = false
581
608
  let item = toStringHelp(WasmI32.load(cur, 20n), extraIndents, false)
582
609
  strings = slConsDisableGc(item, strings)
610
+ Memory.decRef(WasmI32.fromGrain(item))
583
611
  cur = WasmI32.load(cur, 24n)
584
612
  }
585
613
  }
586
- strings = slConsDisableGc("]", strings)
614
+ let rbrack = "]"
615
+ strings = slConsDisableGc(rbrack, strings)
587
616
  let reversed = reverse(strings)
588
617
  let string = join(reversed)
589
618
  Memory.decRef(WasmI32.fromGrain(strings))
590
619
  Memory.decRef(WasmI32.fromGrain(reversed))
620
+ Memory.decRef(WasmI32.fromGrain(lbrack))
621
+ Memory.decRef(WasmI32.fromGrain(rbrack))
622
+ Memory.decRef(WasmI32.fromGrain(commaspace))
591
623
  string
592
624
  }
593
625