@grain/stdlib 0.4.5 → 0.5.1
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 +18 -18
- package/array.md +18 -18
- package/bigint.gr +497 -0
- package/bigint.md +811 -0
- package/buffer.gr +49 -213
- package/buffer.md +24 -17
- package/bytes.gr +100 -202
- package/bytes.md +19 -0
- package/char.gr +63 -133
- 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 +37 -37
- package/int32.gr +479 -230
- package/int32.md +937 -0
- package/int64.gr +479 -230
- package/int64.md +937 -0
- package/list.gr +467 -70
- package/list.md +1141 -0
- package/map.gr +192 -7
- package/map.md +525 -0
- package/number.gr +30 -54
- package/number.md +3 -3
- package/option.md +1 -1
- package/package.json +3 -3
- package/pervasives.gr +499 -59
- package/pervasives.md +1116 -0
- package/queue.gr +4 -0
- package/queue.md +10 -0
- package/random.gr +196 -0
- package/random.md +179 -0
- 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 -278
- package/runtime/dataStructures.md +391 -0
- package/runtime/debug.md +6 -0
- package/runtime/equal.gr +5 -23
- package/runtime/equal.md +6 -0
- package/runtime/exception.md +30 -0
- package/runtime/gc.gr +20 -3
- package/runtime/gc.md +36 -0
- package/runtime/malloc.gr +13 -11
- package/runtime/malloc.md +55 -0
- package/runtime/numberUtils.gr +93 -41
- package/runtime/numberUtils.md +54 -0
- package/runtime/numbers.gr +1043 -391
- package/runtime/numbers.md +300 -0
- package/runtime/string.gr +136 -230
- package/runtime/string.md +24 -0
- package/runtime/stringUtils.gr +58 -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.md +71 -0
- package/runtime/unsafe/errors.md +204 -0
- package/runtime/unsafe/memory.md +54 -0
- package/runtime/unsafe/printWasm.md +24 -0
- package/runtime/unsafe/tags.gr +9 -8
- package/runtime/unsafe/tags.md +120 -0
- package/runtime/unsafe/wasmf32.md +168 -0
- package/runtime/unsafe/wasmf64.md +168 -0
- package/runtime/unsafe/wasmi32.md +282 -0
- 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 +1 -1
- package/runtime/wasi.md +839 -0
- package/set.gr +17 -8
- package/set.md +24 -21
- package/stack.gr +3 -3
- package/stack.md +4 -6
- package/string.gr +196 -331
- package/string.md +3 -3
- package/sys/file.gr +246 -430
- package/sys/process.gr +27 -45
- package/sys/random.gr +47 -16
- package/sys/random.md +38 -0
- package/sys/time.gr +11 -27
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 (==),
|
|
@@ -19,6 +20,7 @@ import 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"
|
|
@@ -37,29 +39,13 @@ primitive (&&): (Bool, Bool) -> Bool = "@and"
|
|
|
37
39
|
primitive (||): (Bool, Bool) -> Bool = "@or"
|
|
38
40
|
|
|
39
41
|
enum StringList {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
[],
|
|
43
|
+
[...](String, StringList),
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
@
|
|
45
|
-
let slConsDisableGc = (a, b) => {
|
|
46
|
-
Memory.incRef(WasmI32.fromGrain(SLCons))
|
|
47
|
-
Memory.incRef(WasmI32.fromGrain(a))
|
|
48
|
-
// for easier chaining, we don't incRef `b`
|
|
49
|
-
SLCons(a, b)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
@disableGC
|
|
53
|
-
let mut _RUNTIME_TYPE_METADATA_PTR = 0x01n
|
|
46
|
+
primitive _RUNTIME_TYPE_METADATA_PTR: WasmI32 = "@heap.type_metadata"
|
|
54
47
|
|
|
55
|
-
@
|
|
56
|
-
let initPtr = () => {
|
|
57
|
-
// hack to avoid incRef on this pointer
|
|
58
|
-
_RUNTIME_TYPE_METADATA_PTR = 0x408n
|
|
59
|
-
}
|
|
60
|
-
initPtr()
|
|
61
|
-
|
|
62
|
-
@disableGC
|
|
48
|
+
@unsafe
|
|
63
49
|
let findTypeMetadata = (moduleId, typeId) => {
|
|
64
50
|
let mut metadataPtr = WasmI32.load(_RUNTIME_TYPE_METADATA_PTR, 0n)
|
|
65
51
|
let mut modData = -1n
|
|
@@ -89,7 +75,7 @@ let findTypeMetadata = (moduleId, typeId) => {
|
|
|
89
75
|
}
|
|
90
76
|
}
|
|
91
77
|
|
|
92
|
-
@
|
|
78
|
+
@unsafe
|
|
93
79
|
let getVariantName = variant => {
|
|
94
80
|
let moduleId = WasmI32.load(variant, 4n) >> 1n
|
|
95
81
|
let typeId = WasmI32.load(variant, 8n) >> 1n
|
|
@@ -120,7 +106,7 @@ let getVariantName = variant => {
|
|
|
120
106
|
}
|
|
121
107
|
}
|
|
122
108
|
|
|
123
|
-
@
|
|
109
|
+
@unsafe
|
|
124
110
|
let getRecordFieldNames = record_ => {
|
|
125
111
|
let moduleId = WasmI32.load(record_, 4n) >> 1n
|
|
126
112
|
let typeId = WasmI32.load(record_, 8n) >> 1n
|
|
@@ -139,6 +125,7 @@ let getRecordFieldNames = record_ => {
|
|
|
139
125
|
for (let mut i = 0n; i < arity; i += 1n) {
|
|
140
126
|
let fieldLength = WasmI32.load(fields + fieldOffset, 4n)
|
|
141
127
|
let fieldName = allocateString(fieldLength)
|
|
128
|
+
Memory.incRef(fieldName)
|
|
142
129
|
Memory.copy(fieldName + 8n, fields + fieldOffset + 8n, fieldLength)
|
|
143
130
|
WasmI32.store(fieldArray + i * 4n, fieldName, 8n)
|
|
144
131
|
|
|
@@ -149,29 +136,29 @@ let getRecordFieldNames = record_ => {
|
|
|
149
136
|
}
|
|
150
137
|
}
|
|
151
138
|
|
|
152
|
-
@
|
|
139
|
+
@unsafe
|
|
153
140
|
let rec totalBytes = (acc, list) => {
|
|
154
141
|
match (list) {
|
|
155
|
-
|
|
142
|
+
[hd, ...tl] =>
|
|
156
143
|
totalBytes(acc + WasmI32.load(WasmI32.fromGrain(hd), 4n), tl),
|
|
157
|
-
|
|
144
|
+
[] => acc,
|
|
158
145
|
}
|
|
159
146
|
}
|
|
160
147
|
|
|
161
|
-
@
|
|
148
|
+
@unsafe
|
|
162
149
|
let rec writeStrings = (buf, list) => {
|
|
163
150
|
match (list) {
|
|
164
|
-
|
|
151
|
+
[hd, ...tl] => {
|
|
165
152
|
let hd = WasmI32.fromGrain(hd)
|
|
166
153
|
let hdSize = WasmI32.load(hd, 4n)
|
|
167
154
|
Memory.copy(buf, hd + 8n, hdSize)
|
|
168
155
|
writeStrings(buf + hdSize, tl)
|
|
169
156
|
},
|
|
170
|
-
|
|
157
|
+
[] => void,
|
|
171
158
|
}
|
|
172
159
|
}
|
|
173
160
|
|
|
174
|
-
@
|
|
161
|
+
@unsafe
|
|
175
162
|
let join = list => {
|
|
176
163
|
let len = totalBytes(0n, list)
|
|
177
164
|
let str = allocateString(len)
|
|
@@ -179,21 +166,20 @@ let join = list => {
|
|
|
179
166
|
WasmI32.toGrain(str): String
|
|
180
167
|
}
|
|
181
168
|
|
|
182
|
-
@
|
|
169
|
+
@unsafe
|
|
183
170
|
let reverse = list => {
|
|
184
|
-
@
|
|
171
|
+
@unsafe
|
|
185
172
|
let rec iter = (list, acc) => {
|
|
186
173
|
match (list) {
|
|
187
|
-
|
|
188
|
-
|
|
174
|
+
[] => acc,
|
|
175
|
+
[first, ...rest] => iter(rest, [first, ...acc]),
|
|
189
176
|
}
|
|
190
177
|
}
|
|
191
|
-
|
|
192
|
-
iter(list, SLEmpty)
|
|
178
|
+
iter(list, [])
|
|
193
179
|
}
|
|
194
180
|
|
|
195
|
-
@
|
|
196
|
-
export let
|
|
181
|
+
@unsafe
|
|
182
|
+
export let concat = (s1: String, s2: String) => {
|
|
197
183
|
let ptr1 = WasmI32.fromGrain(s1)
|
|
198
184
|
let ptr2 = WasmI32.fromGrain(s2)
|
|
199
185
|
|
|
@@ -205,14 +191,10 @@ export let rec concat = (s1: String, s2: String) => {
|
|
|
205
191
|
Memory.copy(newString + 8n, ptr1 + 8n, size1)
|
|
206
192
|
Memory.copy(newString + 8n + size1, ptr2 + 8n, size2)
|
|
207
193
|
|
|
208
|
-
|
|
209
|
-
Memory.decRef(ptr1)
|
|
210
|
-
Memory.decRef(ptr2)
|
|
211
|
-
Memory.decRef(WasmI32.fromGrain(concat))
|
|
212
|
-
ret
|
|
194
|
+
WasmI32.toGrain(newString): String
|
|
213
195
|
}
|
|
214
196
|
|
|
215
|
-
@
|
|
197
|
+
@unsafe
|
|
216
198
|
let escape = (ptr, isString) => {
|
|
217
199
|
let _SEQ_B = 0x08n
|
|
218
200
|
let _SEQ_F = 0x0Cn
|
|
@@ -226,24 +208,9 @@ let escape = (ptr, isString) => {
|
|
|
226
208
|
|
|
227
209
|
let _SEQ_QUOTE = if (isString) _SEQ_DQUOTE else _SEQ_SQUOTE
|
|
228
210
|
|
|
229
|
-
let size =
|
|
230
|
-
WasmI32.load(ptr, 4n)
|
|
231
|
-
} else {
|
|
232
|
-
let byte = WasmI32.load8U(ptr, 4n)
|
|
233
|
-
|
|
234
|
-
// Calculate number of bytes via utf-8 encoding
|
|
235
|
-
if ((byte & 0x80n) == 0x00n) {
|
|
236
|
-
1n
|
|
237
|
-
} else if ((byte & 0xF0n) == 0xF0n) {
|
|
238
|
-
4n
|
|
239
|
-
} else if ((byte & 0xE0n) == 0xE0n) {
|
|
240
|
-
3n
|
|
241
|
-
} else {
|
|
242
|
-
2n
|
|
243
|
-
}
|
|
244
|
-
}
|
|
211
|
+
let size = WasmI32.load(ptr, 4n)
|
|
245
212
|
|
|
246
|
-
let startOffset =
|
|
213
|
+
let startOffset = 8n
|
|
247
214
|
let stringOffset = 8n
|
|
248
215
|
|
|
249
216
|
let mut newSize = 2n // extra space for quote characters
|
|
@@ -299,33 +266,65 @@ let escape = (ptr, isString) => {
|
|
|
299
266
|
WasmI32.toGrain(escapedString): String
|
|
300
267
|
}
|
|
301
268
|
|
|
302
|
-
@
|
|
269
|
+
@unsafe
|
|
303
270
|
let escapeString = (s: String) => {
|
|
304
271
|
escape(WasmI32.fromGrain(s), true)
|
|
305
272
|
}
|
|
306
273
|
|
|
307
|
-
@
|
|
308
|
-
let escapeChar = (
|
|
309
|
-
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
|
+
}
|
|
310
311
|
}
|
|
311
312
|
|
|
312
|
-
@
|
|
313
|
+
@unsafe
|
|
313
314
|
let isListVariant = (variant: String) => {
|
|
314
315
|
// Only lists can start with `[`, so only need to check for that
|
|
315
316
|
// Sort of a hack until we have a better solution
|
|
316
317
|
WasmI32.load8U(WasmI32.fromGrain(variant), 8n) == 0x5Bn
|
|
317
318
|
}
|
|
318
319
|
|
|
319
|
-
@
|
|
320
|
+
@unsafe
|
|
320
321
|
let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
321
322
|
let tag = WasmI32.load(ptr, 0n)
|
|
322
323
|
match (tag) {
|
|
323
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)
|
|
324
327
|
if (toplevel) {
|
|
325
|
-
// We can just return the pointer since its already a string and
|
|
326
|
-
// doesn't need escaping in this case, but by convention its reference
|
|
327
|
-
// count needs to be incremented.
|
|
328
|
-
Memory.incRef(ptr)
|
|
329
328
|
WasmI32.toGrain(ptr): String
|
|
330
329
|
} else {
|
|
331
330
|
escapeString(WasmI32.toGrain(ptr))
|
|
@@ -369,25 +368,6 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
369
368
|
|
|
370
369
|
WasmI32.toGrain(str): String
|
|
371
370
|
},
|
|
372
|
-
t when t == Tags._GRAIN_CHAR_HEAP_TAG => {
|
|
373
|
-
if (toplevel) {
|
|
374
|
-
let byte = WasmI32.load8U(ptr, 4n)
|
|
375
|
-
let numBytes = if ((byte & 0x80n) == 0x00n) {
|
|
376
|
-
1n
|
|
377
|
-
} else if ((byte & 0xF0n) == 0xF0n) {
|
|
378
|
-
4n
|
|
379
|
-
} else if ((byte & 0xE0n) == 0xE0n) {
|
|
380
|
-
3n
|
|
381
|
-
} else {
|
|
382
|
-
2n
|
|
383
|
-
}
|
|
384
|
-
let str = allocateString(numBytes)
|
|
385
|
-
Memory.copy(str + 8n, ptr + 4n, numBytes)
|
|
386
|
-
WasmI32.toGrain(str): String
|
|
387
|
-
} else {
|
|
388
|
-
escapeChar(WasmI32.toGrain(ptr))
|
|
389
|
-
}
|
|
390
|
-
},
|
|
391
371
|
t when t == Tags._GRAIN_ADT_HEAP_TAG => {
|
|
392
372
|
// [ <value type tag>, <module_tag>, <type_tag>, <variant_tag>, <arity>, elts ... ]
|
|
393
373
|
let variantName = getVariantName(ptr)
|
|
@@ -406,33 +386,22 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
406
386
|
} else {
|
|
407
387
|
let comspace = ", "
|
|
408
388
|
let rparen = ")"
|
|
409
|
-
|
|
410
|
-
let mut strings = slConsDisableGc(rparen, SLEmpty)
|
|
389
|
+
let mut strings = [rparen]
|
|
411
390
|
for (let mut i = variantArity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
412
391
|
let tmp = toStringHelp(
|
|
413
392
|
WasmI32.load(ptr + i, 20n),
|
|
414
393
|
extraIndents,
|
|
415
394
|
false
|
|
416
395
|
)
|
|
417
|
-
strings =
|
|
418
|
-
Memory.decRef(WasmI32.fromGrain(tmp))
|
|
396
|
+
strings = [tmp, ...strings]
|
|
419
397
|
if (i > 0n) {
|
|
420
|
-
strings =
|
|
398
|
+
strings = [comspace, ...strings]
|
|
421
399
|
}
|
|
422
400
|
}
|
|
423
|
-
Memory.incRef(WasmI32.fromGrain(variantName))
|
|
424
401
|
let lparen = "("
|
|
425
|
-
strings =
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
)
|
|
429
|
-
let string = join(strings)
|
|
430
|
-
Memory.decRef(WasmI32.fromGrain(variantName))
|
|
431
|
-
Memory.decRef(WasmI32.fromGrain(lparen))
|
|
432
|
-
Memory.decRef(WasmI32.fromGrain(rparen))
|
|
433
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
434
|
-
Memory.decRef(WasmI32.fromGrain(comspace))
|
|
435
|
-
string
|
|
402
|
+
strings = [variantName, lparen, ...strings]
|
|
403
|
+
|
|
404
|
+
join(strings)
|
|
436
405
|
}
|
|
437
406
|
}
|
|
438
407
|
}
|
|
@@ -459,13 +428,9 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
459
428
|
let spacePadding = allocateString(padAmount)
|
|
460
429
|
Memory.fill(spacePadding + 8n, 0x20n, padAmount) // create indentation
|
|
461
430
|
let spacePadding = WasmI32.toGrain(spacePadding): String
|
|
462
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
463
431
|
let newline = "\n"
|
|
464
432
|
let rbrace = "}"
|
|
465
|
-
let mut strings =
|
|
466
|
-
newline,
|
|
467
|
-
slConsDisableGc(prevSpacePadding, slConsDisableGc(rbrace, SLEmpty))
|
|
468
|
-
)
|
|
433
|
+
let mut strings = [newline, prevSpacePadding, rbrace]
|
|
469
434
|
let colspace = ": "
|
|
470
435
|
let comlf = ",\n"
|
|
471
436
|
for (let mut i = recordArity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
@@ -475,58 +440,33 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
475
440
|
extraIndents + 1n,
|
|
476
441
|
false
|
|
477
442
|
)
|
|
478
|
-
strings =
|
|
479
|
-
spacePadding,
|
|
480
|
-
slConsDisableGc(
|
|
481
|
-
fieldName,
|
|
482
|
-
slConsDisableGc(colspace, slConsDisableGc(fieldValue, strings))
|
|
483
|
-
)
|
|
484
|
-
)
|
|
485
|
-
Memory.decRef(WasmI32.fromGrain(fieldValue))
|
|
443
|
+
strings = [spacePadding, fieldName, colspace, fieldValue, ...strings]
|
|
486
444
|
if (i > 0n) {
|
|
487
|
-
strings =
|
|
445
|
+
strings = [comlf, ...strings]
|
|
488
446
|
}
|
|
489
447
|
}
|
|
490
448
|
let lbrace = "{\n"
|
|
491
|
-
strings =
|
|
492
|
-
let string = join(strings)
|
|
493
|
-
|
|
494
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
495
|
-
Memory.decRef(WasmI32.fromGrain(spacePadding))
|
|
496
|
-
Memory.decRef(WasmI32.fromGrain(colspace))
|
|
497
|
-
Memory.decRef(WasmI32.fromGrain(comlf))
|
|
498
|
-
Memory.decRef(WasmI32.fromGrain(lbrace))
|
|
499
|
-
Memory.decRef(WasmI32.fromGrain(rbrace))
|
|
500
|
-
Memory.decRef(WasmI32.fromGrain(newline))
|
|
449
|
+
strings = [lbrace, ...strings]
|
|
501
450
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
string
|
|
451
|
+
join(strings)
|
|
505
452
|
}
|
|
506
453
|
},
|
|
507
454
|
t when t == Tags._GRAIN_ARRAY_HEAP_TAG => {
|
|
508
455
|
let arity = WasmI32.load(ptr, 4n)
|
|
509
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
510
456
|
let rbrack = "]"
|
|
511
|
-
let mut strings =
|
|
457
|
+
let mut strings = [rbrack]
|
|
512
458
|
let comspace = ", "
|
|
513
459
|
for (let mut i = arity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
514
460
|
let item = toStringHelp(WasmI32.load(ptr + i, 8n), extraIndents, false)
|
|
515
|
-
strings =
|
|
516
|
-
Memory.decRef(WasmI32.fromGrain(item))
|
|
461
|
+
strings = [item, ...strings]
|
|
517
462
|
if (i > 0n) {
|
|
518
|
-
strings =
|
|
463
|
+
strings = [comspace, ...strings]
|
|
519
464
|
}
|
|
520
465
|
}
|
|
521
466
|
let lbrack = "[> "
|
|
522
|
-
strings =
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
Memory.decRef(WasmI32.fromGrain(comspace))
|
|
526
|
-
Memory.decRef(WasmI32.fromGrain(lbrack))
|
|
527
|
-
Memory.decRef(WasmI32.fromGrain(rbrack))
|
|
528
|
-
|
|
529
|
-
string
|
|
467
|
+
strings = [lbrack, ...strings]
|
|
468
|
+
|
|
469
|
+
join(strings)
|
|
530
470
|
},
|
|
531
471
|
t when t == Tags._GRAIN_BOXED_NUM_HEAP_TAG => {
|
|
532
472
|
let numberTag = WasmI32.load(ptr, 4n)
|
|
@@ -537,21 +477,15 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
537
477
|
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
538
478
|
NumberUtils.itoa64(WasmI64.load(ptr, 8n), 10n)
|
|
539
479
|
},
|
|
480
|
+
t when t == Tags._GRAIN_BIGINT_BOXED_NUM_TAG => {
|
|
481
|
+
BI.bigIntToString10(ptr)
|
|
482
|
+
},
|
|
540
483
|
t when t == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG => {
|
|
541
|
-
let numerator =
|
|
542
|
-
let denominator =
|
|
543
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
484
|
+
let numerator = BI.bigIntToString10(WasmI32.load(ptr, 8n))
|
|
485
|
+
let denominator = BI.bigIntToString10(WasmI32.load(ptr, 12n))
|
|
544
486
|
let slash = "/"
|
|
545
|
-
let strings =
|
|
546
|
-
|
|
547
|
-
slConsDisableGc(slash, slConsDisableGc(denominator, SLEmpty))
|
|
548
|
-
)
|
|
549
|
-
let string = join(strings)
|
|
550
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
551
|
-
Memory.decRef(WasmI32.fromGrain(numerator))
|
|
552
|
-
Memory.decRef(WasmI32.fromGrain(denominator))
|
|
553
|
-
Memory.decRef(WasmI32.fromGrain(slash))
|
|
554
|
-
string
|
|
487
|
+
let strings = [numerator, slash, denominator]
|
|
488
|
+
join(strings)
|
|
555
489
|
},
|
|
556
490
|
t when t == Tags._GRAIN_FLOAT32_BOXED_NUM_TAG => {
|
|
557
491
|
NumberUtils.dtoa(WasmF64.promoteF32(WasmF32.load(ptr, 8n)))
|
|
@@ -571,14 +505,12 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
571
505
|
} else {
|
|
572
506
|
WasmI32.store(ptr, 0x80000000n | tupleLength, 4n)
|
|
573
507
|
let comspace = ", "
|
|
574
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
575
508
|
let rparen = ")"
|
|
576
|
-
let mut strings =
|
|
509
|
+
let mut strings = [rparen]
|
|
577
510
|
if (tupleLength <= 1n) {
|
|
578
511
|
// Special case: unary tuple
|
|
579
512
|
let comma = ","
|
|
580
|
-
strings =
|
|
581
|
-
Memory.decRef(WasmI32.fromGrain(comma))
|
|
513
|
+
strings = [comma, ...strings]
|
|
582
514
|
void
|
|
583
515
|
}
|
|
584
516
|
for (let mut i = tupleLength * 4n - 4n; i >= 0n; i -= 4n) {
|
|
@@ -587,73 +519,66 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
587
519
|
extraIndents,
|
|
588
520
|
false
|
|
589
521
|
)
|
|
590
|
-
strings =
|
|
591
|
-
Memory.decRef(WasmI32.fromGrain(item))
|
|
522
|
+
strings = [item, ...strings]
|
|
592
523
|
if (i > 0n) {
|
|
593
|
-
strings =
|
|
524
|
+
strings = [comspace, ...strings]
|
|
594
525
|
}
|
|
595
526
|
}
|
|
596
527
|
WasmI32.store(ptr, tupleLength, 4n)
|
|
597
528
|
|
|
598
529
|
Memory.incRef(WasmI32.fromGrain(strings))
|
|
599
530
|
let lparen = "("
|
|
600
|
-
strings =
|
|
531
|
+
strings = [lparen, ...strings]
|
|
601
532
|
|
|
602
|
-
|
|
603
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
604
|
-
Memory.decRef(WasmI32.fromGrain(comspace))
|
|
605
|
-
Memory.decRef(WasmI32.fromGrain(rparen))
|
|
606
|
-
Memory.decRef(WasmI32.fromGrain(lparen))
|
|
607
|
-
|
|
608
|
-
string
|
|
533
|
+
join(strings)
|
|
609
534
|
}
|
|
610
535
|
},
|
|
611
536
|
t when t == Tags._GRAIN_LAMBDA_HEAP_TAG => {
|
|
612
537
|
"<lambda>"
|
|
613
538
|
},
|
|
614
539
|
_ => {
|
|
615
|
-
|
|
616
|
-
let strings = slConsDisableGc(
|
|
540
|
+
let strings = [
|
|
617
541
|
"<unknown heap tag type: 0x",
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
slConsDisableGc(">", SLEmpty)
|
|
625
|
-
)
|
|
626
|
-
)
|
|
627
|
-
)
|
|
628
|
-
)
|
|
629
|
-
let string = join(strings)
|
|
630
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
631
|
-
string
|
|
542
|
+
NumberUtils.itoa32(tag, 16n),
|
|
543
|
+
" | value: 0x",
|
|
544
|
+
NumberUtils.itoa32(ptr, 16n),
|
|
545
|
+
">",
|
|
546
|
+
]
|
|
547
|
+
join(strings)
|
|
632
548
|
},
|
|
633
549
|
}
|
|
634
550
|
}, toStringHelp = (grainValue, extraIndents, toplevel) => {
|
|
635
551
|
if ((grainValue & 1n) != 0n) {
|
|
636
552
|
// Simple (unboxed) numbers
|
|
637
553
|
NumberUtils.itoa32(grainValue >> 1n, 10n)
|
|
638
|
-
} else if ((grainValue & 7n) == Tags._GRAIN_GENERIC_HEAP_TAG_TYPE) {
|
|
639
|
-
heapValueToString(grainValue, extraIndents, toplevel)
|
|
640
|
-
} else if (grainValue == WasmI32.fromGrain(true)) {
|
|
641
|
-
"true"
|
|
642
|
-
} else if (grainValue == WasmI32.fromGrain(false)) {
|
|
643
|
-
"false"
|
|
644
|
-
} else if (grainValue == WasmI32.fromGrain(void)) {
|
|
645
|
-
"void"
|
|
646
554
|
} else {
|
|
647
|
-
|
|
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
|
+
}
|
|
648
574
|
}
|
|
649
575
|
}, listToString = (ptr, extraIndents) => {
|
|
650
576
|
let mut cur = ptr
|
|
651
577
|
let mut isFirst = true
|
|
652
578
|
|
|
653
|
-
Memory.incRef(WasmI32.fromGrain(SLEmpty))
|
|
654
579
|
let lbrack = "["
|
|
655
580
|
let commaspace = ", "
|
|
656
|
-
let mut strings =
|
|
581
|
+
let mut strings = [lbrack]
|
|
657
582
|
|
|
658
583
|
while (true) {
|
|
659
584
|
let variantId = WasmI32.load(cur, 12n) >> 1n // tagged number
|
|
@@ -661,46 +586,30 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
661
586
|
break
|
|
662
587
|
} else {
|
|
663
588
|
if (!isFirst) {
|
|
664
|
-
strings =
|
|
589
|
+
strings = [commaspace, ...strings]
|
|
665
590
|
}
|
|
666
591
|
isFirst = false
|
|
667
592
|
let item = toStringHelp(WasmI32.load(cur, 20n), extraIndents, false)
|
|
668
|
-
strings =
|
|
669
|
-
Memory.decRef(WasmI32.fromGrain(item))
|
|
593
|
+
strings = [item, ...strings]
|
|
670
594
|
cur = WasmI32.load(cur, 24n)
|
|
671
595
|
}
|
|
672
596
|
}
|
|
673
597
|
let rbrack = "]"
|
|
674
|
-
strings =
|
|
598
|
+
strings = [rbrack, ...strings]
|
|
675
599
|
let reversed = reverse(strings)
|
|
676
|
-
|
|
677
|
-
Memory.decRef(WasmI32.fromGrain(strings))
|
|
678
|
-
Memory.decRef(WasmI32.fromGrain(reversed))
|
|
679
|
-
Memory.decRef(WasmI32.fromGrain(lbrack))
|
|
680
|
-
Memory.decRef(WasmI32.fromGrain(rbrack))
|
|
681
|
-
Memory.decRef(WasmI32.fromGrain(commaspace))
|
|
682
|
-
string
|
|
600
|
+
join(reversed)
|
|
683
601
|
}
|
|
684
602
|
|
|
685
|
-
@
|
|
686
|
-
export let
|
|
603
|
+
@unsafe
|
|
604
|
+
export let toString = value => {
|
|
687
605
|
let value = WasmI32.fromGrain(value)
|
|
688
|
-
|
|
689
|
-
Memory.decRef(value)
|
|
690
|
-
Memory.decRef(WasmI32.fromGrain(toString))
|
|
691
|
-
ret
|
|
606
|
+
toStringHelp(value, 0n, true)
|
|
692
607
|
}
|
|
693
608
|
|
|
694
|
-
@
|
|
695
|
-
export let
|
|
696
|
-
// First convert the value to string, if it isn't one already.
|
|
697
|
-
// toString will either return value instance itself if it's already a
|
|
698
|
-
// string, or a new string with the content of value object, which will need
|
|
699
|
-
// to be deallocated. In either case it's sufficient to force decrement its
|
|
700
|
-
// reference count.
|
|
609
|
+
@unsafe
|
|
610
|
+
export let print = value => {
|
|
611
|
+
// First convert the value to string, if it isn't one already.
|
|
701
612
|
let valuePtr = WasmI32.fromGrain(value)
|
|
702
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
703
|
-
Memory.incRef(valuePtr) // for function call
|
|
704
613
|
let s = toString(value)
|
|
705
614
|
let ptr = WasmI32.fromGrain(s)
|
|
706
615
|
// iov: [<ptr to string> <nbytes of string> <ptr to newline> <nbytes of newline>] (32 bytes)
|
|
@@ -717,8 +626,5 @@ export let rec print = value => {
|
|
|
717
626
|
WasmI32.store(iov, 1n, 12n)
|
|
718
627
|
fd_write(1n, iov, 2n, written)
|
|
719
628
|
Memory.free(buf)
|
|
720
|
-
Memory.decRef(ptr)
|
|
721
|
-
Memory.decRef(WasmI32.fromGrain(print))
|
|
722
|
-
Memory.decRef(WasmI32.fromGrain(value))
|
|
723
629
|
void
|
|
724
630
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
### String.**StringList**
|
|
2
|
+
|
|
3
|
+
```grain
|
|
4
|
+
type StringList
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
### String.**concat**
|
|
8
|
+
|
|
9
|
+
```grain
|
|
10
|
+
concat : (String, String) -> String
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### String.**toString**
|
|
14
|
+
|
|
15
|
+
```grain
|
|
16
|
+
toString : a -> String
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### String.**print**
|
|
20
|
+
|
|
21
|
+
```grain
|
|
22
|
+
print : a -> Void
|
|
23
|
+
```
|
|
24
|
+
|