@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.
- package/CHANGELOG.md +87 -0
- package/LICENSE +1 -1
- package/array.gr +92 -73
- package/array.md +18 -18
- package/bigint.gr +497 -0
- package/bigint.md +811 -0
- package/buffer.gr +56 -217
- package/buffer.md +24 -17
- package/bytes.gr +103 -205
- package/bytes.md +19 -0
- package/char.gr +152 -166
- package/char.md +200 -0
- package/exception.md +6 -0
- package/float32.gr +159 -82
- package/float32.md +315 -0
- package/float64.gr +163 -82
- package/float64.md +315 -0
- package/hash.gr +53 -49
- package/int32.gr +479 -230
- package/int32.md +937 -0
- package/int64.gr +479 -230
- package/int64.md +937 -0
- package/list.gr +530 -116
- package/list.md +1141 -0
- package/map.gr +302 -121
- package/map.md +525 -0
- package/number.gr +51 -57
- package/number.md +37 -3
- package/option.gr +25 -25
- package/option.md +1 -1
- package/package.json +3 -3
- package/pervasives.gr +504 -52
- package/pervasives.md +1116 -0
- package/queue.gr +8 -1
- package/queue.md +10 -0
- package/random.gr +196 -0
- package/random.md +179 -0
- package/range.gr +26 -26
- package/regex.gr +1833 -842
- package/regex.md +11 -11
- package/result.md +1 -1
- package/runtime/bigint.gr +2045 -0
- package/runtime/bigint.md +326 -0
- package/runtime/dataStructures.gr +99 -279
- package/runtime/dataStructures.md +391 -0
- package/runtime/debug.gr +0 -1
- package/runtime/debug.md +6 -0
- package/runtime/equal.gr +40 -37
- package/runtime/equal.md +6 -0
- package/runtime/exception.gr +28 -15
- package/runtime/exception.md +30 -0
- package/runtime/gc.gr +50 -20
- package/runtime/gc.md +36 -0
- package/runtime/malloc.gr +32 -22
- package/runtime/malloc.md +55 -0
- package/runtime/numberUtils.gr +297 -142
- package/runtime/numberUtils.md +54 -0
- package/runtime/numbers.gr +1204 -453
- package/runtime/numbers.md +300 -0
- package/runtime/string.gr +193 -228
- package/runtime/string.md +24 -0
- package/runtime/stringUtils.gr +62 -38
- package/runtime/stringUtils.md +6 -0
- package/runtime/unsafe/constants.gr +17 -0
- package/runtime/unsafe/constants.md +72 -0
- package/runtime/unsafe/conv.gr +10 -10
- package/runtime/unsafe/conv.md +71 -0
- package/runtime/unsafe/errors.md +204 -0
- package/runtime/unsafe/memory.gr +14 -3
- package/runtime/unsafe/memory.md +54 -0
- package/runtime/unsafe/printWasm.gr +4 -4
- package/runtime/unsafe/printWasm.md +24 -0
- package/runtime/unsafe/tags.gr +11 -10
- package/runtime/unsafe/tags.md +120 -0
- package/runtime/unsafe/wasmf32.gr +9 -2
- package/runtime/unsafe/wasmf32.md +168 -0
- package/runtime/unsafe/wasmf64.gr +9 -2
- package/runtime/unsafe/wasmf64.md +168 -0
- package/runtime/unsafe/wasmi32.gr +65 -47
- package/runtime/unsafe/wasmi32.md +282 -0
- package/runtime/unsafe/wasmi64.gr +78 -50
- package/runtime/unsafe/wasmi64.md +300 -0
- package/runtime/utils/printing.gr +62 -0
- package/runtime/utils/printing.md +18 -0
- package/runtime/wasi.gr +200 -46
- package/runtime/wasi.md +839 -0
- package/set.gr +125 -121
- package/set.md +24 -21
- package/stack.gr +29 -29
- package/stack.md +4 -6
- package/string.gr +434 -415
- package/string.md +3 -3
- package/sys/file.gr +477 -482
- package/sys/process.gr +33 -47
- package/sys/random.gr +48 -20
- package/sys/random.md +38 -0
- package/sys/time.gr +12 -28
package/runtime/string.gr
CHANGED
|
@@ -7,6 +7,7 @@ import WasmI32, {
|
|
|
7
7
|
divS as (/),
|
|
8
8
|
shl as (<<),
|
|
9
9
|
shrS as (>>),
|
|
10
|
+
shrU as (>>>),
|
|
10
11
|
and as (&),
|
|
11
12
|
or as (|),
|
|
12
13
|
eq as (==),
|
|
@@ -14,44 +15,37 @@ import WasmI32, {
|
|
|
14
15
|
geS as (>=),
|
|
15
16
|
gtS as (>),
|
|
16
17
|
leS as (<=),
|
|
17
|
-
ltS as (<)
|
|
18
|
+
ltS as (<),
|
|
18
19
|
} from "runtime/unsafe/wasmi32"
|
|
19
20
|
import WasmI64 from "runtime/unsafe/wasmi64"
|
|
20
21
|
import WasmF32 from "runtime/unsafe/wasmf32"
|
|
21
22
|
import WasmF64 from "runtime/unsafe/wasmf64"
|
|
23
|
+
import BI from "runtime/bigint"
|
|
22
24
|
import Memory from "runtime/unsafe/memory"
|
|
23
25
|
import Tags from "runtime/unsafe/tags"
|
|
24
26
|
import NumberUtils from "runtime/numberUtils"
|
|
25
27
|
|
|
26
28
|
import { allocateString, allocateArray } from "runtime/dataStructures"
|
|
27
29
|
|
|
28
|
-
import foreign wasm fd_write: (
|
|
30
|
+
import foreign wasm fd_write: (
|
|
31
|
+
WasmI32,
|
|
32
|
+
WasmI32,
|
|
33
|
+
WasmI32,
|
|
34
|
+
WasmI32,
|
|
35
|
+
) -> WasmI32 from "wasi_snapshot_preview1"
|
|
29
36
|
|
|
30
|
-
primitive (!)
|
|
31
|
-
primitive (&&)
|
|
32
|
-
primitive (||)
|
|
37
|
+
primitive (!): Bool -> Bool = "@not"
|
|
38
|
+
primitive (&&): (Bool, Bool) -> Bool = "@and"
|
|
39
|
+
primitive (||): (Bool, Bool) -> Bool = "@or"
|
|
33
40
|
|
|
34
|
-
enum StringList {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
let slConsDisableGc = (a, b) => {
|
|
38
|
-
Memory.incRef(WasmI32.fromGrain(SLCons))
|
|
39
|
-
Memory.incRef(WasmI32.fromGrain(a))
|
|
40
|
-
// for easier chaining, we don't incRef `b`
|
|
41
|
-
SLCons(a, b)
|
|
41
|
+
enum StringList {
|
|
42
|
+
[],
|
|
43
|
+
[...](String, StringList),
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
@
|
|
45
|
-
let mut _RUNTIME_TYPE_METADATA_PTR = 0x01n;
|
|
46
|
-
|
|
47
|
-
@disableGC
|
|
48
|
-
let initPtr = () => {
|
|
49
|
-
// hack to avoid incRef on this pointer
|
|
50
|
-
_RUNTIME_TYPE_METADATA_PTR = 0x408n
|
|
51
|
-
}
|
|
52
|
-
initPtr();
|
|
46
|
+
primitive _RUNTIME_TYPE_METADATA_PTR: WasmI32 = "@heap.type_metadata"
|
|
53
47
|
|
|
54
|
-
@
|
|
48
|
+
@unsafe
|
|
55
49
|
let findTypeMetadata = (moduleId, typeId) => {
|
|
56
50
|
let mut metadataPtr = WasmI32.load(_RUNTIME_TYPE_METADATA_PTR, 0n)
|
|
57
51
|
let mut modData = -1n
|
|
@@ -81,8 +75,8 @@ let findTypeMetadata = (moduleId, typeId) => {
|
|
|
81
75
|
}
|
|
82
76
|
}
|
|
83
77
|
|
|
84
|
-
@
|
|
85
|
-
let getVariantName =
|
|
78
|
+
@unsafe
|
|
79
|
+
let getVariantName = variant => {
|
|
86
80
|
let moduleId = WasmI32.load(variant, 4n) >> 1n
|
|
87
81
|
let typeId = WasmI32.load(variant, 8n) >> 1n
|
|
88
82
|
let variantId = WasmI32.load(variant, 12n) >> 1n
|
|
@@ -112,8 +106,8 @@ let getVariantName = (variant) => {
|
|
|
112
106
|
}
|
|
113
107
|
}
|
|
114
108
|
|
|
115
|
-
@
|
|
116
|
-
let getRecordFieldNames =
|
|
109
|
+
@unsafe
|
|
110
|
+
let getRecordFieldNames = record_ => {
|
|
117
111
|
let moduleId = WasmI32.load(record_, 4n) >> 1n
|
|
118
112
|
let typeId = WasmI32.load(record_, 8n) >> 1n
|
|
119
113
|
let arity = WasmI32.load(record_, 12n)
|
|
@@ -131,8 +125,9 @@ let getRecordFieldNames = (record_) => {
|
|
|
131
125
|
for (let mut i = 0n; i < arity; i += 1n) {
|
|
132
126
|
let fieldLength = WasmI32.load(fields + fieldOffset, 4n)
|
|
133
127
|
let fieldName = allocateString(fieldLength)
|
|
128
|
+
Memory.incRef(fieldName)
|
|
134
129
|
Memory.copy(fieldName + 8n, fields + fieldOffset + 8n, fieldLength)
|
|
135
|
-
WasmI32.store(fieldArray +
|
|
130
|
+
WasmI32.store(fieldArray + i * 4n, fieldName, 8n)
|
|
136
131
|
|
|
137
132
|
fieldOffset += WasmI32.load(fields + fieldOffset, 0n)
|
|
138
133
|
}
|
|
@@ -141,50 +136,50 @@ let getRecordFieldNames = (record_) => {
|
|
|
141
136
|
}
|
|
142
137
|
}
|
|
143
138
|
|
|
144
|
-
@
|
|
139
|
+
@unsafe
|
|
145
140
|
let rec totalBytes = (acc, list) => {
|
|
146
141
|
match (list) {
|
|
147
|
-
|
|
148
|
-
|
|
142
|
+
[hd, ...tl] =>
|
|
143
|
+
totalBytes(acc + WasmI32.load(WasmI32.fromGrain(hd), 4n), tl),
|
|
144
|
+
[] => acc,
|
|
149
145
|
}
|
|
150
146
|
}
|
|
151
147
|
|
|
152
|
-
@
|
|
148
|
+
@unsafe
|
|
153
149
|
let rec writeStrings = (buf, list) => {
|
|
154
150
|
match (list) {
|
|
155
|
-
|
|
151
|
+
[hd, ...tl] => {
|
|
156
152
|
let hd = WasmI32.fromGrain(hd)
|
|
157
153
|
let hdSize = WasmI32.load(hd, 4n)
|
|
158
154
|
Memory.copy(buf, hd + 8n, hdSize)
|
|
159
155
|
writeStrings(buf + hdSize, tl)
|
|
160
156
|
},
|
|
161
|
-
|
|
157
|
+
[] => void,
|
|
162
158
|
}
|
|
163
159
|
}
|
|
164
160
|
|
|
165
|
-
@
|
|
166
|
-
let join =
|
|
161
|
+
@unsafe
|
|
162
|
+
let join = list => {
|
|
167
163
|
let len = totalBytes(0n, list)
|
|
168
164
|
let str = allocateString(len)
|
|
169
165
|
writeStrings(str + 8n, list)
|
|
170
166
|
WasmI32.toGrain(str): String
|
|
171
167
|
}
|
|
172
168
|
|
|
173
|
-
@
|
|
174
|
-
let reverse =
|
|
175
|
-
@
|
|
169
|
+
@unsafe
|
|
170
|
+
let reverse = list => {
|
|
171
|
+
@unsafe
|
|
176
172
|
let rec iter = (list, acc) => {
|
|
177
173
|
match (list) {
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
[] => acc,
|
|
175
|
+
[first, ...rest] => iter(rest, [first, ...acc]),
|
|
180
176
|
}
|
|
181
177
|
}
|
|
182
|
-
|
|
183
|
-
iter(list, SLEmpty)
|
|
178
|
+
iter(list, [])
|
|
184
179
|
}
|
|
185
180
|
|
|
186
|
-
@
|
|
187
|
-
export let
|
|
181
|
+
@unsafe
|
|
182
|
+
export let concat = (s1: String, s2: String) => {
|
|
188
183
|
let ptr1 = WasmI32.fromGrain(s1)
|
|
189
184
|
let ptr2 = WasmI32.fromGrain(s2)
|
|
190
185
|
|
|
@@ -196,14 +191,10 @@ export let rec concat = (s1: String, s2: String) => {
|
|
|
196
191
|
Memory.copy(newString + 8n, ptr1 + 8n, size1)
|
|
197
192
|
Memory.copy(newString + 8n + size1, ptr2 + 8n, size2)
|
|
198
193
|
|
|
199
|
-
|
|
200
|
-
Memory.decRef(ptr1)
|
|
201
|
-
Memory.decRef(ptr2)
|
|
202
|
-
Memory.decRef(WasmI32.fromGrain(concat))
|
|
203
|
-
ret
|
|
194
|
+
WasmI32.toGrain(newString): String
|
|
204
195
|
}
|
|
205
196
|
|
|
206
|
-
@
|
|
197
|
+
@unsafe
|
|
207
198
|
let escape = (ptr, isString) => {
|
|
208
199
|
let _SEQ_B = 0x08n
|
|
209
200
|
let _SEQ_F = 0x0Cn
|
|
@@ -217,30 +208,20 @@ let escape = (ptr, isString) => {
|
|
|
217
208
|
|
|
218
209
|
let _SEQ_QUOTE = if (isString) _SEQ_DQUOTE else _SEQ_SQUOTE
|
|
219
210
|
|
|
220
|
-
let size =
|
|
221
|
-
WasmI32.load(ptr, 4n)
|
|
222
|
-
} else {
|
|
223
|
-
let byte = WasmI32.load8U(ptr, 4n)
|
|
224
|
-
|
|
225
|
-
// Calculate number of bytes via utf-8 encoding
|
|
226
|
-
if ((byte & 0x80n) == 0x00n) {
|
|
227
|
-
1n
|
|
228
|
-
} else if ((byte & 0xF0n) == 0xF0n) {
|
|
229
|
-
4n
|
|
230
|
-
} else if ((byte & 0xE0n) == 0xE0n) {
|
|
231
|
-
3n
|
|
232
|
-
} else {
|
|
233
|
-
2n
|
|
234
|
-
}
|
|
235
|
-
}
|
|
211
|
+
let size = WasmI32.load(ptr, 4n)
|
|
236
212
|
|
|
237
|
-
let startOffset =
|
|
213
|
+
let startOffset = 8n
|
|
238
214
|
let stringOffset = 8n
|
|
239
215
|
|
|
240
216
|
let mut newSize = 2n // extra space for quote characters
|
|
241
217
|
for (let mut i = 0n; i < size; i += 1n) {
|
|
242
218
|
let byte = WasmI32.load8U(ptr + i, startOffset)
|
|
243
|
-
if (
|
|
219
|
+
if (
|
|
220
|
+
byte >= _SEQ_B && byte <= _SEQ_R || /* b, f, n, r, t, v */
|
|
221
|
+
byte == _SEQ_V ||
|
|
222
|
+
byte == _SEQ_SLASH ||
|
|
223
|
+
byte == _SEQ_QUOTE
|
|
224
|
+
) {
|
|
244
225
|
newSize += 2n
|
|
245
226
|
} else {
|
|
246
227
|
newSize += 1n
|
|
@@ -254,7 +235,12 @@ let escape = (ptr, isString) => {
|
|
|
254
235
|
|
|
255
236
|
for (let mut i = 0n; i < size; i += 1n) {
|
|
256
237
|
let byte = WasmI32.load8U(ptr + i, startOffset)
|
|
257
|
-
if (
|
|
238
|
+
if (
|
|
239
|
+
byte >= _SEQ_B && byte <= _SEQ_R || /* b, f, n, r, t, v */
|
|
240
|
+
byte == _SEQ_V ||
|
|
241
|
+
byte == _SEQ_SLASH ||
|
|
242
|
+
byte == _SEQ_QUOTE
|
|
243
|
+
) {
|
|
258
244
|
WasmI32.store8(escapedString + j, _SEQ_SLASH, stringOffset)
|
|
259
245
|
j += 1n
|
|
260
246
|
let seq = match (byte) {
|
|
@@ -264,7 +250,7 @@ let escape = (ptr, isString) => {
|
|
|
264
250
|
r when r == _SEQ_R => 0x72n,
|
|
265
251
|
t when t == _SEQ_T => 0x74n,
|
|
266
252
|
v when v == _SEQ_V => 0x76n,
|
|
267
|
-
_ => byte
|
|
253
|
+
_ => byte,
|
|
268
254
|
}
|
|
269
255
|
WasmI32.store8(escapedString + j, seq, stringOffset)
|
|
270
256
|
j += 1n
|
|
@@ -280,33 +266,65 @@ let escape = (ptr, isString) => {
|
|
|
280
266
|
WasmI32.toGrain(escapedString): String
|
|
281
267
|
}
|
|
282
268
|
|
|
283
|
-
@
|
|
269
|
+
@unsafe
|
|
284
270
|
let escapeString = (s: String) => {
|
|
285
271
|
escape(WasmI32.fromGrain(s), true)
|
|
286
272
|
}
|
|
287
273
|
|
|
288
|
-
@
|
|
289
|
-
let escapeChar = (
|
|
290
|
-
escape(WasmI32.fromGrain(
|
|
274
|
+
@unsafe
|
|
275
|
+
let escapeChar = (s: String) => {
|
|
276
|
+
escape(WasmI32.fromGrain(s), false)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@unsafe
|
|
280
|
+
let usvToString = usv => {
|
|
281
|
+
if (usv < 0x80n) {
|
|
282
|
+
let string = allocateString(1n)
|
|
283
|
+
WasmI32.store8(string, usv, 8n)
|
|
284
|
+
WasmI32.toGrain(string): String
|
|
285
|
+
} else {
|
|
286
|
+
let mut count = 0n
|
|
287
|
+
let mut offset = 0n
|
|
288
|
+
if (usv <= 0x07FFn) {
|
|
289
|
+
count = 1n
|
|
290
|
+
offset = 0xC0n
|
|
291
|
+
} else if (usv <= 0xFFFFn) {
|
|
292
|
+
count = 2n
|
|
293
|
+
offset = 0xE0n
|
|
294
|
+
} else {
|
|
295
|
+
count = 3n
|
|
296
|
+
offset = 0xF0n
|
|
297
|
+
}
|
|
298
|
+
let string = allocateString(count + 1n)
|
|
299
|
+
WasmI32.store8(string, (usv >>> 6n * count) + offset, 8n)
|
|
300
|
+
|
|
301
|
+
let mut n = 0n
|
|
302
|
+
while (count > 0n) {
|
|
303
|
+
n += 1n
|
|
304
|
+
let temp = usv >>> 6n * (count - 1n)
|
|
305
|
+
WasmI32.store8(string + n, 0x80n | temp & 0x3Fn, 8n)
|
|
306
|
+
count -= 1n
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
WasmI32.toGrain(string): String
|
|
310
|
+
}
|
|
291
311
|
}
|
|
292
312
|
|
|
293
|
-
@
|
|
313
|
+
@unsafe
|
|
294
314
|
let isListVariant = (variant: String) => {
|
|
295
315
|
// Only lists can start with `[`, so only need to check for that
|
|
296
316
|
// Sort of a hack until we have a better solution
|
|
297
317
|
WasmI32.load8U(WasmI32.fromGrain(variant), 8n) == 0x5Bn
|
|
298
318
|
}
|
|
299
319
|
|
|
300
|
-
@
|
|
320
|
+
@unsafe
|
|
301
321
|
let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
302
322
|
let tag = WasmI32.load(ptr, 0n)
|
|
303
323
|
match (tag) {
|
|
304
324
|
t when t == Tags._GRAIN_STRING_HEAP_TAG => {
|
|
325
|
+
// In both cases, we incRef ptr so we can use it again via WasmI32.toGrain
|
|
326
|
+
Memory.incRef(ptr)
|
|
305
327
|
if (toplevel) {
|
|
306
|
-
// We can just return the pointer since its already a string and
|
|
307
|
-
// doesn't need escaping in this case, but by convention its reference
|
|
308
|
-
// count needs to be incremented.
|
|
309
|
-
Memory.incRef(ptr)
|
|
310
328
|
WasmI32.toGrain(ptr): String
|
|
311
329
|
} else {
|
|
312
330
|
escapeString(WasmI32.toGrain(ptr))
|
|
@@ -350,25 +368,6 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
350
368
|
|
|
351
369
|
WasmI32.toGrain(str): String
|
|
352
370
|
},
|
|
353
|
-
t when t == Tags._GRAIN_CHAR_HEAP_TAG => {
|
|
354
|
-
if (toplevel) {
|
|
355
|
-
let byte = WasmI32.load8U(ptr, 4n)
|
|
356
|
-
let numBytes = if ((byte & 0x80n) == 0x00n) {
|
|
357
|
-
1n
|
|
358
|
-
} else if ((byte & 0xF0n) == 0xF0n) {
|
|
359
|
-
4n
|
|
360
|
-
} else if ((byte & 0xE0n) == 0xE0n) {
|
|
361
|
-
3n
|
|
362
|
-
} else {
|
|
363
|
-
2n
|
|
364
|
-
}
|
|
365
|
-
let str = allocateString(numBytes)
|
|
366
|
-
Memory.copy(str + 8n, ptr + 4n, numBytes)
|
|
367
|
-
WasmI32.toGrain(str): String
|
|
368
|
-
} else {
|
|
369
|
-
escapeChar(WasmI32.toGrain(ptr))
|
|
370
|
-
}
|
|
371
|
-
},
|
|
372
371
|
t when t == Tags._GRAIN_ADT_HEAP_TAG => {
|
|
373
372
|
// [ <value type tag>, <module_tag>, <type_tag>, <variant_tag>, <arity>, elts ... ]
|
|
374
373
|
let variantName = getVariantName(ptr)
|
|
@@ -387,26 +386,22 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
387
386
|
} else {
|
|
388
387
|
let comspace = ", "
|
|
389
388
|
let rparen = ")"
|
|
390
|
-
|
|
391
|
-
let mut strings = slConsDisableGc(rparen, SLEmpty)
|
|
389
|
+
let mut strings = [rparen]
|
|
392
390
|
for (let mut i = variantArity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
393
|
-
let tmp = toStringHelp(
|
|
394
|
-
|
|
395
|
-
|
|
391
|
+
let tmp = toStringHelp(
|
|
392
|
+
WasmI32.load(ptr + i, 20n),
|
|
393
|
+
extraIndents,
|
|
394
|
+
false
|
|
395
|
+
)
|
|
396
|
+
strings = [tmp, ...strings]
|
|
396
397
|
if (i > 0n) {
|
|
397
|
-
strings =
|
|
398
|
+
strings = [comspace, ...strings]
|
|
398
399
|
}
|
|
399
400
|
}
|
|
400
|
-
Memory.incRef(WasmI32.fromGrain(variantName))
|
|
401
401
|
let lparen = "("
|
|
402
|
-
strings =
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
Memory.decRef(WasmI32.fromGrain(lparen))
|
|
406
|
-
Memory.decRef(WasmI32.fromGrain(rparen))
|
|
407
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
408
|
-
Memory.decRef(WasmI32.fromGrain(comspace))
|
|
409
|
-
string
|
|
402
|
+
strings = [variantName, lparen, ...strings]
|
|
403
|
+
|
|
404
|
+
join(strings)
|
|
410
405
|
}
|
|
411
406
|
}
|
|
412
407
|
}
|
|
@@ -418,70 +413,60 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
418
413
|
"<record value>"
|
|
419
414
|
} else {
|
|
420
415
|
let prevPadAmount = extraIndents * 2n
|
|
421
|
-
let prevSpacePadding = if (prevPadAmount == 0n)
|
|
416
|
+
let prevSpacePadding = if (prevPadAmount == 0n) {
|
|
417
|
+
""
|
|
418
|
+
} else {
|
|
422
419
|
let v = allocateString(prevPadAmount)
|
|
423
|
-
Memory.fill(
|
|
424
|
-
|
|
420
|
+
Memory.fill(
|
|
421
|
+
v + 8n,
|
|
422
|
+
0x20n,
|
|
423
|
+
prevPadAmount
|
|
424
|
+
) // create indentation for closing brace
|
|
425
|
+
WasmI32.toGrain(v): String
|
|
425
426
|
}
|
|
426
427
|
let padAmount = (extraIndents + 1n) * 2n
|
|
427
428
|
let spacePadding = allocateString(padAmount)
|
|
428
429
|
Memory.fill(spacePadding + 8n, 0x20n, padAmount) // create indentation
|
|
429
430
|
let spacePadding = WasmI32.toGrain(spacePadding): String
|
|
430
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
431
431
|
let newline = "\n"
|
|
432
432
|
let rbrace = "}"
|
|
433
|
-
let mut strings =
|
|
433
|
+
let mut strings = [newline, prevSpacePadding, rbrace]
|
|
434
434
|
let colspace = ": "
|
|
435
435
|
let comlf = ",\n"
|
|
436
|
-
for (let mut i = recordArity * 4n - 4n; i >= 0n;
|
|
436
|
+
for (let mut i = recordArity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
437
437
|
let fieldName = WasmI32.toGrain(WasmI32.load(fields + i, 8n)): String
|
|
438
|
-
let fieldValue = toStringHelp(
|
|
439
|
-
|
|
440
|
-
|
|
438
|
+
let fieldValue = toStringHelp(
|
|
439
|
+
WasmI32.load(ptr + i, 16n),
|
|
440
|
+
extraIndents + 1n,
|
|
441
|
+
false
|
|
442
|
+
)
|
|
443
|
+
strings = [spacePadding, fieldName, colspace, fieldValue, ...strings]
|
|
441
444
|
if (i > 0n) {
|
|
442
|
-
strings =
|
|
445
|
+
strings = [comlf, ...strings]
|
|
443
446
|
}
|
|
444
447
|
}
|
|
445
448
|
let lbrace = "{\n"
|
|
446
|
-
strings =
|
|
447
|
-
let string = join(strings)
|
|
448
|
-
|
|
449
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
450
|
-
Memory.decRef(WasmI32.fromGrain(spacePadding))
|
|
451
|
-
Memory.decRef(WasmI32.fromGrain(colspace))
|
|
452
|
-
Memory.decRef(WasmI32.fromGrain(comlf))
|
|
453
|
-
Memory.decRef(WasmI32.fromGrain(lbrace))
|
|
454
|
-
Memory.decRef(WasmI32.fromGrain(rbrace))
|
|
455
|
-
Memory.decRef(WasmI32.fromGrain(newline))
|
|
456
|
-
|
|
457
|
-
Memory.free(fields) // Avoid double-free of record field names
|
|
449
|
+
strings = [lbrace, ...strings]
|
|
458
450
|
|
|
459
|
-
|
|
451
|
+
join(strings)
|
|
460
452
|
}
|
|
461
453
|
},
|
|
462
454
|
t when t == Tags._GRAIN_ARRAY_HEAP_TAG => {
|
|
463
455
|
let arity = WasmI32.load(ptr, 4n)
|
|
464
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
465
456
|
let rbrack = "]"
|
|
466
|
-
let mut strings =
|
|
457
|
+
let mut strings = [rbrack]
|
|
467
458
|
let comspace = ", "
|
|
468
459
|
for (let mut i = arity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
469
460
|
let item = toStringHelp(WasmI32.load(ptr + i, 8n), extraIndents, false)
|
|
470
|
-
strings =
|
|
471
|
-
Memory.decRef(WasmI32.fromGrain(item))
|
|
461
|
+
strings = [item, ...strings]
|
|
472
462
|
if (i > 0n) {
|
|
473
|
-
strings =
|
|
463
|
+
strings = [comspace, ...strings]
|
|
474
464
|
}
|
|
475
465
|
}
|
|
476
466
|
let lbrack = "[> "
|
|
477
|
-
strings =
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
Memory.decRef(WasmI32.fromGrain(comspace))
|
|
481
|
-
Memory.decRef(WasmI32.fromGrain(lbrack))
|
|
482
|
-
Memory.decRef(WasmI32.fromGrain(rbrack))
|
|
483
|
-
|
|
484
|
-
string
|
|
467
|
+
strings = [lbrack, ...strings]
|
|
468
|
+
|
|
469
|
+
join(strings)
|
|
485
470
|
},
|
|
486
471
|
t when t == Tags._GRAIN_BOXED_NUM_HEAP_TAG => {
|
|
487
472
|
let numberTag = WasmI32.load(ptr, 4n)
|
|
@@ -492,18 +477,15 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
492
477
|
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
493
478
|
NumberUtils.itoa64(WasmI64.load(ptr, 8n), 10n)
|
|
494
479
|
},
|
|
480
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
481
|
+
BI.bigIntToString10(ptr)
|
|
482
|
+
},
|
|
495
483
|
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
496
|
-
let numerator =
|
|
497
|
-
let denominator =
|
|
498
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
484
|
+
let numerator = BI.bigIntToString10(WasmI32.load(ptr, 8n))
|
|
485
|
+
let denominator = BI.bigIntToString10(WasmI32.load(ptr, 12n))
|
|
499
486
|
let slash = "/"
|
|
500
|
-
let strings =
|
|
501
|
-
|
|
502
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
503
|
-
Memory.decRef(WasmI32.fromGrain(numerator))
|
|
504
|
-
Memory.decRef(WasmI32.fromGrain(denominator))
|
|
505
|
-
Memory.decRef(WasmI32.fromGrain(slash))
|
|
506
|
-
string
|
|
487
|
+
let strings = [numerator, slash, denominator]
|
|
488
|
+
join(strings)
|
|
507
489
|
},
|
|
508
490
|
t when t == Tags._GRAIN_FLOAT32_BOXED_NUM_TAG => {
|
|
509
491
|
NumberUtils.dtoa(WasmF64.promoteF32(WasmF32.load(ptr, 8n)))
|
|
@@ -513,7 +495,7 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
513
495
|
},
|
|
514
496
|
_ => {
|
|
515
497
|
"<unknown boxed number>"
|
|
516
|
-
}
|
|
498
|
+
},
|
|
517
499
|
}
|
|
518
500
|
},
|
|
519
501
|
t when t == Tags._GRAIN_TUPLE_HEAP_TAG => {
|
|
@@ -523,78 +505,80 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
523
505
|
} else {
|
|
524
506
|
WasmI32.store(ptr, 0x80000000n | tupleLength, 4n)
|
|
525
507
|
let comspace = ", "
|
|
526
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
527
508
|
let rparen = ")"
|
|
528
|
-
let mut strings =
|
|
509
|
+
let mut strings = [rparen]
|
|
529
510
|
if (tupleLength <= 1n) {
|
|
530
511
|
// Special case: unary tuple
|
|
531
512
|
let comma = ","
|
|
532
|
-
strings =
|
|
533
|
-
Memory.decRef(WasmI32.fromGrain(comma))
|
|
513
|
+
strings = [comma, ...strings]
|
|
534
514
|
void
|
|
535
515
|
}
|
|
536
516
|
for (let mut i = tupleLength * 4n - 4n; i >= 0n; i -= 4n) {
|
|
537
|
-
let item = toStringHelp(
|
|
538
|
-
|
|
539
|
-
|
|
517
|
+
let item = toStringHelp(
|
|
518
|
+
WasmI32.load(ptr + i, 8n),
|
|
519
|
+
extraIndents,
|
|
520
|
+
false
|
|
521
|
+
)
|
|
522
|
+
strings = [item, ...strings]
|
|
540
523
|
if (i > 0n) {
|
|
541
|
-
strings =
|
|
524
|
+
strings = [comspace, ...strings]
|
|
542
525
|
}
|
|
543
526
|
}
|
|
544
527
|
WasmI32.store(ptr, tupleLength, 4n)
|
|
545
528
|
|
|
546
529
|
Memory.incRef(WasmI32.fromGrain(strings))
|
|
547
530
|
let lparen = "("
|
|
548
|
-
strings =
|
|
531
|
+
strings = [lparen, ...strings]
|
|
549
532
|
|
|
550
|
-
|
|
551
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
552
|
-
Memory.decRef(WasmI32.fromGrain(comspace))
|
|
553
|
-
Memory.decRef(WasmI32.fromGrain(rparen))
|
|
554
|
-
Memory.decRef(WasmI32.fromGrain(lparen))
|
|
555
|
-
|
|
556
|
-
string
|
|
533
|
+
join(strings)
|
|
557
534
|
}
|
|
558
535
|
},
|
|
559
536
|
t when t == Tags._GRAIN_LAMBDA_HEAP_TAG => {
|
|
560
537
|
"<lambda>"
|
|
561
538
|
},
|
|
562
539
|
_ => {
|
|
563
|
-
|
|
564
|
-
let strings = slConsDisableGc(
|
|
540
|
+
let strings = [
|
|
565
541
|
"<unknown heap tag type: 0x",
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
542
|
+
NumberUtils.itoa32(tag, 16n),
|
|
543
|
+
" | value: 0x",
|
|
544
|
+
NumberUtils.itoa32(ptr, 16n),
|
|
545
|
+
">",
|
|
546
|
+
]
|
|
547
|
+
join(strings)
|
|
548
|
+
},
|
|
574
549
|
}
|
|
575
550
|
}, toStringHelp = (grainValue, extraIndents, toplevel) => {
|
|
576
551
|
if ((grainValue & 1n) != 0n) {
|
|
577
552
|
// Simple (unboxed) numbers
|
|
578
553
|
NumberUtils.itoa32(grainValue >> 1n, 10n)
|
|
579
|
-
} else if ((grainValue & 7n) == Tags._GRAIN_GENERIC_HEAP_TAG_TYPE) {
|
|
580
|
-
heapValueToString(grainValue, extraIndents, toplevel)
|
|
581
|
-
} else if (grainValue == WasmI32.fromGrain(true)) {
|
|
582
|
-
"true"
|
|
583
|
-
} else if (grainValue == WasmI32.fromGrain(false)) {
|
|
584
|
-
"false"
|
|
585
|
-
} else if (grainValue == WasmI32.fromGrain(void)) {
|
|
586
|
-
"void"
|
|
587
554
|
} else {
|
|
588
|
-
|
|
555
|
+
let tag = grainValue & 7n
|
|
556
|
+
if (tag == Tags._GRAIN_GENERIC_HEAP_TAG_TYPE) {
|
|
557
|
+
heapValueToString(grainValue, extraIndents, toplevel)
|
|
558
|
+
} else if (tag == Tags._GRAIN_CHAR_TAG_TYPE) {
|
|
559
|
+
let string = usvToString(grainValue >> 3n)
|
|
560
|
+
if (toplevel) {
|
|
561
|
+
string
|
|
562
|
+
} else {
|
|
563
|
+
escapeChar(string)
|
|
564
|
+
}
|
|
565
|
+
} else if (grainValue == WasmI32.fromGrain(true)) {
|
|
566
|
+
"true"
|
|
567
|
+
} else if (grainValue == WasmI32.fromGrain(false)) {
|
|
568
|
+
"false"
|
|
569
|
+
} else if (grainValue == WasmI32.fromGrain(void)) {
|
|
570
|
+
"void"
|
|
571
|
+
} else {
|
|
572
|
+
"<unknown value>"
|
|
573
|
+
}
|
|
589
574
|
}
|
|
590
575
|
}, listToString = (ptr, extraIndents) => {
|
|
591
576
|
let mut cur = ptr
|
|
592
577
|
let mut isFirst = true
|
|
593
578
|
|
|
594
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
595
579
|
let lbrack = "["
|
|
596
580
|
let commaspace = ", "
|
|
597
|
-
let mut strings =
|
|
581
|
+
let mut strings = [lbrack]
|
|
598
582
|
|
|
599
583
|
while (true) {
|
|
600
584
|
let variantId = WasmI32.load(cur, 12n) >> 1n // tagged number
|
|
@@ -602,46 +586,30 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
602
586
|
break
|
|
603
587
|
} else {
|
|
604
588
|
if (!isFirst) {
|
|
605
|
-
strings =
|
|
589
|
+
strings = [commaspace, ...strings]
|
|
606
590
|
}
|
|
607
591
|
isFirst = false
|
|
608
592
|
let item = toStringHelp(WasmI32.load(cur, 20n), extraIndents, false)
|
|
609
|
-
strings =
|
|
610
|
-
Memory.decRef(WasmI32.fromGrain(item))
|
|
593
|
+
strings = [item, ...strings]
|
|
611
594
|
cur = WasmI32.load(cur, 24n)
|
|
612
595
|
}
|
|
613
596
|
}
|
|
614
597
|
let rbrack = "]"
|
|
615
|
-
strings =
|
|
598
|
+
strings = [rbrack, ...strings]
|
|
616
599
|
let reversed = reverse(strings)
|
|
617
|
-
|
|
618
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
619
|
-
Memory.decRef(WasmI32.fromGrain(reversed))
|
|
620
|
-
Memory.decRef(WasmI32.fromGrain(lbrack))
|
|
621
|
-
Memory.decRef(WasmI32.fromGrain(rbrack))
|
|
622
|
-
Memory.decRef(WasmI32.fromGrain(commaspace))
|
|
623
|
-
string
|
|
600
|
+
join(reversed)
|
|
624
601
|
}
|
|
625
602
|
|
|
626
|
-
@
|
|
627
|
-
export let
|
|
603
|
+
@unsafe
|
|
604
|
+
export let toString = value => {
|
|
628
605
|
let value = WasmI32.fromGrain(value)
|
|
629
|
-
|
|
630
|
-
Memory.decRef(value)
|
|
631
|
-
Memory.decRef(WasmI32.fromGrain(toString))
|
|
632
|
-
ret
|
|
606
|
+
toStringHelp(value, 0n, true)
|
|
633
607
|
}
|
|
634
608
|
|
|
635
|
-
@
|
|
636
|
-
export let
|
|
637
|
-
// First convert the value to string, if it isn't one already.
|
|
638
|
-
// toString will either return value instance itself if it's already a
|
|
639
|
-
// string, or a new string with the content of value object, which will need
|
|
640
|
-
// to be deallocated. In either case it's sufficient to force decrement its
|
|
641
|
-
// reference count.
|
|
609
|
+
@unsafe
|
|
610
|
+
export let print = value => {
|
|
611
|
+
// First convert the value to string, if it isn't one already.
|
|
642
612
|
let valuePtr = WasmI32.fromGrain(value)
|
|
643
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
644
|
-
Memory.incRef(valuePtr) // for function call
|
|
645
613
|
let s = toString(value)
|
|
646
614
|
let ptr = WasmI32.fromGrain(s)
|
|
647
615
|
// iov: [<ptr to string> <nbytes of string> <ptr to newline> <nbytes of newline>] (32 bytes)
|
|
@@ -658,8 +626,5 @@ export let rec print = (value) => {
|
|
|
658
626
|
WasmI32.store(iov, 1n, 12n)
|
|
659
627
|
fd_write(1n, iov, 2n, written)
|
|
660
628
|
Memory.free(buf)
|
|
661
|
-
Memory.decRef(ptr)
|
|
662
|
-
Memory.decRef(WasmI32.fromGrain(print))
|
|
663
|
-
Memory.decRef(WasmI32.fromGrain(value))
|
|
664
629
|
void
|
|
665
630
|
}
|