@grain/stdlib 0.5.2 → 0.5.3

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.
@@ -0,0 +1,279 @@
1
+ ---
2
+ title: PriorityQueue
3
+ ---
4
+
5
+ A mutable priority queue implementation. A priority queue is a data structure that maintains elements in a priority order. Elements with higher priority are served before elements with lower priority when extracting from the priority queue.
6
+
7
+ <details disabled>
8
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
9
+ No other changes yet.
10
+ </details>
11
+
12
+ ```grain
13
+ import PriorityQueue from "priorityqueue"
14
+ ```
15
+
16
+ ## Types
17
+
18
+ Type declarations included in the PriorityQueue module.
19
+
20
+ ### PriorityQueue.**PriorityQueue**
21
+
22
+ ```grain
23
+ type PriorityQueue<a>
24
+ ```
25
+
26
+ Mutable data structure which maintains a priority order for its elements.
27
+
28
+ ## Values
29
+
30
+ Functions for working with PriorityQueues.
31
+
32
+ ### PriorityQueue.**makeSized**
33
+
34
+ <details disabled>
35
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
36
+ No other changes yet.
37
+ </details>
38
+
39
+ ```grain
40
+ makeSized : (Number, ((a, a) -> Number)) -> PriorityQueue<a>
41
+ ```
42
+
43
+ Creates a new priority queue with a given internal storage size and a
44
+ comparator function, which is used to determine priority of elements. The
45
+ comparator function takes two elements and must return 0 if both share
46
+ priority, a positive number if the first has greater priority, and a
47
+ negative number if the first has less priority.
48
+
49
+ Generally, you won't need to care about the storage size of your priority
50
+ queue and can use `PriorityQueue.make()` instead.
51
+
52
+ Parameters:
53
+
54
+ |param|type|description|
55
+ |-----|----|-----------|
56
+ |`size`|`Number`|The initial storage size of the priority queue|
57
+ |`comp`|`(a, a) -> Number`|The comparator function used to indicate priority order|
58
+
59
+ Returns:
60
+
61
+ |type|description|
62
+ |----|-----------|
63
+ |`PriorityQueue<a>`|An empty priority queue|
64
+
65
+ ### PriorityQueue.**make**
66
+
67
+ <details disabled>
68
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
69
+ No other changes yet.
70
+ </details>
71
+
72
+ ```grain
73
+ make : ((a, a) -> Number) -> PriorityQueue<a>
74
+ ```
75
+
76
+ Creates a new priority queue with a comparator function, which is used to
77
+ determine priority of elements. The comparator function takes two elements
78
+ and must return 0 if both share priority, a positive number if the first
79
+ has greater priority, and a negative number if the first has less priority.
80
+
81
+ Parameters:
82
+
83
+ |param|type|description|
84
+ |-----|----|-----------|
85
+ |`comp`|`(a, a) -> Number`|The comparator function used to indicate priority order|
86
+
87
+ Returns:
88
+
89
+ |type|description|
90
+ |----|-----------|
91
+ |`PriorityQueue<a>`|An empty priority queue|
92
+
93
+ Examples:
94
+
95
+ ```grain
96
+ PriorityQueue.make(compare) // creates a min priority queue of numbers using the compare pervasive
97
+ ```
98
+
99
+ ```grain
100
+ PriorityQueue.make((a, b) => String.length(b) - String.length(a)) // creates a priority queue by string length (longest to shortest)
101
+ ```
102
+
103
+ ### PriorityQueue.**size**
104
+
105
+ <details disabled>
106
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
107
+ No other changes yet.
108
+ </details>
109
+
110
+ ```grain
111
+ size : PriorityQueue<a> -> Number
112
+ ```
113
+
114
+ Gets the number of elements in a priority queue.
115
+
116
+ Parameters:
117
+
118
+ |param|type|description|
119
+ |-----|----|-----------|
120
+ |`pq`|`PriorityQueue<a>`|The priority queue to inspect|
121
+
122
+ Returns:
123
+
124
+ |type|description|
125
+ |----|-----------|
126
+ |`Number`|The number of elements in the priority queue|
127
+
128
+ ### PriorityQueue.**isEmpty**
129
+
130
+ <details disabled>
131
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
132
+ No other changes yet.
133
+ </details>
134
+
135
+ ```grain
136
+ isEmpty : PriorityQueue<a> -> Bool
137
+ ```
138
+
139
+ Determines if the priority queue contains no elements.
140
+
141
+ Parameters:
142
+
143
+ |param|type|description|
144
+ |-----|----|-----------|
145
+ |`pq`|`PriorityQueue<a>`|The priority queue to check|
146
+
147
+ Returns:
148
+
149
+ |type|description|
150
+ |----|-----------|
151
+ |`Bool`|`true` if the priority queue is empty and `false` otherwise|
152
+
153
+ ### PriorityQueue.**push**
154
+
155
+ <details disabled>
156
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
157
+ No other changes yet.
158
+ </details>
159
+
160
+ ```grain
161
+ push : (a, PriorityQueue<a>) -> Void
162
+ ```
163
+
164
+ Adds a new element to the priority queue.
165
+
166
+ Parameters:
167
+
168
+ |param|type|description|
169
+ |-----|----|-----------|
170
+ |`val`|`a`|The value to add into the priority queue|
171
+ |`pq`|`PriorityQueue<a>`|The priority queue to update|
172
+
173
+ ### PriorityQueue.**peek**
174
+
175
+ <details disabled>
176
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
177
+ No other changes yet.
178
+ </details>
179
+
180
+ ```grain
181
+ peek : PriorityQueue<a> -> Option<a>
182
+ ```
183
+
184
+ Retrieves the highest priority element in the priority queue. It is not
185
+ removed from the queue.
186
+
187
+ Parameters:
188
+
189
+ |param|type|description|
190
+ |-----|----|-----------|
191
+ |`pq`|`PriorityQueue<a>`|The priority queue to inspect|
192
+
193
+ Returns:
194
+
195
+ |type|description|
196
+ |----|-----------|
197
+ |`Option<a>`|`Some(value)` containing the highest priority element or `None` if the priority queue is empty|
198
+
199
+ ### PriorityQueue.**pop**
200
+
201
+ <details disabled>
202
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
203
+ No other changes yet.
204
+ </details>
205
+
206
+ ```grain
207
+ pop : PriorityQueue<a> -> Option<a>
208
+ ```
209
+
210
+ Removes and retrieves the highest priority element in the priority queue.
211
+
212
+ Parameters:
213
+
214
+ |param|type|description|
215
+ |-----|----|-----------|
216
+ |`pq`|`PriorityQueue<a>`|The priority queue to inspect|
217
+
218
+ Returns:
219
+
220
+ |type|description|
221
+ |----|-----------|
222
+ |`Option<a>`|`Some(value)` containing the highest priority element or `None` if the priority queue is empty|
223
+
224
+ ### PriorityQueue.**drain**
225
+
226
+ <details disabled>
227
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
228
+ No other changes yet.
229
+ </details>
230
+
231
+ ```grain
232
+ drain : PriorityQueue<a> -> List<a>
233
+ ```
234
+
235
+ Clears the priority queue and produces a list of all of the elements in the priority
236
+ queue in priority order.
237
+
238
+ Parameters:
239
+
240
+ |param|type|description|
241
+ |-----|----|-----------|
242
+ |`pq`|`PriorityQueue<a>`|The priority queue to drain|
243
+
244
+ Returns:
245
+
246
+ |type|description|
247
+ |----|-----------|
248
+ |`List<a>`|A list of all elements in the priority in priority order|
249
+
250
+ ### PriorityQueue.**fromList**
251
+
252
+ <details disabled>
253
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
254
+ No other changes yet.
255
+ </details>
256
+
257
+ ```grain
258
+ fromList : (List<a>, ((a, a) -> Number)) -> PriorityQueue<a>
259
+ ```
260
+
261
+ Constructs a new priority queue initialized with the elements in the list
262
+ using a custom comparator function, which is used to determine priority of
263
+ elements. The comparator function takes two elements and must return 0 if
264
+ both share priority, a positive number if the first has greater priority,
265
+ and a negative number if the first has less priority.
266
+
267
+ Parameters:
268
+
269
+ |param|type|description|
270
+ |-----|----|-----------|
271
+ |`list`|`List<a>`|A list of values used to initialize the priority queue|
272
+ |`comp`|`(a, a) -> Number`|A comparator function used to assign priority to elements|
273
+
274
+ Returns:
275
+
276
+ |type|description|
277
+ |----|-----------|
278
+ |`PriorityQueue<a>`|A priority queue containing the elements from the list|
279
+
package/regex.gr CHANGED
@@ -487,7 +487,7 @@ enum MergeMode {
487
487
  }
