@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/char.gr CHANGED
@@ -1,210 +1,196 @@
1
+ /**
2
+ * @module Char: Utilities for working with the Char type.
3
+ *
4
+ * The Char type represents a single [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value).
5
+ *
6
+ * @example import Char from "char"
7
+ *
8
+ * @since 0.3.0
9
+ */
10
+
1
11
  import WasmI32 from "runtime/unsafe/wasmi32"
2
- import Memory from "runtime/unsafe/memory"
3
12
  import Errors from "runtime/unsafe/errors"
4
- import { tagSimpleNumber, allocateChar, allocateString } from "runtime/dataStructures"
5
-
6
- export *
13
+ import Tags from "runtime/unsafe/tags"
14
+ import {
15
+ tagSimpleNumber,
16
+ tagChar,
17
+ untagChar,
18
+ allocateString,
19
+ } from "runtime/dataStructures"
7
20
 
8
21
  exception MalformedUtf8
9
22
 
10
- // The minimum value of Unicode characters
11
- // Number
12
- let min = 0x0000
13
-
14
- // The maximum value of Unicode characters
15
- // Number
16
- let max = 0x10FFFF
17
-
18
- // Returns true if the given number is a valid Unicode scalar value.
19
- // @param n: Number - the value to check
20
- // @returns Bool
21
- let isValid = (n) => {
22
- n >= min && (n <= 0xD7FF || n >= 0xE000) && n <= max
23
+ /**
24
+ * @section Values: Functions and constants included in the Char module.
25
+ */
26
+
27
+ /**
28
+ * The minimum valid Unicode scalar value.
29
+ *
30
+ * @since 0.3.0
31
+ */
32
+ export let min = 0x0000
33
+ /**
34
+ * The maximum valid Unicode scalar value.
35
+ *
36
+ * @since 0.3.0
37
+ */
38
+ export let max = 0x10FFFF
39
+
40
+ /**
41
+ * Determines whether the given character code is a valid Unicode scalar value.
42
+ *
43
+ * @param charCode: The number to check
44
+ * @returns `true` if the number refers to a valid Unicode scalar value or `false` otherwise
45
+ *
46
+ * @since 0.3.0
47
+ */
48
+ export let isValid = charCode => {
49
+ charCode >= min &&
50
+ (charCode <= 0xD7FF || charCode >= 0xE000) &&
51
+ charCode <= max
23
52
  }
24
53
 
25
- // Returns the Unicode code point for the character
26
- // @param char: Char - the input character
27
- // @returns Number
28
- @disableGC
29
- let rec code = (c: Char) => {
30
- // Algorithm from https://encoding.spec.whatwg.org/#utf-8-decoder
31
-
32
- let c = WasmI32.fromGrain(c)
54
+ /**
55
+ * Determines the Unicode scalar value for a character.
56
+ *
57
+ * @param char: The character
58
+ * @returns The Unicode scalar value for the given character
59
+ *
60
+ * @since 0.3.0
61
+ */
62
+ @unsafe
63
+ export let code = (char: Char) => {
64
+ let usv = untagChar(char)
65
+
66
+ // This could save an instruction by combining the two tagging operations,
67
+ // though we stick with tagSimpleNumber for simplicity.
68
+ tagSimpleNumber(usv)
69
+ }
33
70
 
34
- let (+) = WasmI32.add
35
- let (==) = WasmI32.eq
36
- let (>=) = WasmI32.geU
37
- let (<=) = WasmI32.leU
71
+ /**
72
+ * Creates a character from the given Unicode scalar value.
73
+ * Throws an exception if the Unicode scalar value is invalid.
74
+ *
75
+ * @param usv: The Unicode scalar value
76
+ * @returns The character for the given Unicode scalar value
77
+ *
78
+ * @since 0.3.0
79
+ */
80
+ @unsafe
81
+ export let fromCode = (usv: Number) => {
82
+ let (-) = WasmI32.sub
38
83
  let (<<) = WasmI32.shl
39
- let (&) = WasmI32.and
40
- let (|) = WasmI32.or
41
84
 
42
- let mut codePoint = 0n
43
- let mut bytesSeen = 0n
44
- let mut bytesNeeded = 0n
45
- let mut lowerBoundary = 0x80n
46
- let mut upperBoundary = 0xBFn
47
-
48
- let mut offset = 0n
49
-
50
- let mut result = 0n
51
-
52
- while (true) {
53
- let byte = WasmI32.load8U(c + offset, 4n)
54
- offset += 1n
55
- if (bytesNeeded == 0n) {
56
- if (byte >= 0x00n && byte <= 0x7Fn) {
57
- result = byte
58
- break
59
- } else if (byte >= 0xC2n && byte <= 0xDFn) {
60
- bytesNeeded = 1n
61
- codePoint = byte & 0x1Fn
62
- } else if (byte >= 0xE0n && byte <= 0xEFn) {
63
- if (byte == 0xE0n) lowerBoundary = 0xA0n
64
- if (byte == 0xEDn) upperBoundary = 0x9Fn
65
- bytesNeeded = 2n
66
- codePoint = byte & 0xFn
67
- } else if (byte >= 0xF0n && byte <= 0xF4n) {
68
- if (byte == 0xF0n) lowerBoundary = 0x90n
69
- if (byte == 0xF4n) upperBoundary = 0x8Fn
70
- bytesNeeded = 3n
71
- codePoint = byte & 0x7n
72
- } else {
73
- throw MalformedUtf8
74
- }
75
- continue
76
- }
77
- if (!(lowerBoundary <= byte && byte <= upperBoundary)) {
78
- throw MalformedUtf8
79
- }
80
- lowerBoundary = 0x80n
81
- upperBoundary = 0xBFn
82
- codePoint = (codePoint << 6n) | (byte & 0x3Fn)
83
- bytesSeen += 1n
84
- if (bytesSeen == bytesNeeded) {
85
- result = codePoint
86
- break
87
- }
85
+ if (!isValid(usv)) {
86
+ throw InvalidArgument("Invalid character code")
88
87
  }
89
88
 
90
- Memory.decRef(c)
91
- Memory.decRef(WasmI32.fromGrain(code))
92
- tagSimpleNumber(result)
89
+ // usv is now guaranteed to be a simple number
90
+ let usv = WasmI32.fromGrain(usv)
91
+
92
+ // Here we use a math trick to avoid fully untagging and retagging.
93
+ // Simple numbers are represented as 2n + 1 and chars are represented as
94
+ // 8n + 2. Quick reminder that shifting left is the equivalent of multiplying
95
+ // by 2, and that _GRAIN_CHAR_TAG_TYPE is equal to 2:
96
+ // 4(2n + 1) - 2 = 8n + 2
97
+ let char = (usv << 2n) - Tags._GRAIN_CHAR_TAG_TYPE
98
+
99
+ WasmI32.toGrain(char): Char
100
+ }
101
+
102
+ /**
103
+ * Returns the next valid character by Unicode scalar value.
104
+ * Throws if the input character is the max valid Unicode scalar value.
105
+ *
106
+ * @param char: The character
107
+ * @returns The next valid character by Unicode scalar value
108
+ *
109
+ * @since 0.3.0
110
+ */
111
+ export let succ = char => {
112
+ let codePoint = code(char)
113
+ if (codePoint == max) {
114
+ fail "no valid Unicode scalar value past U+10FFF"
115
+ } else if (codePoint == 0xD7FF) {
116
+ fromCode(0xE000)
117
+ } else {
118
+ fromCode(codePoint + 1)
119
+ }
93
120
  }
94
121
 
95
- // Returns the Char for the given code point. Fails if the code point is invalid.
96
- // @param codePoint: Number - the Unicode code point
97
- // @returns Char
98
- @disableGC
99
- let rec fromCode = (code: Number) => {
100
- // Algorithm from https://encoding.spec.whatwg.org/#utf-8-encoder
122
+ /**
123
+ * Returns the previous valid character by Unicode scalar value.
124
+ * Throws if the input character is the min valid Unicode scalar value.
125
+ *
126
+ * @param char: The character
127
+ * @returns The previous valid character by Unicode scalar value
128
+ *
129
+ * @since 0.3.0
130
+ */
131
+ export let pred = char => {
132
+ let codePoint = code(char)
133
+ if (codePoint == min) {
134
+ fail "no valid Unicode scalar value below U+0000"
135
+ } else if (codePoint == 0xE000) {
136
+ fromCode(0xD7FF)
137
+ } else {
138
+ fromCode(codePoint - 1)
139
+ }
140
+ }
101
141
 
142
+ /**
143
+ * Converts the given character to a string.
144
+ *
145
+ * @param char: The character to convert
146
+ * @returns A string containing the given character
147
+ *
148
+ * @since 0.3.0
149
+ */
150
+ @unsafe
151
+ export let toString = (char: Char) => {
102
152
  let (+) = WasmI32.add
103
153
  let (-) = WasmI32.sub
104
154
  let (*) = WasmI32.mul
105
- let (==) = WasmI32.eq
106
- let (>) = WasmI32.gtU
107
- let (<=) = WasmI32.leU
108
- let (<) = WasmI32.ltU
109
- let (>>>) = WasmI32.shrU
110
155
  let (&) = WasmI32.and
111
156
  let (|) = WasmI32.or
157
+ let (>>>) = WasmI32.shrU
158
+ let (<) = WasmI32.ltU
159
+ let (>) = WasmI32.gtU
160
+ let (<=) = WasmI32.leU
112
161
 
113
- let code = WasmI32.fromGrain(code)
114
- if ((code & 1n) == 0n) {
115
- throw InvalidArgument("Invalid character code")
116
- }
162
+ let usv = untagChar(char)
117
163
 
118
- let code = code >>> 1n
119
- let result = if (code < 0x80n) {
120
- let char = allocateChar()
121
- WasmI32.store8(char, code, 4n)
122
- WasmI32.toGrain(char): Char
164
+ let result = if (usv < 0x80n) {
165
+ let string = allocateString(1n)
166
+ WasmI32.store8(string, usv, 8n)
167
+ WasmI32.toGrain(string): String
123
168
  } else {
124
169
  let mut count = 0n
125
170
  let mut offset = 0n
126
- if (code <= 0x07FFn) {
171
+ if (usv <= 0x07FFn) {
127
172
  count = 1n
128
173
  offset = 0xC0n
129
- } else if (code <= 0xFFFFn) {
174
+ } else if (usv <= 0xFFFFn) {
130
175
  count = 2n
131
176
  offset = 0xE0n
132
177
  } else {
133
178
  count = 3n
134
179
  offset = 0xF0n
135
180
  }
136
- let char = allocateChar()
137
- WasmI32.store8(char, (code >>> (6n * count)) + offset, 4n)
181
+ let string = allocateString(count + 1n)
182
+ WasmI32.store8(string, (usv >>> 6n * count) + offset, 8n)
138
183
 
139
184
  let mut n = 0n
140
185
  while (count > 0n) {
141
186
  n += 1n
142
- let temp = code >>> (6n * (count - 1n))
143
- WasmI32.store8(char + n, 0x80n | (temp & 0x3Fn), 4n)
187
+ let temp = usv >>> 6n * (count - 1n)
188
+ WasmI32.store8(string + n, 0x80n | temp & 0x3Fn, 8n)
144
189
  count -= 1n
145
190
  }
146
191
 
147
- WasmI32.toGrain(char): Char
192
+ WasmI32.toGrain(string): String
148
193
  }
149
194
 
150
- // We've asserted that the original `code` was a stack allocated number so
151
- // no need to decRef it
152
- Memory.decRef(WasmI32.fromGrain(fromCode))
153
195
  result
154
196
  }
155
-
156
- // Returns the next valid Unicode character by code point. Fails if the input character is U+10FFFF.
157
- // @param char: Char - the input character
158
- // @returns Char
159
- let succ = (c) => {
160
- let codePoint = code(c)
161
- if (codePoint == max) {
162
- fail "no valid Unicode code point past U+10FFF"
163
- } else if (codePoint == 0xD7FF) {
164
- fromCode(0xE000)
165
- } else {
166
- fromCode(codePoint + 1)
167
- }
168
- }
169
-
170
- // Returns the previous valid Unicode character by code point. Fails if the input character is U+0000.
171
- // @param char: Char - the input character
172
- // @returns Char
173
- let pred = (c) => {
174
- let codePoint = code(c)
175
- if (codePoint == min) {
176
- fail "no valid Unicode code point below U+0000"
177
- } else if (codePoint == 0xE000) {
178
- fromCode(0xD7FF)
179
- } else {
180
- fromCode(codePoint - 1)
181
- }
182
- }
183
-
184
- // Creates a new string containing the character.
185
- // @param char: Char - the character to convert
186
- // @returns String
187
- @disableGC
188
- export let rec toString = (c: Char) => {
189
- let (+) = WasmI32.add
190
- let (&) = WasmI32.and
191
- let (==) = WasmI32.eq
192
-
193
- let c = WasmI32.fromGrain(c)
194
- let byte = WasmI32.load8U(c, 4n)
195
- let n = if ((byte & 0x80n) == 0x00n) {
196
- 1n
197
- } else if ((byte & 0xF0n) == 0xF0n) {
198
- 4n
199
- } else if ((byte & 0xE0n) == 0xE0n) {
200
- 3n
201
- } else {
202
- 2n
203
- }
204
- let str = allocateString(n)
205
- Memory.copy(str + 8n, c + 4n, n)
206
- let ret = WasmI32.toGrain(str): String
207
- Memory.decRef(WasmI32.fromGrain(c))
208
- Memory.decRef(WasmI32.fromGrain(toString))
209
- ret
210
- }
package/char.md ADDED
@@ -0,0 +1,200 @@
1
+ ---
2
+ title: Char
3
+ ---
4
+
5
+ Utilities for working with the Char type.
6
+
7
+ The Char type represents a single [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value).
8
+
9
+ <details disabled>
10
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
11
+ No other changes yet.
12
+ </details>
13
+
14
+ ```grain
15
+ import Char from "char"
16
+ ```
17
+
18
+ ## Values
19
+
20
+ Functions and constants included in the Char module.
21
+
22
+ ### Char.**min**
23
+
24
+ <details disabled>
25
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
26
+ No other changes yet.
27
+ </details>
28
+
29
+ ```grain
30
+ min : Number
31
+ ```
32
+
33
+ The minimum valid Unicode scalar value.
34
+
35
+ ### Char.**max**
36
+
37
+ <details disabled>
38
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
39
+ No other changes yet.
40
+ </details>
41
+
42
+ ```grain
43
+ max : Number
44
+ ```
45
+
46
+ The maximum valid Unicode scalar value.
47
+
48
+ ### Char.**isValid**
49
+
50
+ <details disabled>
51
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
52
+ No other changes yet.
53
+ </details>
54
+
55
+ ```grain
56
+ isValid : Number -> Bool
57
+ ```
58
+
59
+ Determines whether the given character code is a valid Unicode scalar value.
60
+
61
+ Parameters:
62
+
63
+ |param|type|description|
64
+ |-----|----|-----------|
65
+ |`charCode`|`Number`|The number to check|
66
+
67
+ Returns:
68
+
69
+ |type|description|
70
+ |----|-----------|
71
+ |`Bool`|`true` if the number refers to a valid Unicode scalar value or `false` otherwise|
72
+
73
+ ### Char.**code**
74
+
75
+ <details disabled>
76
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
77
+ No other changes yet.
78
+ </details>
79
+
80
+ ```grain
81
+ code : Char -> Number
82
+ ```
83
+
84
+ Determines the Unicode scalar value for a character.
85
+
86
+ Parameters:
87
+
88
+ |param|type|description|
89
+ |-----|----|-----------|
90
+ |`char`|`Char`|The character|
91
+
92
+ Returns:
93
+
94
+ |type|description|
95
+ |----|-----------|
96
+ |`Number`|The Unicode scalar value for the given character|
97
+
98
+ ### Char.**fromCode**
99
+
100
+ <details disabled>
101
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
102
+ No other changes yet.
103
+ </details>
104
+
105
+ ```grain
106
+ fromCode : Number -> Char
107
+ ```
108
+
109
+ Creates a character from the given Unicode scalar value.
110
+ Throws an exception if the Unicode scalar value is invalid.
111
+
112
+ Parameters:
113
+
114
+ |param|type|description|
115
+ |-----|----|-----------|
116
+ |`usv`|`Number`|The Unicode scalar value|
117
+
118
+ Returns:
119
+
120
+ |type|description|
121
+ |----|-----------|
122
+ |`Char`|The character for the given Unicode scalar value|
123
+
124
+ ### Char.**succ**
125
+
126
+ <details disabled>
127
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
128
+ No other changes yet.
129
+ </details>
130
+
131
+ ```grain
132
+ succ : Char -> Char
133
+ ```
134
+
135
+ Returns the next valid character by Unicode scalar value.
136
+ Throws if the input character is the max valid Unicode scalar value.
137
+
138
+ Parameters:
139
+
140
+ |param|type|description|
141
+ |-----|----|-----------|
142
+ |`char`|`Char`|The character|
143
+
144
+ Returns:
145
+
146
+ |type|description|
147
+ |----|-----------|
148
+ |`Char`|The next valid character by Unicode scalar value|
149
+
150
+ ### Char.**pred**
151
+
152
+ <details disabled>
153
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
154
+ No other changes yet.
155
+ </details>
156
+
157
+ ```grain
158
+ pred : Char -> Char
159
+ ```
160
+
161
+ Returns the previous valid character by Unicode scalar value.
162
+ Throws if the input character is the min valid Unicode scalar value.
163
+
164
+ Parameters:
165
+
166
+ |param|type|description|
167
+ |-----|----|-----------|
168
+ |`char`|`Char`|The character|
169
+
170
+ Returns:
171
+
172
+ |type|description|
173
+ |----|-----------|
174
+ |`Char`|The previous valid character by Unicode scalar value|
175
+
176
+ ### Char.**toString**
177
+
178
+ <details disabled>
179
+ <summary tabindex="-1">Added in <code>0.3.0</code></summary>
180
+ No other changes yet.
181
+ </details>
182
+
183
+ ```grain
184
+ toString : Char -> String
185
+ ```
186
+
187
+ Converts the given character to a string.
188
+
189
+ Parameters:
190
+
191
+ |param|type|description|
192
+ |-----|----|-----------|
193
+ |`char`|`Char`|The character to convert|
194
+
195
+ Returns:
196
+
197
+ |type|description|
198
+ |----|-----------|
199
+ |`String`|A string containing the given character|
200
+
package/exception.md ADDED
@@ -0,0 +1,6 @@
1
+ ### Exception.**registerPrinter**
2
+
3
+ ```grain
4
+ registerPrinter : (Exception -> Option<String>) -> Void
5
+ ```
6
+