@grain/stdlib 0.5.13 → 0.6.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 +193 -0
- package/LICENSE +1 -1
- package/README.md +25 -2
- package/array.gr +1512 -199
- package/array.md +2032 -94
- package/bigint.gr +239 -140
- package/bigint.md +450 -106
- package/buffer.gr +595 -102
- package/buffer.md +903 -145
- package/bytes.gr +401 -110
- package/bytes.md +551 -63
- package/char.gr +228 -49
- package/char.md +373 -7
- package/exception.gr +26 -12
- package/exception.md +29 -5
- package/float32.gr +130 -109
- package/float32.md +185 -57
- package/float64.gr +112 -99
- package/float64.md +185 -57
- package/hash.gr +47 -37
- package/hash.md +21 -3
- package/int16.gr +430 -0
- package/int16.md +618 -0
- package/int32.gr +200 -269
- package/int32.md +254 -289
- package/int64.gr +142 -225
- package/int64.md +254 -289
- package/int8.gr +511 -0
- package/int8.md +786 -0
- package/json.gr +2084 -0
- package/json.md +608 -0
- package/list.gr +120 -68
- package/list.md +125 -80
- package/map.gr +560 -57
- package/map.md +672 -56
- package/marshal.gr +239 -227
- package/marshal.md +36 -4
- package/number.gr +626 -676
- package/number.md +738 -153
- package/option.gr +33 -35
- package/option.md +58 -42
- package/package.json +2 -2
- package/path.gr +148 -187
- package/path.md +47 -96
- package/pervasives.gr +75 -416
- package/pervasives.md +85 -180
- package/priorityqueue.gr +433 -74
- package/priorityqueue.md +422 -54
- package/queue.gr +362 -80
- package/queue.md +433 -38
- package/random.gr +67 -75
- package/random.md +68 -40
- package/range.gr +135 -63
- package/range.md +198 -43
- package/rational.gr +284 -0
- package/rational.md +545 -0
- package/regex.gr +933 -1066
- package/regex.md +59 -60
- package/result.gr +23 -25
- package/result.md +54 -39
- package/runtime/atof/common.gr +78 -82
- package/runtime/atof/common.md +22 -10
- package/runtime/atof/decimal.gr +102 -127
- package/runtime/atof/decimal.md +28 -7
- package/runtime/atof/lemire.gr +56 -71
- package/runtime/atof/lemire.md +9 -1
- package/runtime/atof/parse.gr +83 -110
- package/runtime/atof/parse.md +12 -2
- package/runtime/atof/slow.gr +28 -35
- package/runtime/atof/slow.md +9 -1
- package/runtime/atof/table.gr +19 -18
- package/runtime/atof/table.md +10 -2
- package/runtime/atoi/parse.gr +153 -136
- package/runtime/atoi/parse.md +50 -1
- package/runtime/bigint.gr +410 -517
- package/runtime/bigint.md +71 -57
- package/runtime/compare.gr +176 -85
- package/runtime/compare.md +31 -1
- package/runtime/dataStructures.gr +144 -32
- package/runtime/dataStructures.md +267 -31
- package/runtime/debugPrint.gr +34 -15
- package/runtime/debugPrint.md +37 -5
- package/runtime/equal.gr +53 -52
- package/runtime/equal.md +30 -1
- package/runtime/exception.gr +38 -47
- package/runtime/exception.md +10 -8
- package/runtime/gc.gr +23 -152
- package/runtime/gc.md +13 -17
- package/runtime/malloc.gr +31 -31
- package/runtime/malloc.md +11 -3
- package/runtime/numberUtils.gr +191 -172
- package/runtime/numberUtils.md +17 -9
- package/runtime/numbers.gr +1695 -1021
- package/runtime/numbers.md +1098 -134
- package/runtime/string.gr +540 -242
- package/runtime/string.md +76 -6
- package/runtime/unsafe/constants.gr +30 -13
- package/runtime/unsafe/constants.md +80 -0
- package/runtime/unsafe/conv.gr +55 -28
- package/runtime/unsafe/conv.md +41 -9
- package/runtime/unsafe/memory.gr +10 -30
- package/runtime/unsafe/memory.md +15 -19
- package/runtime/unsafe/tags.gr +37 -21
- package/runtime/unsafe/tags.md +88 -8
- package/runtime/unsafe/wasmf32.gr +30 -36
- package/runtime/unsafe/wasmf32.md +64 -56
- package/runtime/unsafe/wasmf64.gr +30 -36
- package/runtime/unsafe/wasmf64.md +64 -56
- package/runtime/unsafe/wasmi32.gr +49 -66
- package/runtime/unsafe/wasmi32.md +102 -94
- package/runtime/unsafe/wasmi64.gr +52 -79
- package/runtime/unsafe/wasmi64.md +108 -100
- package/runtime/utils/printing.gr +13 -15
- package/runtime/utils/printing.md +11 -3
- package/runtime/wasi.gr +294 -295
- package/runtime/wasi.md +62 -42
- package/set.gr +574 -64
- package/set.md +634 -54
- package/stack.gr +181 -64
- package/stack.md +271 -42
- package/string.gr +453 -533
- package/string.md +241 -151
- package/uint16.gr +369 -0
- package/uint16.md +585 -0
- package/uint32.gr +470 -0
- package/uint32.md +737 -0
- package/uint64.gr +471 -0
- package/uint64.md +737 -0
- package/uint8.gr +369 -0
- package/uint8.md +585 -0
- package/uri.gr +1093 -0
- package/uri.md +477 -0
- package/{sys → wasi}/file.gr +914 -500
- package/{sys → wasi}/file.md +454 -50
- package/wasi/process.gr +292 -0
- package/{sys → wasi}/process.md +164 -6
- package/wasi/random.gr +77 -0
- package/wasi/random.md +80 -0
- package/{sys → wasi}/time.gr +15 -22
- package/{sys → wasi}/time.md +5 -5
- package/immutablearray.gr +0 -929
- package/immutablearray.md +0 -1038
- package/immutablemap.gr +0 -493
- package/immutablemap.md +0 -479
- package/immutablepriorityqueue.gr +0 -360
- package/immutablepriorityqueue.md +0 -291
- package/immutableset.gr +0 -498
- package/immutableset.md +0 -449
- package/runtime/debug.gr +0 -2
- package/runtime/debug.md +0 -6
- package/runtime/unsafe/errors.gr +0 -36
- package/runtime/unsafe/errors.md +0 -204
- package/sys/process.gr +0 -254
- package/sys/random.gr +0 -79
- package/sys/random.md +0 -66
package/runtime/string.gr
CHANGED
|
@@ -1,139 +1,244 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
primitive (!)
|
|
38
|
-
primitive (&&)
|
|
39
|
-
primitive (||)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
let
|
|
52
|
-
let
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
@noPervasives
|
|
2
|
+
module String
|
|
3
|
+
|
|
4
|
+
from "runtime/unsafe/wasmi32" include WasmI32
|
|
5
|
+
use WasmI32.{
|
|
6
|
+
(+),
|
|
7
|
+
(-),
|
|
8
|
+
(*),
|
|
9
|
+
(/),
|
|
10
|
+
remS as (%),
|
|
11
|
+
(<<),
|
|
12
|
+
(>>),
|
|
13
|
+
(&),
|
|
14
|
+
(>>>),
|
|
15
|
+
(|),
|
|
16
|
+
(==),
|
|
17
|
+
(!=),
|
|
18
|
+
(>=),
|
|
19
|
+
(>),
|
|
20
|
+
(<=),
|
|
21
|
+
(<),
|
|
22
|
+
}
|
|
23
|
+
from "runtime/unsafe/wasmi64" include WasmI64
|
|
24
|
+
from "runtime/unsafe/wasmf32" include WasmF32
|
|
25
|
+
from "runtime/unsafe/wasmf64" include WasmF64
|
|
26
|
+
from "runtime/bigint" include Bigint as BI
|
|
27
|
+
from "runtime/unsafe/memory" include Memory
|
|
28
|
+
from "runtime/unsafe/tags" include Tags
|
|
29
|
+
from "runtime/numberUtils" include NumberUtils
|
|
30
|
+
|
|
31
|
+
from "runtime/dataStructures" include DataStructures
|
|
32
|
+
use DataStructures.{ allocateString, allocateArray, untagSimpleNumber }
|
|
33
|
+
|
|
34
|
+
foreign wasm fd_write:
|
|
35
|
+
(WasmI32, WasmI32, WasmI32, WasmI32) => WasmI32 from "wasi_snapshot_preview1"
|
|
36
|
+
|
|
37
|
+
primitive (!) = "@not"
|
|
38
|
+
primitive (&&) = "@and"
|
|
39
|
+
primitive (||) = "@or"
|
|
40
|
+
primitive builtinId = "@builtin.id"
|
|
41
|
+
primitive ignore = "@ignore"
|
|
42
|
+
primitive throw = "@throw"
|
|
43
|
+
|
|
44
|
+
exception MalformedUnicode
|
|
45
|
+
|
|
46
|
+
@unsafe
|
|
47
|
+
primitive typeMetadata = "@heap.type_metadata"
|
|
48
|
+
|
|
49
|
+
@unsafe
|
|
50
|
+
let findTypeMetadata = typeHash => {
|
|
51
|
+
let typeMetadata = typeMetadata()
|
|
52
|
+
let numBuckets = WasmI32.load(typeMetadata, 0n)
|
|
53
|
+
let hashHash = typeHash % numBuckets
|
|
54
|
+
// First 8 bytes of metadata are for table size
|
|
55
|
+
let bucketPtr = typeMetadata + 8n + (hashHash << 3n) // 8 bytes/bucket
|
|
56
|
+
let bucketDataOffset = WasmI32.load(bucketPtr, 0n)
|
|
57
|
+
let bucketSize = WasmI32.load(bucketPtr, 4n)
|
|
58
|
+
let beginDataPtr = typeMetadata + bucketDataOffset
|
|
59
|
+
let endDataPtr = beginDataPtr + (bucketSize << 3n)
|
|
60
|
+
for (let mut ptr = beginDataPtr; ptr < endDataPtr; ptr += 8n) {
|
|
61
|
+
if (WasmI32.load(ptr, 0n) == typeHash) {
|
|
62
|
+
return typeMetadata + WasmI32.load(ptr, 4n)
|
|
58
63
|
}
|
|
59
|
-
metadataPtr = WasmI32.load(metadataPtr, 0n)
|
|
60
64
|
}
|
|
65
|
+
return -1n
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@unsafe
|
|
69
|
+
let _LIST_ID = untagSimpleNumber(builtinId("List"))
|
|
70
|
+
@unsafe
|
|
71
|
+
let _OPTION_ID = untagSimpleNumber(builtinId("Option"))
|
|
72
|
+
@unsafe
|
|
73
|
+
let _RESULT_ID = untagSimpleNumber(builtinId("Result"))
|
|
74
|
+
|
|
75
|
+
let _SOME = "Some"
|
|
76
|
+
let _NONE = "None"
|
|
77
|
+
let _OK = "Ok"
|
|
78
|
+
let _ERR = "Err"
|
|
79
|
+
|
|
80
|
+
// Resizable arrays: <num items> <capacity> <...data>
|
|
81
|
+
@unsafe
|
|
82
|
+
let _VEC_LEN_OFFSET = 0n
|
|
83
|
+
@unsafe
|
|
84
|
+
let _VEC_CAP_OFFSET = 4n
|
|
85
|
+
@unsafe
|
|
86
|
+
let _VEC_DATA_OFFSET = 8n
|
|
87
|
+
|
|
88
|
+
@unsafe
|
|
89
|
+
let _VISITED_BIT = 0x80000000n
|
|
90
|
+
|
|
91
|
+
@unsafe
|
|
92
|
+
let makeVecBox = () => {
|
|
93
|
+
let vecBox = Memory.malloc(4n)
|
|
94
|
+
WasmI32.store(vecBox, 0n, 0n)
|
|
95
|
+
vecBox
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@unsafe
|
|
99
|
+
let initVec = vecBox => {
|
|
100
|
+
let initCap = 4n
|
|
101
|
+
let vec = Memory.malloc(8n + initCap * 4n)
|
|
102
|
+
WasmI32.store(vec, 0n, _VEC_LEN_OFFSET)
|
|
103
|
+
WasmI32.store(vec, initCap, _VEC_CAP_OFFSET)
|
|
104
|
+
WasmI32.store(vecBox, vec, 0n)
|
|
105
|
+
vec
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@unsafe
|
|
109
|
+
let freeVecBox = vecBox => {
|
|
110
|
+
let vecPtr = WasmI32.load(vecBox, 0n)
|
|
111
|
+
if (vecPtr != 0n) {
|
|
112
|
+
Memory.free(vecPtr)
|
|
113
|
+
}
|
|
114
|
+
Memory.free(vecBox)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@unsafe
|
|
118
|
+
let vecPush = (vecBox, val) => {
|
|
119
|
+
let mut vecPtr = WasmI32.load(vecBox, 0n)
|
|
120
|
+
if (vecPtr == 0n) {
|
|
121
|
+
vecPtr = initVec(vecBox)
|
|
122
|
+
}
|
|
123
|
+
let len = WasmI32.load(vecPtr, _VEC_LEN_OFFSET)
|
|
124
|
+
let cap = WasmI32.load(vecPtr, _VEC_CAP_OFFSET)
|
|
125
|
+
if (len == cap) {
|
|
126
|
+
let newCap = cap * 2n
|
|
127
|
+
let newVec = Memory.malloc(8n + newCap * 4n)
|
|
128
|
+
Memory.copy(newVec, vecPtr, 8n + cap * 4n)
|
|
129
|
+
WasmI32.store(newVec, newCap, _VEC_CAP_OFFSET)
|
|
130
|
+
Memory.free(vecPtr)
|
|
131
|
+
WasmI32.store(vecBox, newVec, 0n)
|
|
132
|
+
vecPtr = newVec
|
|
133
|
+
}
|
|
134
|
+
WasmI32.store(vecPtr + len * 4n, val, _VEC_DATA_OFFSET)
|
|
135
|
+
WasmI32.store(vecPtr, len + 1n, _VEC_LEN_OFFSET)
|
|
136
|
+
}
|
|
61
137
|
|
|
62
|
-
|
|
63
|
-
|
|
138
|
+
@unsafe
|
|
139
|
+
let vecLen = vecBox => {
|
|
140
|
+
let vecPtr = WasmI32.load(vecBox, 0n)
|
|
141
|
+
if (vecPtr == 0n) {
|
|
142
|
+
0n
|
|
64
143
|
} else {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
typeData = modData
|
|
69
|
-
break
|
|
70
|
-
}
|
|
71
|
-
modData += WasmI32.load(modData, 0n)
|
|
72
|
-
}
|
|
144
|
+
WasmI32.load(vecPtr, _VEC_LEN_OFFSET)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
73
147
|
|
|
74
|
-
|
|
148
|
+
@unsafe
|
|
149
|
+
let vecFindIndex = (vecBox, val) => {
|
|
150
|
+
let vecPtr = WasmI32.load(vecBox, 0n)
|
|
151
|
+
let len = vecLen(vecBox)
|
|
152
|
+
for (let mut i = 0n; i < len; i += 1n) {
|
|
153
|
+
if (WasmI32.load(vecPtr + i * 4n, _VEC_DATA_OFFSET) == val) {
|
|
154
|
+
return i
|
|
155
|
+
}
|
|
75
156
|
}
|
|
157
|
+
return -1n
|
|
76
158
|
}
|
|
77
159
|
|
|
78
160
|
@unsafe
|
|
79
|
-
let
|
|
80
|
-
let moduleId = WasmI32.load(variant, 4n) >> 1n
|
|
161
|
+
let isListVariant = variant => {
|
|
81
162
|
let typeId = WasmI32.load(variant, 8n) >> 1n
|
|
82
|
-
|
|
163
|
+
typeId == _LIST_ID
|
|
164
|
+
}
|
|
83
165
|
|
|
84
|
-
|
|
166
|
+
@unsafe
|
|
167
|
+
let getBuiltinVariantName = variant => {
|
|
168
|
+
let typeId = WasmI32.load(variant, 8n) >> 1n
|
|
169
|
+
let variantId = WasmI32.load(variant, 12n) >> 1n
|
|
85
170
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
let end = block + sectionLength
|
|
93
|
-
let mut result = -1n
|
|
94
|
-
while (block < end) {
|
|
95
|
-
if (WasmI32.load(block, 4n) == variantId) {
|
|
96
|
-
let length = WasmI32.load(block, 8n)
|
|
97
|
-
let str = allocateString(length)
|
|
98
|
-
Memory.copy(str + 8n, block + 12n, length)
|
|
99
|
-
result = str
|
|
100
|
-
break
|
|
171
|
+
match (typeId) {
|
|
172
|
+
id when id == _OPTION_ID => {
|
|
173
|
+
if (variantId == 0n) {
|
|
174
|
+
Memory.incRef(WasmI32.fromGrain(_SOME))
|
|
175
|
+
} else {
|
|
176
|
+
Memory.incRef(WasmI32.fromGrain(_NONE))
|
|
101
177
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
178
|
+
},
|
|
179
|
+
id when id == _RESULT_ID => {
|
|
180
|
+
if (variantId == 0n) {
|
|
181
|
+
Memory.incRef(WasmI32.fromGrain(_OK))
|
|
182
|
+
} else {
|
|
183
|
+
Memory.incRef(WasmI32.fromGrain(_ERR))
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
_ => -1n,
|
|
106
187
|
}
|
|
107
188
|
}
|
|
108
189
|
|
|
109
190
|
@unsafe
|
|
110
|
-
let
|
|
111
|
-
let
|
|
112
|
-
|
|
113
|
-
let
|
|
191
|
+
let getFieldArray = (fields, arity) => {
|
|
192
|
+
let fieldArray = allocateArray(arity)
|
|
193
|
+
|
|
194
|
+
let mut fieldOffset = 0n
|
|
195
|
+
for (let mut i = 0n; i < arity; i += 1n) {
|
|
196
|
+
let fieldLength = WasmI32.load(fields + fieldOffset, 4n)
|
|
197
|
+
let fieldName = allocateString(fieldLength)
|
|
198
|
+
Memory.incRef(fieldName)
|
|
199
|
+
Memory.copy(fieldName + 8n, fields + fieldOffset + 8n, fieldLength)
|
|
200
|
+
WasmI32.store(fieldArray + i * 4n, fieldName, 8n)
|
|
201
|
+
|
|
202
|
+
fieldOffset += WasmI32.load(fields + fieldOffset, 0n)
|
|
203
|
+
}
|
|
114
204
|
|
|
115
|
-
|
|
205
|
+
fieldArray
|
|
206
|
+
}
|
|
116
207
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
208
|
+
@unsafe
|
|
209
|
+
let getVariantMetadata = variant => {
|
|
210
|
+
let typeHash = WasmI32.load(variant, 4n) >> 1n
|
|
211
|
+
let variantId = WasmI32.load(variant, 12n) >> 1n
|
|
121
212
|
|
|
122
|
-
|
|
213
|
+
let mut block = findTypeMetadata(typeHash)
|
|
123
214
|
|
|
124
|
-
|
|
125
|
-
for (let mut i = 0n; i < arity; i += 1n) {
|
|
126
|
-
let fieldLength = WasmI32.load(fields + fieldOffset, 4n)
|
|
127
|
-
let fieldName = allocateString(fieldLength)
|
|
128
|
-
Memory.incRef(fieldName)
|
|
129
|
-
Memory.copy(fieldName + 8n, fields + fieldOffset + 8n, fieldLength)
|
|
130
|
-
WasmI32.store(fieldArray + i * 4n, fieldName, 8n)
|
|
215
|
+
if (block == -1n) return -1n
|
|
131
216
|
|
|
132
|
-
|
|
133
|
-
|
|
217
|
+
let sectionLength = WasmI32.load(block, 0n)
|
|
218
|
+
block += 4n
|
|
134
219
|
|
|
135
|
-
|
|
220
|
+
let end = block + sectionLength
|
|
221
|
+
while (block < end) {
|
|
222
|
+
if (WasmI32.load(block, 8n) == variantId) {
|
|
223
|
+
return block
|
|
224
|
+
}
|
|
225
|
+
block += WasmI32.load(block, 0n)
|
|
136
226
|
}
|
|
227
|
+
|
|
228
|
+
return -1n
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@unsafe
|
|
232
|
+
let getRecordFieldNames = record_ => {
|
|
233
|
+
let typeHash = WasmI32.load(record_, 4n) >> 1n
|
|
234
|
+
let arity = WasmI32.load(record_, 12n)
|
|
235
|
+
|
|
236
|
+
let mut fields = findTypeMetadata(typeHash)
|
|
237
|
+
|
|
238
|
+
if (fields == -1n) return -1n
|
|
239
|
+
|
|
240
|
+
fields += 4n
|
|
241
|
+
return getFieldArray(fields, arity)
|
|
137
242
|
}
|
|
138
243
|
|
|
139
244
|
@unsafe
|
|
@@ -178,10 +283,21 @@ let reverse = list => {
|
|
|
178
283
|
iter(list, [])
|
|
179
284
|
}
|
|
180
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Concatenate two strings.
|
|
288
|
+
*
|
|
289
|
+
* @param str1: The beginning string
|
|
290
|
+
* @param str2: The ending string
|
|
291
|
+
* @returns The combined string
|
|
292
|
+
*
|
|
293
|
+
* @example "Foo" ++ "Bar" == "FooBar"
|
|
294
|
+
*
|
|
295
|
+
* @since v0.2.0
|
|
296
|
+
*/
|
|
181
297
|
@unsafe
|
|
182
|
-
|
|
183
|
-
let ptr1 = WasmI32.fromGrain(
|
|
184
|
-
let ptr2 = WasmI32.fromGrain(
|
|
298
|
+
provide let concat = (str1: String, str2: String) => {
|
|
299
|
+
let ptr1 = WasmI32.fromGrain(str1)
|
|
300
|
+
let ptr2 = WasmI32.fromGrain(str2)
|
|
185
301
|
|
|
186
302
|
let size1 = WasmI32.load(ptr1, 4n)
|
|
187
303
|
let size2 = WasmI32.load(ptr2, 4n)
|
|
@@ -218,7 +334,6 @@ let escape = (ptr, isString) => {
|
|
|
218
334
|
let byte = WasmI32.load8U(ptr + i, startOffset)
|
|
219
335
|
if (
|
|
220
336
|
byte >= _SEQ_B && byte <= _SEQ_R || /* b, f, n, r, t, v */
|
|
221
|
-
byte == _SEQ_V ||
|
|
222
337
|
byte == _SEQ_SLASH ||
|
|
223
338
|
byte == _SEQ_QUOTE
|
|
224
339
|
) {
|
|
@@ -237,7 +352,6 @@ let escape = (ptr, isString) => {
|
|
|
237
352
|
let byte = WasmI32.load8U(ptr + i, startOffset)
|
|
238
353
|
if (
|
|
239
354
|
byte >= _SEQ_B && byte <= _SEQ_R || /* b, f, n, r, t, v */
|
|
240
|
-
byte == _SEQ_V ||
|
|
241
355
|
byte == _SEQ_SLASH ||
|
|
242
356
|
byte == _SEQ_QUOTE
|
|
243
357
|
) {
|
|
@@ -296,12 +410,12 @@ let usvToString = usv => {
|
|
|
296
410
|
offset = 0xF0n
|
|
297
411
|
}
|
|
298
412
|
let string = allocateString(count + 1n)
|
|
299
|
-
WasmI32.store8(string, (usv >>> 6n * count) + offset, 8n)
|
|
413
|
+
WasmI32.store8(string, (usv >>> (6n * count)) + offset, 8n)
|
|
300
414
|
|
|
301
415
|
let mut n = 0n
|
|
302
416
|
while (count > 0n) {
|
|
303
417
|
n += 1n
|
|
304
|
-
let temp = usv >>> 6n * (count - 1n)
|
|
418
|
+
let temp = usv >>> (6n * (count - 1n))
|
|
305
419
|
WasmI32.store8(string + n, 0x80n | temp & 0x3Fn, 8n)
|
|
306
420
|
count -= 1n
|
|
307
421
|
}
|
|
@@ -311,14 +425,28 @@ let usvToString = usv => {
|
|
|
311
425
|
}
|
|
312
426
|
|
|
313
427
|
@unsafe
|
|
314
|
-
let
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
428
|
+
let reportCycle = (ptr, cycles) => {
|
|
429
|
+
let mut cycleNum = vecFindIndex(cycles, ptr)
|
|
430
|
+
if (cycleNum == -1n) {
|
|
431
|
+
cycleNum = vecLen(cycles)
|
|
432
|
+
vecPush(cycles, ptr)
|
|
433
|
+
}
|
|
434
|
+
let numStr = NumberUtils.itoa32(cycleNum + 1n, 10n)
|
|
435
|
+
join(["<cycle to <", numStr, ">>"])
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
@unsafe
|
|
439
|
+
let cyclePrefix = (ptr, cycles) => {
|
|
440
|
+
let cycleNum = vecFindIndex(cycles, ptr)
|
|
441
|
+
if (cycleNum != -1n) {
|
|
442
|
+
join(["<", NumberUtils.itoa32(cycleNum + 1n, 10n), "> "])
|
|
443
|
+
} else {
|
|
444
|
+
""
|
|
445
|
+
}
|
|
318
446
|
}
|
|
319
447
|
|
|
320
448
|
@unsafe
|
|
321
|
-
let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
449
|
+
let rec heapValueToString = (ptr, extraIndents, toplevel, cycles) => {
|
|
322
450
|
let tag = WasmI32.load(ptr, 0n)
|
|
323
451
|
match (tag) {
|
|
324
452
|
t when t == Tags._GRAIN_STRING_HEAP_TAG => {
|
|
@@ -338,9 +466,10 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
338
466
|
needsEllipsis = true
|
|
339
467
|
}
|
|
340
468
|
let headBytes = 8n // <bytes:
|
|
341
|
-
|
|
469
|
+
// This is two digits and a space for each byte, minus one space for the last byte
|
|
470
|
+
let hexBytes = numBytes * 3n - 1n
|
|
342
471
|
let tailBytes = if (needsEllipsis) {
|
|
343
|
-
|
|
472
|
+
4n // ...>
|
|
344
473
|
} else {
|
|
345
474
|
1n // >
|
|
346
475
|
}
|
|
@@ -370,38 +499,47 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
370
499
|
},
|
|
371
500
|
t when t == Tags._GRAIN_ADT_HEAP_TAG => {
|
|
372
501
|
// [ <value type tag>, <module_tag>, <type_tag>, <variant_tag>, <arity>, elts ... ]
|
|
373
|
-
let
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
502
|
+
let builtinVariantName = getBuiltinVariantName(ptr)
|
|
503
|
+
if (builtinVariantName != -1n) {
|
|
504
|
+
// Assumes that all builtin variants do not have inline record
|
|
505
|
+
// constructors; if this changes this should be changed as well
|
|
506
|
+
tupleVariantToString(
|
|
507
|
+
ptr,
|
|
508
|
+
WasmI32.toGrain(builtinVariantName),
|
|
509
|
+
extraIndents,
|
|
510
|
+
cycles
|
|
511
|
+
)
|
|
512
|
+
} else if (isListVariant(ptr)) {
|
|
513
|
+
listToString(ptr, extraIndents, cycles)
|
|
377
514
|
} else {
|
|
378
|
-
let
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
listToString(ptr, extraIndents)
|
|
515
|
+
let variantPtr = getVariantMetadata(ptr)
|
|
516
|
+
if (variantPtr == -1n) {
|
|
517
|
+
"<enum value>"
|
|
382
518
|
} else {
|
|
383
|
-
let
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
strings = [variantName,
|
|
519
|
+
let length = WasmI32.load(variantPtr, 12n)
|
|
520
|
+
let variantName = allocateString(length)
|
|
521
|
+
Memory.copy(variantName + 8n, variantPtr + 16n, length)
|
|
522
|
+
let variantName = WasmI32.toGrain(variantName): String
|
|
523
|
+
let distToRecordFields = WasmI32.load(variantPtr, 4n)
|
|
524
|
+
let isRecordVariant = distToRecordFields != 0n
|
|
525
|
+
if (isRecordVariant) {
|
|
526
|
+
let fields = variantPtr + distToRecordFields
|
|
527
|
+
let recordArity = WasmI32.load(ptr, 16n)
|
|
528
|
+
let recordVariantFields = getFieldArray(fields, recordArity)
|
|
529
|
+
let recordString = recordToString(
|
|
530
|
+
ptr,
|
|
531
|
+
recordArity,
|
|
532
|
+
recordVariantFields,
|
|
533
|
+
20n,
|
|
534
|
+
extraIndents,
|
|
535
|
+
cycles
|
|
536
|
+
)
|
|
537
|
+
Memory.decRef(recordVariantFields)
|
|
538
|
+
let strings = [variantName, recordString]
|
|
403
539
|
|
|
404
540
|
join(strings)
|
|
541
|
+
} else {
|
|
542
|
+
tupleVariantToString(ptr, variantName, extraIndents, cycles)
|
|
405
543
|
}
|
|
406
544
|
}
|
|
407
545
|
}
|
|
@@ -412,68 +550,55 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
412
550
|
if (fields == -1n) {
|
|
413
551
|
"<record value>"
|
|
414
552
|
} else {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
""
|
|
553
|
+
if ((recordArity & _VISITED_BIT) != 0n) {
|
|
554
|
+
reportCycle(ptr, cycles)
|
|
418
555
|
} else {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
let padAmount = (extraIndents + 1n) * 2n
|
|
428
|
-
let spacePadding = allocateString(padAmount)
|
|
429
|
-
Memory.fill(spacePadding + 8n, 0x20n, padAmount) // create indentation
|
|
430
|
-
let spacePadding = WasmI32.toGrain(spacePadding): String
|
|
431
|
-
let newline = "\n"
|
|
432
|
-
let rbrace = "}"
|
|
433
|
-
let mut strings = [newline, prevSpacePadding, rbrace]
|
|
434
|
-
let colspace = ": "
|
|
435
|
-
let comlf = ",\n"
|
|
436
|
-
for (let mut i = recordArity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
437
|
-
let fieldName = WasmI32.toGrain(WasmI32.load(fields + i, 8n)): String
|
|
438
|
-
let fieldValue = toStringHelp(
|
|
439
|
-
WasmI32.load(ptr + i, 16n),
|
|
440
|
-
extraIndents + 1n,
|
|
441
|
-
false
|
|
556
|
+
WasmI32.store(ptr, _VISITED_BIT | recordArity, 12n)
|
|
557
|
+
let result = recordToString(
|
|
558
|
+
ptr,
|
|
559
|
+
recordArity,
|
|
560
|
+
fields,
|
|
561
|
+
16n,
|
|
562
|
+
extraIndents,
|
|
563
|
+
cycles
|
|
442
564
|
)
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
565
|
+
Memory.decRef(fields)
|
|
566
|
+
WasmI32.store(ptr, recordArity, 12n)
|
|
567
|
+
join([cyclePrefix(ptr, cycles), result])
|
|
447
568
|
}
|
|
448
|
-
let lbrace = "{\n"
|
|
449
|
-
strings = [lbrace, ...strings]
|
|
450
|
-
|
|
451
|
-
join(strings)
|
|
452
569
|
}
|
|
453
570
|
},
|
|
454
571
|
t when t == Tags._GRAIN_ARRAY_HEAP_TAG => {
|
|
455
572
|
let arity = WasmI32.load(ptr, 4n)
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
let
|
|
461
|
-
strings = [
|
|
462
|
-
|
|
463
|
-
|
|
573
|
+
if ((arity & _VISITED_BIT) != 0n) {
|
|
574
|
+
reportCycle(ptr, cycles)
|
|
575
|
+
} else {
|
|
576
|
+
WasmI32.store(ptr, _VISITED_BIT | arity, 4n)
|
|
577
|
+
let rbrack = "]"
|
|
578
|
+
let mut strings = [rbrack]
|
|
579
|
+
let comspace = ", "
|
|
580
|
+
for (let mut i = arity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
581
|
+
let item = toStringHelp(
|
|
582
|
+
WasmI32.load(ptr + i, 8n),
|
|
583
|
+
extraIndents,
|
|
584
|
+
false,
|
|
585
|
+
cycles
|
|
586
|
+
)
|
|
587
|
+
strings = [item, ...strings]
|
|
588
|
+
if (i > 0n) {
|
|
589
|
+
strings = [comspace, ...strings]
|
|
590
|
+
}
|
|
464
591
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
592
|
+
WasmI32.store(ptr, arity, 4n)
|
|
593
|
+
let lbrack = "[> "
|
|
594
|
+
strings = [lbrack, ...strings]
|
|
468
595
|
|
|
469
|
-
|
|
596
|
+
join([cyclePrefix(ptr, cycles), ...strings])
|
|
597
|
+
}
|
|
470
598
|
},
|
|
471
599
|
t when t == Tags._GRAIN_BOXED_NUM_HEAP_TAG => {
|
|
472
600
|
let numberTag = WasmI32.load(ptr, 4n)
|
|
473
601
|
match (numberTag) {
|
|
474
|
-
t when t == Tags._GRAIN_INT32_BOXED_NUM_TAG => {
|
|
475
|
-
NumberUtils.itoa32(WasmI32.load(ptr, 8n), 10n)
|
|
476
|
-
},
|
|
477
602
|
t when t == Tags._GRAIN_INT64_BOXED_NUM_TAG => {
|
|
478
603
|
NumberUtils.itoa64(WasmI64.load(ptr, 8n), 10n)
|
|
479
604
|
},
|
|
@@ -487,9 +612,6 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
487
612
|
let strings = [numerator, slash, denominator]
|
|
488
613
|
join(strings)
|
|
489
614
|
},
|
|
490
|
-
t when t == Tags._GRAIN_FLOAT32_BOXED_NUM_TAG => {
|
|
491
|
-
NumberUtils.dtoa(WasmF64.promoteF32(WasmF32.load(ptr, 8n)))
|
|
492
|
-
},
|
|
493
615
|
t when t == Tags._GRAIN_FLOAT64_BOXED_NUM_TAG => {
|
|
494
616
|
NumberUtils.dtoa(WasmF64.load(ptr, 8n))
|
|
495
617
|
},
|
|
@@ -498,26 +620,34 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
498
620
|
},
|
|
499
621
|
}
|
|
500
622
|
},
|
|
623
|
+
t when t == Tags._GRAIN_INT32_HEAP_TAG => {
|
|
624
|
+
NumberUtils.itoa32(WasmI32.load(ptr, 4n), 10n)
|
|
625
|
+
},
|
|
626
|
+
t when t == Tags._GRAIN_FLOAT32_HEAP_TAG => {
|
|
627
|
+
NumberUtils.dtoa(WasmF64.promoteF32(WasmF32.load(ptr, 4n)))
|
|
628
|
+
},
|
|
629
|
+
t when t == Tags._GRAIN_UINT32_HEAP_TAG => {
|
|
630
|
+
NumberUtils.utoa32(WasmI32.load(ptr, 4n), 10n)
|
|
631
|
+
},
|
|
632
|
+
t when t == Tags._GRAIN_UINT64_HEAP_TAG => {
|
|
633
|
+
NumberUtils.utoa64(WasmI64.load(ptr, 8n), 10n)
|
|
634
|
+
},
|
|
501
635
|
t when t == Tags._GRAIN_TUPLE_HEAP_TAG => {
|
|
502
636
|
let tupleLength = WasmI32.load(ptr, 4n)
|
|
503
|
-
if ((tupleLength &
|
|
504
|
-
|
|
637
|
+
if ((tupleLength & _VISITED_BIT) != 0n) {
|
|
638
|
+
reportCycle(ptr, cycles)
|
|
505
639
|
} else {
|
|
506
|
-
WasmI32.store(ptr,
|
|
640
|
+
WasmI32.store(ptr, _VISITED_BIT | tupleLength, 4n)
|
|
507
641
|
let comspace = ", "
|
|
508
642
|
let rparen = ")"
|
|
643
|
+
let mut lparen = "("
|
|
509
644
|
let mut strings = [rparen]
|
|
510
|
-
if (tupleLength <= 1n) {
|
|
511
|
-
// Special case: unary tuple
|
|
512
|
-
let comma = ","
|
|
513
|
-
strings = [comma, ...strings]
|
|
514
|
-
void
|
|
515
|
-
}
|
|
516
645
|
for (let mut i = tupleLength * 4n - 4n; i >= 0n; i -= 4n) {
|
|
517
646
|
let item = toStringHelp(
|
|
518
647
|
WasmI32.load(ptr + i, 8n),
|
|
519
648
|
extraIndents,
|
|
520
|
-
false
|
|
649
|
+
false,
|
|
650
|
+
cycles
|
|
521
651
|
)
|
|
522
652
|
strings = [item, ...strings]
|
|
523
653
|
if (i > 0n) {
|
|
@@ -527,10 +657,13 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
527
657
|
WasmI32.store(ptr, tupleLength, 4n)
|
|
528
658
|
|
|
529
659
|
Memory.incRef(WasmI32.fromGrain(strings))
|
|
530
|
-
let lparen = "("
|
|
531
660
|
strings = [lparen, ...strings]
|
|
532
|
-
|
|
533
|
-
|
|
661
|
+
if (tupleLength <= 1n) {
|
|
662
|
+
// Special case: unary tuple, which is not valid Grain syntax; however, boxed values
|
|
663
|
+
// are stored as a unary tuple, so we keep this in case one gets printed
|
|
664
|
+
strings = ["box", ...strings]
|
|
665
|
+
}
|
|
666
|
+
join([cyclePrefix(ptr, cycles), ...strings])
|
|
534
667
|
}
|
|
535
668
|
},
|
|
536
669
|
t when t == Tags._GRAIN_LAMBDA_HEAP_TAG => {
|
|
@@ -547,21 +680,37 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
547
680
|
join(strings)
|
|
548
681
|
},
|
|
549
682
|
}
|
|
550
|
-
}
|
|
551
|
-
toStringHelp = (grainValue, extraIndents, toplevel) => {
|
|
683
|
+
}
|
|
684
|
+
and toStringHelp = (grainValue, extraIndents, toplevel, cycles) => {
|
|
552
685
|
if ((grainValue & 1n) != 0n) {
|
|
553
686
|
// Simple (unboxed) numbers
|
|
554
687
|
NumberUtils.itoa32(grainValue >> 1n, 10n)
|
|
555
688
|
} else {
|
|
556
689
|
let tag = grainValue & 7n
|
|
557
690
|
if (tag == Tags._GRAIN_GENERIC_HEAP_TAG_TYPE) {
|
|
558
|
-
heapValueToString(grainValue, extraIndents, toplevel)
|
|
559
|
-
} else if (tag == Tags.
|
|
560
|
-
let
|
|
561
|
-
|
|
562
|
-
|
|
691
|
+
heapValueToString(grainValue, extraIndents, toplevel, cycles)
|
|
692
|
+
} else if (tag == Tags._GRAIN_SHORTVAL_TAG_TYPE) {
|
|
693
|
+
let shortVal = grainValue >> 8n
|
|
694
|
+
let shortValTag = (grainValue & 0xF8n) >> 3n
|
|
695
|
+
if (shortValTag == Tags._GRAIN_CHAR_SHORTVAL_TAG) {
|
|
696
|
+
let string = usvToString(shortVal)
|
|
697
|
+
if (toplevel) {
|
|
698
|
+
string
|
|
699
|
+
} else {
|
|
700
|
+
escapeChar(string)
|
|
701
|
+
}
|
|
702
|
+
} else if (
|
|
703
|
+
shortValTag == Tags._GRAIN_INT8_SHORTVAL_TAG ||
|
|
704
|
+
shortValTag == Tags._GRAIN_INT16_SHORTVAL_TAG
|
|
705
|
+
) {
|
|
706
|
+
NumberUtils.itoa32(shortVal, 10n)
|
|
707
|
+
} else if (
|
|
708
|
+
shortValTag == Tags._GRAIN_UINT8_SHORTVAL_TAG ||
|
|
709
|
+
shortValTag == Tags._GRAIN_UINT16_SHORTVAL_TAG
|
|
710
|
+
) {
|
|
711
|
+
NumberUtils.utoa32(shortVal, 10n)
|
|
563
712
|
} else {
|
|
564
|
-
|
|
713
|
+
"<unknown small value>"
|
|
565
714
|
}
|
|
566
715
|
} else if (grainValue == WasmI32.fromGrain(true)) {
|
|
567
716
|
"true"
|
|
@@ -573,8 +722,8 @@ toStringHelp = (grainValue, extraIndents, toplevel) => {
|
|
|
573
722
|
"<unknown value>"
|
|
574
723
|
}
|
|
575
724
|
}
|
|
576
|
-
}
|
|
577
|
-
listToString = (ptr, extraIndents) => {
|
|
725
|
+
}
|
|
726
|
+
and listToString = (ptr, extraIndents, cycles) => {
|
|
578
727
|
let mut cur = ptr
|
|
579
728
|
let mut isFirst = true
|
|
580
729
|
|
|
@@ -584,14 +733,19 @@ listToString = (ptr, extraIndents) => {
|
|
|
584
733
|
|
|
585
734
|
while (true) {
|
|
586
735
|
let variantId = WasmI32.load(cur, 12n) >> 1n // tagged number
|
|
587
|
-
if (variantId ==
|
|
736
|
+
if (variantId == 1n) {
|
|
588
737
|
break
|
|
589
738
|
} else {
|
|
590
739
|
if (!isFirst) {
|
|
591
740
|
strings = [commaspace, ...strings]
|
|
592
741
|
}
|
|
593
742
|
isFirst = false
|
|
594
|
-
let item = toStringHelp(
|
|
743
|
+
let item = toStringHelp(
|
|
744
|
+
WasmI32.load(cur, 20n),
|
|
745
|
+
extraIndents,
|
|
746
|
+
false,
|
|
747
|
+
cycles
|
|
748
|
+
)
|
|
595
749
|
strings = [item, ...strings]
|
|
596
750
|
cur = WasmI32.load(cur, 24n)
|
|
597
751
|
}
|
|
@@ -601,32 +755,176 @@ listToString = (ptr, extraIndents) => {
|
|
|
601
755
|
let reversed = reverse(strings)
|
|
602
756
|
join(reversed)
|
|
603
757
|
}
|
|
758
|
+
and tupleVariantToString = (ptr, variantName, extraIndents, cycles) => {
|
|
759
|
+
let variantArity = WasmI32.load(ptr, 16n)
|
|
760
|
+
if (variantArity == 0n) {
|
|
761
|
+
variantName
|
|
762
|
+
} else {
|
|
763
|
+
let comspace = ", "
|
|
764
|
+
let rparen = ")"
|
|
765
|
+
let mut strings = [rparen]
|
|
766
|
+
for (let mut i = variantArity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
767
|
+
let tmp = toStringHelp(
|
|
768
|
+
WasmI32.load(ptr + i, 20n),
|
|
769
|
+
extraIndents,
|
|
770
|
+
false,
|
|
771
|
+
cycles
|
|
772
|
+
)
|
|
773
|
+
strings = [tmp, ...strings]
|
|
774
|
+
if (i > 0n) {
|
|
775
|
+
strings = [comspace, ...strings]
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
let lparen = "("
|
|
779
|
+
strings = [variantName, lparen, ...strings]
|
|
604
780
|
|
|
781
|
+
join(strings)
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
and recordToString = (
|
|
785
|
+
ptr,
|
|
786
|
+
recordArity,
|
|
787
|
+
fields,
|
|
788
|
+
contentOffset,
|
|
789
|
+
extraIndents,
|
|
790
|
+
cycles,
|
|
791
|
+
) => {
|
|
792
|
+
let prevPadAmount = extraIndents * 2n
|
|
793
|
+
let prevSpacePadding = if (prevPadAmount == 0n) {
|
|
794
|
+
""
|
|
795
|
+
} else {
|
|
796
|
+
let v = allocateString(prevPadAmount)
|
|
797
|
+
Memory.fill(v + 8n, 0x20n, prevPadAmount) // create indentation for closing brace
|
|
798
|
+
WasmI32.toGrain(v): String
|
|
799
|
+
}
|
|
800
|
+
let padAmount = (extraIndents + 1n) * 2n
|
|
801
|
+
let spacePadding = allocateString(padAmount)
|
|
802
|
+
Memory.fill(spacePadding + 8n, 0x20n, padAmount) // create indentation
|
|
803
|
+
let spacePadding = WasmI32.toGrain(spacePadding): String
|
|
804
|
+
let newline = "\n"
|
|
805
|
+
let rbrace = "}"
|
|
806
|
+
let mut strings = [newline, prevSpacePadding, rbrace]
|
|
807
|
+
let colspace = ": "
|
|
808
|
+
let comlf = ",\n"
|
|
809
|
+
for (let mut i = recordArity * 4n - 4n; i >= 0n; i -= 4n) {
|
|
810
|
+
let fieldName = WasmI32.toGrain(WasmI32.load(fields + i, 8n)): String
|
|
811
|
+
let fieldValue = toStringHelp(
|
|
812
|
+
WasmI32.load(ptr + i, contentOffset),
|
|
813
|
+
extraIndents + 1n,
|
|
814
|
+
false,
|
|
815
|
+
cycles
|
|
816
|
+
)
|
|
817
|
+
strings = [spacePadding, fieldName, colspace, fieldValue, ...strings]
|
|
818
|
+
if (i > 0n) {
|
|
819
|
+
strings = [comlf, ...strings]
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
let lbrace = "{\n"
|
|
823
|
+
strings = [lbrace, ...strings]
|
|
824
|
+
|
|
825
|
+
join(strings)
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/**
|
|
829
|
+
* Converts the given operand to a string.
|
|
830
|
+
* Provides a better representation of data types if those types are provided from the module.
|
|
831
|
+
*
|
|
832
|
+
* @param value: The operand
|
|
833
|
+
* @returns The operand, as a string
|
|
834
|
+
*
|
|
835
|
+
* @since v0.1.0
|
|
836
|
+
*/
|
|
605
837
|
@unsafe
|
|
606
|
-
|
|
607
|
-
let
|
|
608
|
-
|
|
838
|
+
provide let toString = value => {
|
|
839
|
+
let ptr = WasmI32.fromGrain(value)
|
|
840
|
+
let cycles = makeVecBox()
|
|
841
|
+
let string = toStringHelp(ptr, 0n, true, cycles)
|
|
842
|
+
freeVecBox(cycles)
|
|
843
|
+
// Prevent the tail call to allow the value to stay alive
|
|
844
|
+
// while we operate on the raw pointer
|
|
845
|
+
ignore(value)
|
|
846
|
+
string
|
|
609
847
|
}
|
|
610
848
|
|
|
849
|
+
/**
|
|
850
|
+
* Prints the given operand to the console. Works for any type. Internally, calls `toString`
|
|
851
|
+
* on the operand, so a better representation of data type will be printed if those types
|
|
852
|
+
* are provided from the module.
|
|
853
|
+
*
|
|
854
|
+
* @param value: The operand
|
|
855
|
+
* @param suffix: The string to print after the argument
|
|
856
|
+
*
|
|
857
|
+
* @since v0.1.0
|
|
858
|
+
*/
|
|
611
859
|
@unsafe
|
|
612
|
-
|
|
860
|
+
provide let print = (value, suffix="\n") => {
|
|
613
861
|
// First convert the value to string, if it isn't one already.
|
|
614
862
|
let valuePtr = WasmI32.fromGrain(value)
|
|
615
863
|
let s = toString(value)
|
|
616
864
|
let ptr = WasmI32.fromGrain(s)
|
|
617
|
-
|
|
618
|
-
//
|
|
865
|
+
let suffixPtr = WasmI32.fromGrain(suffix)
|
|
866
|
+
// iov: [<ptr to string> <nbytes of string> <ptr to end sequence> <nbytes of end sequence>] (32 bytes)
|
|
867
|
+
// buf: <iov> <written>
|
|
619
868
|
// fd_write(STDOUT (1), iov, len(iov), written)
|
|
620
|
-
let buf = Memory.malloc(
|
|
869
|
+
let buf = Memory.malloc(36n)
|
|
621
870
|
let iov = buf
|
|
622
871
|
let written = buf + 32n
|
|
623
|
-
let lf = buf + 36n
|
|
624
872
|
WasmI32.store(iov, ptr + 8n, 0n)
|
|
625
873
|
WasmI32.store(iov, WasmI32.load(ptr, 4n), 4n)
|
|
626
|
-
WasmI32.
|
|
627
|
-
WasmI32.store(iov,
|
|
628
|
-
WasmI32.store(iov, 1n, 12n)
|
|
874
|
+
WasmI32.store(iov, suffixPtr + 8n, 8n)
|
|
875
|
+
WasmI32.store(iov, WasmI32.load(suffixPtr, 4n), 12n)
|
|
629
876
|
fd_write(1n, iov, 2n, written)
|
|
630
877
|
Memory.free(buf)
|
|
631
878
|
void
|
|
632
879
|
}
|
|
880
|
+
|
|
881
|
+
@unsafe
|
|
882
|
+
provide let getCodePoint = (ptr: WasmI32) => {
|
|
883
|
+
// Algorithm from https://encoding.spec.whatwg.org/#utf-8-decoder
|
|
884
|
+
use WasmI32.{ (+), (&), (|), (<<), leU as (<=), geU as (>=), (==) }
|
|
885
|
+
|
|
886
|
+
let mut codePoint = 0n
|
|
887
|
+
let mut bytesSeen = 0n
|
|
888
|
+
let mut bytesNeeded = 0n
|
|
889
|
+
let mut lowerBoundary = 0x80n
|
|
890
|
+
let mut upperBoundary = 0xBFn
|
|
891
|
+
|
|
892
|
+
let mut offset = 0n
|
|
893
|
+
|
|
894
|
+
while (true) {
|
|
895
|
+
let byte = WasmI32.load8U(ptr + offset, 0n)
|
|
896
|
+
offset += 1n
|
|
897
|
+
if (bytesNeeded == 0n) {
|
|
898
|
+
if (byte >= 0x00n && byte <= 0x7Fn) {
|
|
899
|
+
return byte
|
|
900
|
+
} else if (byte >= 0xC2n && byte <= 0xDFn) {
|
|
901
|
+
bytesNeeded = 1n
|
|
902
|
+
codePoint = byte & 0x1Fn
|
|
903
|
+
} else if (byte >= 0xE0n && byte <= 0xEFn) {
|
|
904
|
+
if (byte == 0xE0n) lowerBoundary = 0xA0n
|
|
905
|
+
if (byte == 0xEDn) upperBoundary = 0x9Fn
|
|
906
|
+
bytesNeeded = 2n
|
|
907
|
+
codePoint = byte & 0xFn
|
|
908
|
+
} else if (byte >= 0xF0n && byte <= 0xF4n) {
|
|
909
|
+
if (byte == 0xF0n) lowerBoundary = 0x90n
|
|
910
|
+
if (byte == 0xF4n) upperBoundary = 0x8Fn
|
|
911
|
+
bytesNeeded = 3n
|
|
912
|
+
codePoint = byte & 0x7n
|
|
913
|
+
} else {
|
|
914
|
+
throw MalformedUnicode
|
|
915
|
+
}
|
|
916
|
+
continue
|
|
917
|
+
}
|
|
918
|
+
if (!(lowerBoundary <= byte && byte <= upperBoundary)) {
|
|
919
|
+
throw MalformedUnicode
|
|
920
|
+
}
|
|
921
|
+
lowerBoundary = 0x80n
|
|
922
|
+
upperBoundary = 0xBFn
|
|
923
|
+
codePoint = codePoint << 6n | byte & 0x3Fn
|
|
924
|
+
bytesSeen += 1n
|
|
925
|
+
if (bytesSeen == bytesNeeded) {
|
|
926
|
+
return codePoint
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
return 0n
|
|
930
|
+
}
|