488
488
 
489
489
  let mergeAdjacent = lst => {
490
- // see [TODO] below
490
+ // TODO: see below
491
491
  let readyForAccum = (l, mode) => {
492
492
  match (l) {
493
493
  [] => true,
@@ -512,7 +512,7 @@ let mergeAdjacent = lst => {
512
512
  // drop empty elements
513
513
  [REEmpty, ...tl] => loop(mode, accum, tl),
514
514
  [RELiteralString(""), ...tl] => loop(mode, accum, tl),
515
- // [TODO] Clean up with or-patterns (grain-lang/grain#696)
515
+ // TODO(#696): Clean up with or-patterns
516
516
  _ when readyForAccum(l, mode) => {
517
517
  match (accum) {
518
518
  [] => [],
@@ -592,7 +592,7 @@ REGEX PARSING DEFINITIONS
592
592
 
593
593
  // Range parsing ("[a-z]")
594
594
 
595
- // [TODO] (#769) When byte-based regexes are supported, we'll need another limit of 255 for those.
595
+ // TODO(#769): When byte-based regexes are supported, we'll need another limit of 255 for those.
596
596
  let rangeLimit = 0x10FFFF
597
597
 
598
598
  // These are snake-cased to avoid confusion with their capitalized counterparts
@@ -1578,7 +1578,7 @@ let rec parseAtom = (buf: RegExBuf) => {
1578
1578
  Err(
1579
1579
  parseErr(buf, "unmatched `" ++ Char.toString(c) ++ "` in pattern", 0)
1580
1580
  ),
1581
- // [TODO] case-insensitive (#691)
1581
+ // TODO(#691): Enable case-insensitive regular expression matching
1582
1582
  Ok(c) when buf.config.caseSensitive => {
1583
1583
  ignore(next(buf))
1584
1584
  Ok(RELiteral(c))
@@ -3320,7 +3320,7 @@ record RegularExpression {
3320
3320
  * @section Values: Functions for working with regular expressions.
3321
3321
  */
3322
3322
 
3323
- // [TODO] When #661 is resolved, re-add the following pieces of documentation:
3323
+ // TODO(#661): re-add the following pieces of documentation:
3324
3324
  /*
3325
3325
  [Under POSIX character classes]
3326
3326
 
@@ -0,0 +1,178 @@
1
+ /* grainc-flags --no-pervasives */
2
+
3
+ import WasmI32, {
4
+ eq as (==),
5
+ ne as (!=),
6
+ and as (&),
7
+ xor as (^),
8
+ or as (|),
9
+ add as (+),
10
+ sub as (-),
11
+ mul as (*),
12
+ ltS as (<),
13
+ gtS as (>),
14
+ remS as (%),
15
+ shl as (<<),
16
+ shrU as (>>>),
17
+ } from "runtime/unsafe/wasmi32"
18
+ import WasmI64 from "runtime/unsafe/wasmi64"
19
+ import Memory from "runtime/unsafe/memory"
20
+ import Tags from "runtime/unsafe/tags"
21
+ import { tagSimpleNumber } from "runtime/dataStructures"
22
+ import { isNumber, cmp as numberCompare } from "runtime/numbers"
23
+
24
+ primitive (!): Bool -> Bool = "@not"
25
+ primitive (||): (Bool, Bool) -> Bool = "@or"
26
+ primitive (&&): (Bool, Bool) -> Bool = "@and"
27
+
28
+ @unsafe
29
+ let zero = WasmI32.fromGrain(0)
30
+
31
+ @unsafe
32
+ let rec heapCompareHelp = (heapTag, xptr, yptr) => {
33
+ match (heapTag) {
34
+ t when t == Tags._GRAIN_ADT_HEAP_TAG => {
35
+ // Check if the same constructor variant
36
+ let xvariant = WasmI32.load(xptr, 12n)
37
+ let yvariant = WasmI32.load(yptr, 12n)
38
+ if (xvariant != yvariant) {
39
+ tagSimpleNumber(xvariant - yvariant)
40
+ } else {
41
+ let xarity = WasmI32.load(xptr, 16n)
42
+ let yarity = WasmI32.load(yptr, 16n)
43
+
44
+ let mut result = 0
45
+
46
+ let bytes = xarity * 4n
47
+ for (let mut i = 0n; i < bytes; i += 4n) {
48
+ let sub = compareHelp(
49
+ WasmI32.load(xptr + i, 20n),
50
+ WasmI32.load(yptr + i, 20n)
51
+ )
52
+ if (WasmI32.fromGrain(sub) != zero) {
53
+ result = sub
54
+ break
55
+ }
56
+ }
57
+
58
+ result
59
+ }
60
+ },
61
+ t when t == Tags._GRAIN_RECORD_HEAP_TAG => {
62
+ let xlength = WasmI32.load(xptr, 12n)
63
+ let ylength = WasmI32.load(yptr, 12n)
64
+
65
+ let mut result = 0
66
+
67
+ let bytes = xlength * 4n
68
+ for (let mut i = 0n; i < bytes; i += 4n) {
69
+ let sub = compareHelp(
70
+ WasmI32.load(xptr + i, 16n),
71
+ WasmI32.load(yptr + i, 16n)
72
+ )
73
+ if (WasmI32.fromGrain(sub) != zero) {
74
+ result = sub
75
+ break
76
+ }
77
+ }
78
+
79
+ result
80
+ },
81
+ t when t == Tags._GRAIN_ARRAY_HEAP_TAG => {
82
+ let xlength = WasmI32.load(xptr, 4n)
83
+ let ylength = WasmI32.load(yptr, 4n)
84
+
85
+ // Check if the same length
86
+ if (xlength != ylength) {
87
+ tagSimpleNumber(xlength - ylength)
88
+ } else {
89
+ let mut result = 0
90
+ let bytes = xlength * 4n
91
+ for (let mut i = 0n; i < bytes; i += 4n) {
92
+ let sub = compareHelp(
93
+ WasmI32.load(xptr + i, 8n),
94
+ WasmI32.load(yptr + i, 8n)
95
+ )
96
+ if (WasmI32.fromGrain(sub) != zero) {
97
+ result = sub
98
+ break
99
+ }
100
+ }
101
+
102
+ result
103
+ }
104
+ },
105
+ t when (
106
+ t == Tags._GRAIN_STRING_HEAP_TAG || t == Tags._GRAIN_BYTES_HEAP_TAG
107
+ ) => {
108
+ let xlength = WasmI32.load(xptr, 4n)
109
+ let ylength = WasmI32.load(yptr, 4n)
110
+
111
+ if (xlength == ylength) {
112
+ tagSimpleNumber(Memory.compare(xptr + 8n, yptr + 8n, xlength))
113
+ } else {
114
+ if (xlength < ylength) {
115
+ let sub = Memory.compare(xptr + 8n, yptr + 8n, xlength)
116
+ // The shorter one comes first
117
+ if (sub == 0n) -1 else tagSimpleNumber(sub)
118
+ } else {
119
+ let sub = Memory.compare(xptr + 8n, yptr + 8n, ylength)
120
+ // The shorter one comes first
121
+ if (sub == 0n) 1 else tagSimpleNumber(sub)
122
+ }
123
+ }
124
+ },
125
+ t when t == Tags._GRAIN_TUPLE_HEAP_TAG => {
126
+ let xsize = WasmI32.load(xptr, 4n)
127
+ let ysize = WasmI32.load(yptr, 4n)
128
+
129
+ let mut result = 0
130
+ let bytes = xsize * 4n
131
+ for (let mut i = 0n; i < bytes; i += 4n) {
132
+ let sub = compareHelp(
133
+ WasmI32.load(xptr + i, 8n),
134
+ WasmI32.load(yptr + i, 8n)
135
+ )
136
+ if (WasmI32.fromGrain(sub) != zero) {
137
+ result = sub
138
+ break
139
+ }
140
+ }
141
+
142
+ result
143
+ },
144
+ _ => {
145
+ // No other implementation
146
+ tagSimpleNumber(xptr - yptr)
147
+ },
148
+ }
149
+ }, compareHelp = (x, y) => {
150
+ let xtag = x & Tags._GRAIN_GENERIC_TAG_MASK
151
+ let ytag = y & Tags._GRAIN_GENERIC_TAG_MASK
152
+ if ((xtag & ytag) != Tags._GRAIN_GENERIC_HEAP_TAG_TYPE) {
153
+ // Short circuit for non-pointer values
154
+ if ((xtag & Tags._GRAIN_NUMBER_TAG_MASK) == Tags._GRAIN_NUMBER_TAG_TYPE) {
155
+ // Signed comparisons are necessary for numbers
156
+ if (x < y) -1 else if (x > y) 1 else 0
157
+ } else {
158
+ // Unsigned comparisons are necessary for other stack-allocated values
159
+ if (WasmI32.ltU(x, y)) -1 else if (WasmI32.gtU(x, y)) 1 else 0
160
+ }
161
+ } else if (isNumber(x)) {
162
+ // Numbers have special comparison rules, e.g. NaN == NaN
163
+ tagSimpleNumber(numberCompare(x, y, true))
164
+ } else {
165
+ // Handle all other heap allocated things
166
+ // Can short circuit if pointers are the same
167
+ if (x == y) {
168
+ 0
169
+ } else {
170
+ heapCompareHelp(WasmI32.load(x, 0n), x, y)
171
+ }
172
+ }
173
+ }
174
+
175
+ @unsafe
176
+ export let compare = (x: a, y: a) => {
177
+ compareHelp(WasmI32.fromGrain(x), WasmI32.fromGrain(y))
178
+ }
@@ -0,0 +1,6 @@
1
+ ### Compare.**compare**
2
+
3
+ ```grain
4
+ compare : (a, a) -> Number
5
+ ```
6
+
package/runtime/equal.gr CHANGED
@@ -14,13 +14,12 @@ import WasmI32, {
14
14
  } from "runtime/unsafe/wasmi32"
15
15
  import WasmI64 from "runtime/unsafe/wasmi64"
16
16
  import Tags from "runtime/unsafe/tags"
17
+ import { isNumber, numberEqual } from "runtime/numbers"
17
18
 
18
19
  primitive (!): Bool -> Bool = "@not"
19
20
  primitive (||): (Bool, Bool) -> Bool = "@or"
20
21
  primitive (&&): (Bool, Bool) -> Bool = "@and"
21
22
 
22
- import { isNumber, numberEqual } from "runtime/numbers"
23
-
24
23
  @unsafe
25
24
  let cycleMarker = 0x80000000n
26
25