@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.
- package/CHANGELOG.md +21 -0
- package/array.gr +56 -1
- package/array.md +83 -0
- package/bigint.md +30 -30
- package/buffer.gr +24 -22
- package/float32.md +3 -3
- package/float64.md +3 -3
- package/immutablepriorityqueue.gr +332 -0
- package/immutablepriorityqueue.md +248 -0
- package/list.gr +73 -0
- package/list.md +110 -0
- package/map.gr +1 -2
- package/marshal.gr +1058 -0
- package/marshal.md +76 -0
- package/number.gr +41 -0
- package/number.md +80 -5
- package/package.json +1 -1
- package/pervasives.gr +16 -5
- package/pervasives.md +28 -0
- package/priorityqueue.gr +241 -0
- package/priorityqueue.md +279 -0
- package/regex.gr +5 -5
- package/runtime/compare.gr +178 -0
- package/runtime/compare.md +6 -0
- package/runtime/equal.gr +1 -2
- package/runtime/numbers.gr +307 -68
- package/runtime/numbers.md +24 -0
- package/set.gr +1 -2
- package/string.gr +97 -15
- package/string.md +65 -1
- package/sys/file.gr +3 -3
- package/sys/file.md +3 -3
- package/sys/process.gr +3 -3
- package/sys/process.md +3 -3
- package/sys/random.gr +2 -2
- package/sys/random.md +2 -2
- package/sys/time.gr +2 -2
- package/sys/time.md +2 -2
package/priorityqueue.md
ADDED
|
@@ -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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
+
}
|
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
|
|