@grain/stdlib 0.5.12 → 0.6.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 (155) hide show
  1. package/CHANGELOG.md +200 -0
  2. package/LICENSE +1 -1
  3. package/README.md +25 -2
  4. package/array.gr +1512 -199
  5. package/array.md +2032 -94
  6. package/bigint.gr +239 -140
  7. package/bigint.md +450 -106
  8. package/buffer.gr +595 -102
  9. package/buffer.md +903 -145
  10. package/bytes.gr +401 -110
  11. package/bytes.md +551 -63
  12. package/char.gr +228 -49
  13. package/char.md +373 -7
  14. package/exception.gr +26 -12
  15. package/exception.md +29 -5
  16. package/float32.gr +130 -109
  17. package/float32.md +185 -57
  18. package/float64.gr +112 -99
  19. package/float64.md +185 -57
  20. package/hash.gr +47 -37
  21. package/hash.md +21 -3
  22. package/int16.gr +430 -0
  23. package/int16.md +618 -0
  24. package/int32.gr +200 -269
  25. package/int32.md +254 -289
  26. package/int64.gr +142 -225
  27. package/int64.md +254 -289
  28. package/int8.gr +511 -0
  29. package/int8.md +786 -0
  30. package/json.gr +2084 -0
  31. package/json.md +608 -0
  32. package/list.gr +120 -68
  33. package/list.md +125 -80
  34. package/map.gr +560 -57
  35. package/map.md +672 -56
  36. package/marshal.gr +239 -227
  37. package/marshal.md +36 -4
  38. package/number.gr +626 -676
  39. package/number.md +738 -153
  40. package/option.gr +33 -35
  41. package/option.md +58 -42
  42. package/package.json +2 -2
  43. package/path.gr +148 -187
  44. package/path.md +47 -96
  45. package/pervasives.gr +75 -416
  46. package/pervasives.md +85 -180
  47. package/priorityqueue.gr +433 -74
  48. package/priorityqueue.md +422 -54
  49. package/queue.gr +362 -80
  50. package/queue.md +433 -38
  51. package/random.gr +67 -75
  52. package/random.md +68 -40
  53. package/range.gr +135 -63
  54. package/range.md +198 -43
  55. package/rational.gr +284 -0
  56. package/rational.md +545 -0
  57. package/regex.gr +933 -1066
  58. package/regex.md +59 -60
  59. package/result.gr +23 -25
  60. package/result.md +54 -39
  61. package/runtime/atof/common.gr +78 -82
  62. package/runtime/atof/common.md +22 -10
  63. package/runtime/atof/decimal.gr +102 -127
  64. package/runtime/atof/decimal.md +28 -7
  65. package/runtime/atof/lemire.gr +56 -71
  66. package/runtime/atof/lemire.md +9 -1
  67. package/runtime/atof/parse.gr +83 -110
  68. package/runtime/atof/parse.md +12 -2
  69. package/runtime/atof/slow.gr +28 -35
  70. package/runtime/atof/slow.md +9 -1
  71. package/runtime/atof/table.gr +19 -18
  72. package/runtime/atof/table.md +10 -2
  73. package/runtime/atoi/parse.gr +153 -136
  74. package/runtime/atoi/parse.md +50 -1
  75. package/runtime/bigint.gr +410 -517
  76. package/runtime/bigint.md +71 -57
  77. package/runtime/compare.gr +176 -85
  78. package/runtime/compare.md +31 -1
  79. package/runtime/dataStructures.gr +144 -32
  80. package/runtime/dataStructures.md +267 -31
  81. package/runtime/debugPrint.gr +34 -15
  82. package/runtime/debugPrint.md +37 -5
  83. package/runtime/equal.gr +53 -52
  84. package/runtime/equal.md +30 -1
  85. package/runtime/exception.gr +38 -47
  86. package/runtime/exception.md +10 -8
  87. package/runtime/gc.gr +23 -152
  88. package/runtime/gc.md +13 -17
  89. package/runtime/malloc.gr +31 -31
  90. package/runtime/malloc.md +11 -3
  91. package/runtime/numberUtils.gr +191 -172
  92. package/runtime/numberUtils.md +17 -9
  93. package/runtime/numbers.gr +1695 -1021
  94. package/runtime/numbers.md +1098 -134
  95. package/runtime/string.gr +540 -242
  96. package/runtime/string.md +76 -6
  97. package/runtime/unsafe/constants.gr +30 -13
  98. package/runtime/unsafe/constants.md +80 -0
  99. package/runtime/unsafe/conv.gr +55 -28
  100. package/runtime/unsafe/conv.md +41 -9
  101. package/runtime/unsafe/memory.gr +10 -30
  102. package/runtime/unsafe/memory.md +15 -19
  103. package/runtime/unsafe/tags.gr +37 -21
  104. package/runtime/unsafe/tags.md +88 -8
  105. package/runtime/unsafe/wasmf32.gr +30 -36
  106. package/runtime/unsafe/wasmf32.md +64 -56
  107. package/runtime/unsafe/wasmf64.gr +30 -36
  108. package/runtime/unsafe/wasmf64.md +64 -56
  109. package/runtime/unsafe/wasmi32.gr +49 -66
  110. package/runtime/unsafe/wasmi32.md +102 -94
  111. package/runtime/unsafe/wasmi64.gr +52 -79
  112. package/runtime/unsafe/wasmi64.md +108 -100
  113. package/runtime/utils/printing.gr +13 -15
  114. package/runtime/utils/printing.md +11 -3
  115. package/runtime/wasi.gr +294 -295
  116. package/runtime/wasi.md +62 -42
  117. package/set.gr +574 -64
  118. package/set.md +634 -54
  119. package/stack.gr +181 -64
  120. package/stack.md +271 -42
  121. package/string.gr +453 -533
  122. package/string.md +241 -151
  123. package/uint16.gr +369 -0
  124. package/uint16.md +585 -0
  125. package/uint32.gr +470 -0
  126. package/uint32.md +737 -0
  127. package/uint64.gr +471 -0
  128. package/uint64.md +737 -0
  129. package/uint8.gr +369 -0
  130. package/uint8.md +585 -0
  131. package/uri.gr +1093 -0
  132. package/uri.md +477 -0
  133. package/{sys → wasi}/file.gr +914 -500
  134. package/{sys → wasi}/file.md +454 -50
  135. package/wasi/process.gr +292 -0
  136. package/{sys → wasi}/process.md +164 -6
  137. package/wasi/random.gr +77 -0
  138. package/wasi/random.md +80 -0
  139. package/{sys → wasi}/time.gr +15 -22
  140. package/{sys → wasi}/time.md +5 -5
  141. package/immutablearray.gr +0 -929
  142. package/immutablearray.md +0 -1038
  143. package/immutablemap.gr +0 -493
  144. package/immutablemap.md +0 -479
  145. package/immutablepriorityqueue.gr +0 -360
  146. package/immutablepriorityqueue.md +0 -291
  147. package/immutableset.gr +0 -498
  148. package/immutableset.md +0 -449
  149. package/runtime/debug.gr +0 -2
  150. package/runtime/debug.md +0 -6
  151. package/runtime/unsafe/errors.gr +0 -36
  152. package/runtime/unsafe/errors.md +0 -204
  153. package/sys/process.gr +0 -254
  154. package/sys/random.gr +0 -79
  155. package/sys/random.md +0 -66
package/runtime/equal.gr CHANGED
@@ -1,24 +1,19 @@
1
- /* grainc-flags --no-pervasives */
2
-
3
- import WasmI32, {
4
- eq as (==),
5
- ne as (!=),
6
- and as (&),
7
- xor as (^),
8
- add as (+),
9
- sub as (-),
10
- mul as (*),
11
- ltS as (<),
12
- remS as (%),
13
- shl as (<<),
14
- } from "runtime/unsafe/wasmi32"
15
- import WasmI64 from "runtime/unsafe/wasmi64"
16
- import Tags from "runtime/unsafe/tags"
17
- import { isNumber, numberEqual } from "runtime/numbers"
18
-
19
- primitive (!): Bool -> Bool = "@not"
20
- primitive (||): (Bool, Bool) -> Bool = "@or"
21
- primitive (&&): (Bool, Bool) -> Bool = "@and"
1
+ @noPervasives
2
+ module Equal
3
+
4
+ from "runtime/unsafe/memory" include Memory
5
+ from "runtime/unsafe/wasmi32" include WasmI32
6
+ use WasmI32.{ (==), (!=), (&), (^), (+), (-), (*), (<), remS as (%), (<<) }
7
+ from "runtime/unsafe/wasmi64" include WasmI64
8
+ from "runtime/unsafe/wasmf32" include WasmF32
9
+ from "runtime/unsafe/tags" include Tags
10
+ from "runtime/numbers" include Numbers
11
+ use Numbers.{ isNumber, numberEqual }
12
+
13
+ primitive (!) = "@not"
14
+ primitive (||) = "@or"
15
+ primitive (&&) = "@and"
16
+ primitive ignore = "@ignore"
22
17
 
23
18
  @unsafe
24
19
  let cycleMarker = 0x80000000n
@@ -121,9 +116,7 @@ let rec heapEqualHelp = (heapTag, xptr, yptr) => {
121
116
  result
122
117
  }
123
118
  },
124
- t when (
125
- t == Tags._GRAIN_STRING_HEAP_TAG || t == Tags._GRAIN_BYTES_HEAP_TAG
126
- ) => {
119
+ t when t == Tags._GRAIN_STRING_HEAP_TAG || t == Tags._GRAIN_BYTES_HEAP_TAG => {
127
120
  let xlength = WasmI32.load(xptr, 4n)
128
121
  let ylength = WasmI32.load(yptr, 4n)
129
122
 
@@ -131,30 +124,7 @@ let rec heapEqualHelp = (heapTag, xptr, yptr) => {
131
124
  if (xlength != ylength) {
132
125
  false
133
126
  } else {
134
- let extra = xlength % 8n
135
- let first = xlength - extra
136
- let mut result = true
137
- for (let mut i = 0n; i < first; i += 8n) {
138
- if (
139
- WasmI64.ne(WasmI64.load(xptr + i, 8n), WasmI64.load(yptr + i, 8n))
140
- ) {
141
- result = false
142
- break
143
- }
144
- }
145
- if (result) {
146
- for (let mut i = 0n; i < extra; i += 1n) {
147
- if (
148
- WasmI32.load8U(xptr + first + i, 8n) !=
149
- WasmI32.load8U(yptr + first + i, 8n)
150
- ) {
151
- result = false
152
- break
153
- }
154
- }
155
- }
156
-
157
- result
127
+ Memory.compare(xptr + 8n, yptr + 8n, xlength) == 0n
158
128
  }
159
129
  },
160
130
  t when t == Tags._GRAIN_TUPLE_HEAP_TAG => {
@@ -184,13 +154,25 @@ let rec heapEqualHelp = (heapTag, xptr, yptr) => {
184
154
  result
185
155
  }
186
156
  },
157
+ t when t == Tags._GRAIN_UINT32_HEAP_TAG || t == Tags._GRAIN_INT32_HEAP_TAG => {
158
+ let xval = WasmI32.load(xptr, 4n)
159
+ let yval = WasmI32.load(yptr, 4n)
160
+ xval == yval
161
+ },
162
+ // Float32 is handled by equalHelp directly
163
+ t when t == Tags._GRAIN_UINT64_HEAP_TAG => {
164
+ use WasmI64.{ (==) }
165
+ let xval = WasmI64.load(xptr, 8n)
166
+ let yval = WasmI64.load(yptr, 8n)
167
+ xval == yval
168
+ },
187
169
  _ => {
188
170
  // No other implementation
189
171
  xptr == yptr
190
172
  },
191
173
  }
192
- },
193
- equalHelp = (x, y) => {
174
+ }
175
+ and equalHelp = (x, y) => {
194
176
  if (
195
177
  (x & Tags._GRAIN_GENERIC_TAG_MASK) != 0n &&
196
178
  (y & Tags._GRAIN_GENERIC_TAG_MASK) != 0n
@@ -200,6 +182,12 @@ equalHelp = (x, y) => {
200
182
  } else if (isNumber(x)) {
201
183
  // Numbers have special equality rules, e.g. NaN != NaN
202
184
  numberEqual(x, y)
185
+ } else if (WasmI32.load(x, 0n) == Tags._GRAIN_FLOAT32_HEAP_TAG) {
186
+ // Short circuit for Float32 to correctly handle NaN != NaN
187
+ let xval = WasmF32.load(x, 4n)
188
+ let yval = WasmF32.load(y, 4n)
189
+ use WasmF32.{ (==) }
190
+ xval == yval
203
191
  } else {
204
192
  // Handle all other heap allocated things
205
193
  // Can short circuit if pointers are the same
@@ -207,7 +195,20 @@ equalHelp = (x, y) => {
207
195
  }
208
196
  }
209
197
 
198
+ /**
199
+ * Check that two values are equal. This checks for structural equality,
200
+ * so it also works for comparing things like tuples and lists.
201
+ *
202
+ * @param value1: The first operand
203
+ * @param value2: The second operand
204
+ * @returns `true` if the values are structurally equal or `false` otherwise
205
+ *
206
+ * @since v0.1.0
207
+ */
210
208
  @unsafe
211
- export let equal = (x: a, y: a) => {
212
- equalHelp(WasmI32.fromGrain(x), WasmI32.fromGrain(y))
209
+ provide let equal = (value1: a, value2: a) => {
210
+ let value = equalHelp(WasmI32.fromGrain(value1), WasmI32.fromGrain(value2))
211
+ ignore(value1)
212
+ ignore(value2)
213
+ value
213
214
  }
package/runtime/equal.md CHANGED
@@ -1,6 +1,35 @@
1
+ ---
2
+ title: Equal
3
+ ---
4
+
5
+ ## Values
6
+
7
+ Functions and constants included in the Equal module.
8
+
1
9
  ### Equal.**equal**
2
10
 
11
+ <details disabled>
12
+ <summary tabindex="-1">Added in <code>0.1.0</code></summary>
13
+ No other changes yet.
14
+ </details>
15
+
3
16
  ```grain
4
- equal : (a, a) -> Bool
17
+ equal : (value1: a, value2: a) => Bool
5
18
  ```
6
19
 
20
+ Check that two values are equal. This checks for structural equality,
21
+ so it also works for comparing things like tuples and lists.
22
+
23
+ Parameters:
24
+
25
+ |param|type|description|
26
+ |-----|----|-----------|
27
+ |`value1`|`a`|The first operand|
28
+ |`value2`|`a`|The second operand|
29
+
30
+ Returns:
31
+
32
+ |type|description|
33
+ |----|-----------|
34
+ |`Bool`|`true` if the values are structurally equal or `false` otherwise|
35
+
@@ -1,35 +1,26 @@
1
- /* grainc-flags --compilation-mode=runtime */
1
+ @runtimeMode
2
+ module Exception
2
3
 
3
- import WasmI32, { eq as (==), add as (+) } from "runtime/unsafe/wasmi32"
4
+ from "runtime/unsafe/wasmi32" include WasmI32
5
+ use WasmI32.{ (==), (+), (-) }
4
6
 
5
- import foreign wasm fd_write: (
6
- WasmI32,
7
- WasmI32,
8
- WasmI32,
9
- WasmI32,
10
- ) -> WasmI32 from "wasi_snapshot_preview1"
7
+ foreign wasm fd_write:
8
+ (WasmI32, WasmI32, WasmI32, WasmI32) => WasmI32 from "wasi_snapshot_preview1"
11
9
 
12
- primitive unreachable: () -> a = "@unreachable"
10
+ primitive unreachable = "@unreachable"
13
11
 
14
- enum Option<a> {
15
- Some(a),
16
- None,
17
- }
18
-
19
- export let mut printers = 0n
12
+ provide let mut printers = 0n
20
13
 
21
14
  // These functions are dangerous because they leak runtime memory and perform
22
15
  // no GC operations. As such, they should only be called by this module and/or
23
16
  // modules that understand these restrictions, namely Pervasives.
24
17
 
25
- export let dangerouslyRegisterBasePrinter = f => {
18
+ provide let dangerouslyRegisterBasePrinter = f => {
26
19
  let mut current = printers
27
20
  while (true) {
28
21
  // There will be at least one printer registered by the time this is called
29
- let (_, next) = WasmI32.toGrain(current): (
30
- Exception -> Option<String>,
31
- WasmI32
32
- )
22
+ let (_, next) = WasmI32.toGrain(current):
23
+ (Exception => Option<String>, WasmI32)
33
24
  if (next == 0n) {
34
25
  // Using a tuple in runtime mode is typically disallowed as there is no way
35
26
  // to reclaim the memory, but this function is only called once
@@ -44,36 +35,38 @@ export let dangerouslyRegisterBasePrinter = f => {
44
35
  void
45
36
  }
46
37
 
47
- export let dangerouslyRegisterPrinter = f => {
38
+ provide let dangerouslyRegisterPrinter = f => {
48
39
  printers = WasmI32.fromGrain((f, printers))
49
40
  // We don't decRef the closure or arguments here to avoid a cyclic dep. on Memory.
50
41
  // This is fine, as this function is only called seldomly.
51
42
  void
52
43
  }
53
44
 
45
+ // avoid cirular dependency on gc
46
+ let incRef = v => {
47
+ let ptr = WasmI32.fromGrain(v) - 8n
48
+ WasmI32.store(ptr, WasmI32.load(ptr, 0n) + 1n, 0n)
49
+ v
50
+ }
51
+
54
52
  let _GENERIC_EXCEPTION_NAME = "GrainException"
55
53
 
56
54
  let exceptionToString = (e: Exception) => {
57
55
  let mut result = _GENERIC_EXCEPTION_NAME
58
56
  let mut current = printers
59
57
  while (true) {
60
- if (current == 0n) {
61
- break
62
- }
63
- let (printer, next) = WasmI32.toGrain(current): (
64
- Exception -> Option<String>,
65
- WasmI32
66
- )
67
- match (printer(e)) {
68
- Some(str) => {
69
- result = str
70
- break
58
+ if (current == 0n) return result
59
+ let (printer, next) = WasmI32.toGrain(current):
60
+ (Exception => Option<String>, WasmI32)
61
+ // as GC is not available, manually increment the references
62
+ match (incRef(printer)(incRef(e))) {
63
+ Some(str) => return str,
64
+ None => {
65
+ current = next
71
66
  },
72
- None => void,
73
67
  }
74
- current = next
75
68
  }
76
- result
69
+ return result
77
70
  }
78
71
 
79
72
  // HACK: Allocate static buffer for printing (40 bytes)
@@ -81,7 +74,7 @@ let exceptionToString = (e: Exception) => {
81
74
  // the runtime heap, but this is the only module that needs to do it
82
75
  let iov = WasmI32.fromGrain([> 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n])
83
76
 
84
- export let panic = (msg: String) => {
77
+ provide let panic = (msg: String) => {
85
78
  let ptr = WasmI32.fromGrain(msg)
86
79
  let written = iov + 32n
87
80
  let lf = iov + 36n
@@ -94,18 +87,16 @@ export let panic = (msg: String) => {
94
87
  unreachable()
95
88
  }
96
89
 
97
- export let panicWithException = (e: Exception) => {
90
+ provide let panicWithException = (e: Exception) => {
98
91
  panic(exceptionToString(e))
99
92
  }
100
93
 
101
- export exception IndexOutOfBounds
102
- export exception IndexNonInteger
103
- export exception DivisionByZero
104
- export exception ModuloByZero
105
- export exception Overflow
106
- export exception NumberNotIntlike
107
- export exception NumberNotRational
108
- export exception MatchFailure
94
+ provide exception DivisionByZero
95
+ provide exception ModuloByZero
96
+ provide exception Overflow
97
+ provide exception NumberNotIntlike
98
+ provide exception NumberNotRational
99
+ provide exception MatchFailure
109
100
  /*
110
101
  * `assert <condition>` is essentially syntactic sugar for:
111
102
  * `if (!<condition>) throw AssertionError(<message>)`
@@ -114,8 +105,8 @@ export exception MatchFailure
114
105
  * this file to construct the error, but constructing a string in this module is impractical as we
115
106
  * don't have access to memory allocation since malloc.gr depends on this module.
116
107
  */
117
- export exception AssertionError(String)
118
- export exception InvalidArgument(String)
108
+
109
+ provide exception InvalidArgument(String)
119
110
 
120
111
  let runtimeErrorPrinter = e => {
121
112
  match (e) {
@@ -1,8 +1,10 @@
1
- ### Exception.**Option**
1
+ ---
2
+ title: Exception
3
+ ---
2
4
 
3
- ```grain
4
- type Option<a>
5
- ```
5
+ ## Values
6
+
7
+ Functions and constants included in the Exception module.
6
8
 
7
9
  ### Exception.**printers**
8
10
 
@@ -13,24 +15,24 @@ printers : WasmI32
13
15
  ### Exception.**dangerouslyRegisterBasePrinter**
14
16
 
15
17
  ```grain
16
- dangerouslyRegisterBasePrinter : a -> Void
18
+ dangerouslyRegisterBasePrinter : (f: a) => Void
17
19
  ```
18
20
 
19
21
  ### Exception.**dangerouslyRegisterPrinter**
20
22
 
21
23
  ```grain
22
- dangerouslyRegisterPrinter : a -> Void
24
+ dangerouslyRegisterPrinter : (f: a) => Void
23
25
  ```
24
26
 
25
27
  ### Exception.**panic**
26
28
 
27
29
  ```grain
28
- panic : String -> a
30
+ panic : (msg: String) => a
29
31
  ```
30
32
 
31
33
  ### Exception.**panicWithException**
32
34
 
33
35
  ```grain
34
- panicWithException : Exception -> a
36
+ panicWithException : (e: Exception) => a
35
37
  ```
36
38
 
package/runtime/gc.gr CHANGED
@@ -1,4 +1,5 @@
1
- /* grainc-flags --compilation-mode=runtime */
1
+ @runtimeMode
2
+ module GC
2
3
 
3
4
  /* Notes:
4
5
  *
@@ -18,131 +19,28 @@
18
19
  * userPtr : The pointer returned (and referenced by) to the Grain runtime
19
20
  */
20
21
 
21
- import Malloc from "runtime/malloc"
22
- import Tags from "runtime/unsafe/tags"
23
- import WasmI32, {
24
- add as (+),
25
- sub as (-),
26
- mul as (*),
27
- and as (&),
28
- eq as (==),
29
- } from "runtime/unsafe/wasmi32"
22
+ from "runtime/malloc" include Malloc
23
+ from "runtime/unsafe/tags" include Tags
24
+ from "runtime/unsafe/wasmi32" include WasmI32
25
+ use WasmI32.{ (+), (-), (*), (&), (==), (!=) }
30
26
 
31
27
  // Using foreigns directly here to avoid cyclic dependency
32
- import foreign wasm fd_write: (
33
- WasmI32,
34
- WasmI32,
35
- WasmI32,
36
- WasmI32,
37
- ) -> WasmI32 from "wasi_snapshot_preview1"
28
+ foreign wasm fd_write:
29
+ (WasmI32, WasmI32, WasmI32, WasmI32) => WasmI32 from "wasi_snapshot_preview1"
38
30
 
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"
31
+ primitive (&&) = "@and"
32
+ primitive (||) = "@or"
33
+ primitive throw = "@throw"
34
+ primitive ignore = "@ignore"
35
+ primitive box = "@box"
36
+ primitive unbox = "@unbox"
45
37
 
46
38
  exception DecRefError
47
39
 
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)
60
-
61
40
  let mut _DEBUG = false
62
41
 
63
42
  let _HEADER_SIZE = 8n
64
43
 
65
- /*
66
- //Debugging functions:
67
- import foreign wasm fd_sync : (WasmI32) -> WasmI32 from "wasi_snapshot_preview1"
68
-
69
- // incRef debug messages: "decRef: 0xNNNNNN (prev count: nn)\n"
70
- let _INCREF_DEBUG_STR_1 = "incRef: 0x"
71
- let _INCREF_DEBUG_STR_2 = " (prev count: "
72
- let _INCREF_DEBUG_STR_3 = "; tag: "
73
- let _INCREF_DEBUG_STR_4 = ")\n"
74
-
75
- // decRef debug messages: "decRef: 0xNNNNNN (prev count: nn)\n"
76
- let _DECREF_DEBUG_STR_1 = "decRef: 0x"
77
- let _DECREF_DEBUG_STR_2 = " (prev count: "
78
- let _DECREF_DEBUG_STR_3 = "; ignoreZeros: true)\n"
79
- let _DECREF_DEBUG_STR_4 = "; ignoreZeros: false)\n"
80
-
81
- let logIncRef = (userPtr: WasmI32, refCount: WasmI32) => {
82
- let ptrDecimals = WasmI32.shrU(31n - WasmI32.clz(userPtr), 2n) + 1n
83
- let ptrStr = Malloc.malloc(ptrDecimals)
84
- unbox(utoa32Buffered)(ptrStr, userPtr, 16n)
85
- let refCountDecimals = unbox(decimalCount32)(refCount)
86
- let refCountStr = Malloc.malloc(refCountDecimals)
87
- unbox(utoa32Buffered)(refCountStr, refCount, 10n)
88
- let tag = WasmI32.load(userPtr, 0n)
89
- let tagDecimals = unbox(decimalCount32)(tag)
90
- let tagStr = Malloc.malloc(tagDecimals)
91
- unbox(utoa32Buffered)(tagStr, tag, 10n)
92
- let iov = Malloc.malloc((8n * 5n) + 4n)
93
- let written = iov + (8n * 7n)
94
- WasmI32.store(iov, WasmI32.fromGrain(_INCREF_DEBUG_STR_1) + 8n, 0n)
95
- WasmI32.store(iov, WasmI32.load(WasmI32.fromGrain(_INCREF_DEBUG_STR_1), 4n), 4n)
96
- WasmI32.store(iov, ptrStr, 8n)
97
- WasmI32.store(iov, ptrDecimals, 12n)
98
- WasmI32.store(iov, WasmI32.fromGrain(_INCREF_DEBUG_STR_2) + 8n, 16n)
99
- WasmI32.store(iov, WasmI32.load(WasmI32.fromGrain(_INCREF_DEBUG_STR_2), 4n), 20n)
100
- WasmI32.store(iov, refCountStr, 24n)
101
- WasmI32.store(iov, refCountDecimals, 28n)
102
- WasmI32.store(iov, WasmI32.fromGrain(_INCREF_DEBUG_STR_3) + 8n, 32n)
103
- WasmI32.store(iov, WasmI32.load(WasmI32.fromGrain(_INCREF_DEBUG_STR_3), 4n), 36n)
104
- WasmI32.store(iov, tagStr, 40n)
105
- WasmI32.store(iov, tagDecimals, 44n)
106
- WasmI32.store(iov, WasmI32.fromGrain(_INCREF_DEBUG_STR_4) + 8n, 48n)
107
- WasmI32.store(iov, WasmI32.load(WasmI32.fromGrain(_INCREF_DEBUG_STR_4), 4n), 52n)
108
- fd_write(1n, iov, 7n, written)
109
- fd_sync(1n)
110
- Malloc.free(ptrStr)
111
- Malloc.free(refCountStr)
112
- }
113
-
114
- let logDecRef = (userPtr: WasmI32, refCount: WasmI32, ignoreZeros) => {
115
- let ptrDecimals = WasmI32.shrU(31n - WasmI32.clz(userPtr), 2n) + 1n
116
- let ptrStr = Malloc.malloc(ptrDecimals)
117
- unbox(utoa32Buffered)(ptrStr, userPtr, 16n)
118
- let refCountDecimals = unbox(decimalCount32)(refCount)
119
- let refCountStr = Malloc.malloc(refCountDecimals)
120
- unbox(utoa32Buffered)(refCountStr, refCount, 10n)
121
- let iov = Malloc.malloc((8n * 5n) + 4n)
122
- let written = iov + (8n * 5n)
123
- WasmI32.store(iov, WasmI32.fromGrain(_DECREF_DEBUG_STR_1) + 8n, 0n)
124
- WasmI32.store(iov, WasmI32.load(WasmI32.fromGrain(_DECREF_DEBUG_STR_1), 4n), 4n)
125
- WasmI32.store(iov, ptrStr, 8n)
126
- WasmI32.store(iov, ptrDecimals, 12n)
127
- WasmI32.store(iov, WasmI32.fromGrain(_DECREF_DEBUG_STR_2) + 8n, 16n)
128
- WasmI32.store(iov, WasmI32.load(WasmI32.fromGrain(_DECREF_DEBUG_STR_2), 4n), 20n)
129
- WasmI32.store(iov, refCountStr, 24n)
130
- WasmI32.store(iov, refCountDecimals, 28n)
131
- if (ignoreZeros) {
132
- WasmI32.store(iov, WasmI32.fromGrain(_DECREF_DEBUG_STR_3) + 8n, 32n)
133
- WasmI32.store(iov, WasmI32.load(WasmI32.fromGrain(_DECREF_DEBUG_STR_3), 4n), 36n)
134
- } else {
135
- WasmI32.store(iov, WasmI32.fromGrain(_DECREF_DEBUG_STR_4) + 8n, 32n)
136
- WasmI32.store(iov, WasmI32.load(WasmI32.fromGrain(_DECREF_DEBUG_STR_4), 4n), 36n)
137
- }
138
- fd_write(1n, iov, 5n, written)
139
- fd_sync(1n)
140
- Malloc.free(ptrStr)
141
- Malloc.free(refCountStr)
142
- }
143
-
144
- */
145
-
146
44
  let getRefCount = (userPtr: WasmI32) => {
147
45
  WasmI32.load(userPtr - _HEADER_SIZE, 0n)
148
46
  }
@@ -151,7 +49,7 @@ let setRefCount = (userPtr: WasmI32, count: WasmI32) => {
151
49
  WasmI32.store(userPtr - _HEADER_SIZE, count, 0n)
152
50
  }
153
51
 
154
- export let malloc = (size: WasmI32) => {
52
+ provide let malloc = (size: WasmI32) => {
155
53
  // Add space for header
156
54
  let rawPtr = Malloc.malloc(size + _HEADER_SIZE)
157
55
 
@@ -163,16 +61,13 @@ export let malloc = (size: WasmI32) => {
163
61
  rawPtr + _HEADER_SIZE
164
62
  }
165
63
 
166
- export let free = (userPtr: WasmI32) => {
64
+ provide let free = (userPtr: WasmI32) => {
167
65
  // Free the raw pointer
168
66
  Malloc.free(userPtr - _HEADER_SIZE)
169
67
  }
170
68
 
171
- export let incRef = (userPtr: WasmI32) => {
172
- if (
173
- WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) &&
174
- WasmI32.ne(userPtr, 0n)
175
- ) {
69
+ provide let incRef = (userPtr: WasmI32) => {
70
+ if (WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) && userPtr != 0n) {
176
71
  // if (_DEBUG) {
177
72
  // logIncRef(userPtr, getRefCount(userPtr))
178
73
  // void;
@@ -183,10 +78,7 @@ export let incRef = (userPtr: WasmI32) => {
183
78
  }
184
79
 
185
80
  let rec decRef = (userPtr: WasmI32, ignoreZeros: Bool) => {
186
- if (
187
- WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) &&
188
- WasmI32.ne(userPtr, 0n)
189
- ) {
81
+ if (WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) && userPtr != 0n) {
190
82
  let refCount = getRefCount(userPtr)
191
83
  // if (_DEBUG) {
192
84
  // logDecRef(userPtr, refCount, ignoreZeros)
@@ -213,8 +105,8 @@ let rec decRef = (userPtr: WasmI32, ignoreZeros: Bool) => {
213
105
  } else {
214
106
  userPtr
215
107
  }
216
- },
217
- decRefChildren = (userPtr: WasmI32) => {
108
+ }
109
+ and decRefChildren = (userPtr: WasmI32) => {
218
110
  match (WasmI32.load(userPtr, 0n)) {
219
111
  t when t == Tags._GRAIN_BOXED_NUM_HEAP_TAG => {
220
112
  let tag = WasmI32.load(userPtr, 4n)
@@ -238,9 +130,7 @@ decRefChildren = (userPtr: WasmI32) => {
238
130
  ignore(decRef(WasmI32.load(userPtr + i, 16n), false))
239
131
  }
240
132
  },
241
- t when (
242
- t == Tags._GRAIN_ARRAY_HEAP_TAG || t == Tags._GRAIN_TUPLE_HEAP_TAG
243
- ) => {
133
+ t when t == Tags._GRAIN_ARRAY_HEAP_TAG || t == Tags._GRAIN_TUPLE_HEAP_TAG => {
244
134
  let arity = WasmI32.load(userPtr, 4n)
245
135
  let maxOffset = arity * 4n
246
136
  for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
@@ -261,23 +151,4 @@ decRefChildren = (userPtr: WasmI32) => {
261
151
  }
262
152
  }
263
153
 
264
- export let decRef = userPtr => decRef(userPtr, false)
265
-
266
- // For debugging:
267
-
268
- // export let getRefCount = (value) => {
269
- // let userPtr = WasmI32.fromGrain(value)
270
- // let ret = if (WasmI32.eqz(userPtr & Tags._GRAIN_GENERIC_TAG_MASK) && WasmI32.ne(userPtr, 0n)) {
271
- // WasmI32.toGrain((getRefCount(userPtr) * 2n) + 1n) : Number
272
- // } else {
273
- // 0
274
- // }
275
- // decRef(userPtr)
276
- // ret
277
- // }
278
-
279
- // export let rec setDebug = (enabled: Bool) => {
280
- // _DEBUG = enabled
281
- // decRef(WasmI32.fromGrain(setDebug))
282
- // void
283
- // }
154
+ provide let decRef = userPtr => decRef(userPtr, false)
package/runtime/gc.md CHANGED
@@ -1,36 +1,32 @@
1
- ### Gc.**decimalCount32**
1
+ ---
2
+ title: GC
3
+ ---
2
4
 
3
- ```grain
4
- decimalCount32 : Box<WasmI32 -> WasmI32>
5
- ```
6
-
7
- ### Gc.**utoa32Buffered**
5
+ ## Values
8
6
 
9
- ```grain
10
- utoa32Buffered : Box<(WasmI32, WasmI32, WasmI32) -> Void>
11
- ```
7
+ Functions and constants included in the GC module.
12
8
 
13
- ### Gc.**malloc**
9
+ ### GC.**malloc**
14
10
 
15
11
  ```grain
16
- malloc : WasmI32 -> WasmI32
12
+ malloc : (size: WasmI32) => WasmI32
17
13
  ```
18
14
 
19
- ### Gc.**free**
15
+ ### GC.**free**
20
16
 
21
17
  ```grain
22
- free : WasmI32 -> Void
18
+ free : (userPtr: WasmI32) => Void
23
19
  ```
24
20
 
25
- ### Gc.**incRef**
21
+ ### GC.**incRef**
26
22
 
27
23
  ```grain
28
- incRef : WasmI32 -> WasmI32
24
+ incRef : (userPtr: WasmI32) => WasmI32
29
25
  ```
30
26
 
31
- ### Gc.**decRef**
27
+ ### GC.**decRef**
32
28
 
33
29
  ```grain
34
- decRef : WasmI32 -> WasmI32
30
+ decRef : (userPtr: WasmI32) => WasmI32
35
31
  ```
36
32