toilscript 0.0.1 → 0.1.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/LICENSE +201 -201
- package/NOTICE +94 -94
- package/README.md +101 -114
- package/bin/asc.js +0 -0
- package/bin/asinit.js +6 -6
- package/dist/asc.generated.d.ts +10027 -0
- package/dist/asc.js +24474 -0
- package/dist/asc.js.map +7 -0
- package/dist/importmap.json +9 -0
- package/dist/toilscript.generated.d.ts +11242 -0
- package/dist/toilscript.js +337 -0
- package/dist/toilscript.js.map +7 -0
- package/dist/web.js +22 -0
- package/lib/binaryen.d.ts +2 -2
- package/lib/binaryen.js +2 -2
- package/package.json +115 -114
- package/std/README.md +6 -6
- package/std/assembly/array.ts +550 -550
- package/std/assembly/arraybuffer.ts +77 -77
- package/std/assembly/atomics.ts +127 -127
- package/std/assembly/bindings/asyncify.ts +16 -16
- package/std/assembly/bindings/dom.ts +291 -291
- package/std/assembly/bindings/node.ts +6 -6
- package/std/assembly/bitflags.ts +53 -53
- package/std/assembly/builtins.ts +2650 -2650
- package/std/assembly/byteslice.ts +177 -177
- package/std/assembly/compat.ts +2 -2
- package/std/assembly/console.ts +42 -42
- package/std/assembly/crypto.ts +9 -9
- package/std/assembly/dataview.ts +181 -181
- package/std/assembly/date.ts +375 -375
- package/std/assembly/diagnostics.ts +11 -11
- package/std/assembly/encoding.ts +151 -151
- package/std/assembly/endian.ts +45 -45
- package/std/assembly/error.ts +44 -44
- package/std/assembly/fixedarray.ts +173 -173
- package/std/assembly/fixedmap.ts +326 -326
- package/std/assembly/fixedset.ts +275 -275
- package/std/assembly/function.ts +42 -42
- package/std/assembly/index.d.ts +2892 -2891
- package/std/assembly/iterator.ts +35 -35
- package/std/assembly/map.ts +269 -269
- package/std/assembly/math.ts +3289 -3289
- package/std/assembly/memory.ts +123 -123
- package/std/assembly/number.ts +388 -388
- package/std/assembly/object.ts +36 -36
- package/std/assembly/performance.ts +9 -9
- package/std/assembly/pointer.ts +80 -80
- package/std/assembly/polyfills.ts +27 -27
- package/std/assembly/process.ts +50 -50
- package/std/assembly/reference.ts +48 -48
- package/std/assembly/regexp.ts +12 -12
- package/std/assembly/rt/README.md +83 -83
- package/std/assembly/rt/common.ts +81 -81
- package/std/assembly/rt/index-incremental.ts +2 -2
- package/std/assembly/rt/index-memory.ts +1 -1
- package/std/assembly/rt/index-minimal.ts +2 -2
- package/std/assembly/rt/index-stub.ts +1 -1
- package/std/assembly/rt/index.d.ts +37 -37
- package/std/assembly/rt/itcms.ts +419 -419
- package/std/assembly/rt/memory-runtime.ts +94 -94
- package/std/assembly/rt/rtrace.ts +15 -15
- package/std/assembly/rt/stub.ts +133 -133
- package/std/assembly/rt/tcms.ts +254 -254
- package/std/assembly/rt/tlsf.ts +592 -592
- package/std/assembly/rt.ts +90 -90
- package/std/assembly/set.ts +225 -225
- package/std/assembly/shared/feature.ts +68 -68
- package/std/assembly/shared/runtime.ts +13 -13
- package/std/assembly/shared/target.ts +11 -11
- package/std/assembly/shared/tsconfig.json +11 -11
- package/std/assembly/shared/typeinfo.ts +72 -72
- package/std/assembly/staticarray.ts +423 -423
- package/std/assembly/string.ts +850 -850
- package/std/assembly/symbol.ts +114 -114
- package/std/assembly/table.ts +16 -16
- package/std/assembly/toilscript.ts +16 -0
- package/std/assembly/tsconfig.json +6 -6
- package/std/assembly/typedarray.ts +1954 -1954
- package/std/assembly/uri.ts +17 -17
- package/std/assembly/util/bytes.ts +107 -107
- package/std/assembly/util/casemap.ts +497 -497
- package/std/assembly/util/error.ts +58 -58
- package/std/assembly/util/hash.ts +117 -117
- package/std/assembly/util/math.ts +1922 -1922
- package/std/assembly/util/memory.ts +290 -290
- package/std/assembly/util/number.ts +873 -873
- package/std/assembly/util/sort.ts +313 -313
- package/std/assembly/util/string.ts +1202 -1202
- package/std/assembly/util/uri.ts +275 -275
- package/std/assembly/vector.ts +4 -4
- package/std/assembly.json +16 -16
- package/std/portable/index.d.ts +461 -461
- package/std/portable/index.js +416 -416
- package/std/portable.json +11 -11
- package/std/types/assembly/index.d.ts +1 -1
- package/std/types/assembly/package.json +2 -2
- package/std/types/portable/index.d.ts +1 -1
- package/std/types/portable/package.json +2 -2
- package/tsconfig-base.json +13 -13
- package/util/README.md +23 -23
- package/util/browser/fs.js +1 -1
- package/util/browser/module.js +5 -5
- package/util/browser/path.js +520 -520
- package/util/browser/process.js +59 -59
- package/util/browser/url.js +23 -23
- package/util/cpu.d.ts +9 -9
- package/util/cpu.js +42 -42
- package/util/find.d.ts +6 -6
- package/util/find.js +20 -20
- package/util/node.d.ts +21 -21
- package/util/node.js +34 -34
- package/util/options.d.ts +70 -70
- package/util/options.js +262 -262
- package/util/terminal.d.ts +52 -52
- package/util/terminal.js +35 -35
- package/util/text.d.ts +26 -26
- package/util/text.js +114 -114
- package/util/tsconfig.json +9 -9
- package/util/web.d.ts +11 -11
- package/util/web.js +33 -33
package/std/assembly/fixedset.ts
CHANGED
|
@@ -1,275 +1,275 @@
|
|
|
1
|
-
/// <reference path="./rt/index.d.ts" />
|
|
2
|
-
|
|
3
|
-
import { HASH } from "./util/hash";
|
|
4
|
-
import { Runtime } from "shared/runtime";
|
|
5
|
-
|
|
6
|
-
// Open-addressing hash set with linear probing.
|
|
7
|
-
// Single contiguous buffer, cache-friendly, zero GC overhead under runtime=memory.
|
|
8
|
-
|
|
9
|
-
// @ts-ignore: decorator
|
|
10
|
-
@inline const SLOT_EMPTY: u8 = 0;
|
|
11
|
-
// @ts-ignore: decorator
|
|
12
|
-
@inline const SLOT_OCCUPIED: u8 = 1;
|
|
13
|
-
// @ts-ignore: decorator
|
|
14
|
-
@inline const SLOT_DELETED: u8 = 2;
|
|
15
|
-
|
|
16
|
-
// @ts-ignore: decorator
|
|
17
|
-
@inline const FS_INITIAL_CAPACITY: i32 = 16;
|
|
18
|
-
|
|
19
|
-
// Max load factor 75% = 3/4
|
|
20
|
-
// @ts-ignore: decorator
|
|
21
|
-
@inline const FS_LOAD_N: i32 = 3;
|
|
22
|
-
// @ts-ignore: decorator
|
|
23
|
-
@inline const FS_LOAD_D: i32 = 4;
|
|
24
|
-
|
|
25
|
-
/** Structure of a FixedSet slot. */
|
|
26
|
-
@unmanaged class FixedSetSlot<T> {
|
|
27
|
-
hash: u32;
|
|
28
|
-
state: u8;
|
|
29
|
-
key: T;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Computes the alignment of a slot. */
|
|
33
|
-
// @ts-ignore: decorator
|
|
34
|
-
@inline
|
|
35
|
-
function FS_SLOT_ALIGN<T>(): usize {
|
|
36
|
-
const maxAll = sizeof<T>() > sizeof<u32>() ? sizeof<T>() : sizeof<u32>();
|
|
37
|
-
return maxAll - 1;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Computes the aligned size of a slot. */
|
|
41
|
-
// @ts-ignore: decorator
|
|
42
|
-
@inline
|
|
43
|
-
function FS_SLOT_SIZE<T>(): usize {
|
|
44
|
-
const align = FS_SLOT_ALIGN<T>();
|
|
45
|
-
return (offsetof<FixedSetSlot<T>>() + align) & ~align;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
@final
|
|
49
|
-
export class FixedSet<T> {
|
|
50
|
-
|
|
51
|
-
private dataPtr: usize = 0;
|
|
52
|
-
private _capacity: i32 = 0;
|
|
53
|
-
private capacityMask: u32 = 0;
|
|
54
|
-
private _count: i32 = 0;
|
|
55
|
-
private _entriesUsed: i32 = 0;
|
|
56
|
-
|
|
57
|
-
constructor(initialCapacity: i32 = FS_INITIAL_CAPACITY) {
|
|
58
|
-
if (initialCapacity < 4) initialCapacity = 4;
|
|
59
|
-
let cap: i32 = 4;
|
|
60
|
-
while (cap < initialCapacity) cap <<= 1;
|
|
61
|
-
|
|
62
|
-
let bufferSize = <usize>cap * FS_SLOT_SIZE<T>();
|
|
63
|
-
let ptr: usize;
|
|
64
|
-
if (ASC_RUNTIME == Runtime.Memory) {
|
|
65
|
-
ptr = __alloc(bufferSize);
|
|
66
|
-
} else {
|
|
67
|
-
ptr = __new(bufferSize, idof<ArrayBuffer>());
|
|
68
|
-
}
|
|
69
|
-
memory.fill(ptr, 0, bufferSize);
|
|
70
|
-
this.dataPtr = ptr;
|
|
71
|
-
this._capacity = cap;
|
|
72
|
-
this.capacityMask = <u32>(cap - 1);
|
|
73
|
-
if (ASC_RUNTIME != Runtime.Memory) {
|
|
74
|
-
__link(changetype<usize>(this), ptr, false);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
get size(): i32 {
|
|
79
|
-
return this._count;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@operator("[]")
|
|
83
|
-
has(key: T): bool {
|
|
84
|
-
return this.findSlot(key, HASH<T>(key)) != -1;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
add(key: T): this {
|
|
88
|
-
// Check load factor before insert
|
|
89
|
-
if (this._entriesUsed * FS_LOAD_D >= this._capacity * FS_LOAD_N) {
|
|
90
|
-
this.rehash(
|
|
91
|
-
this._count * 2 > this._capacity
|
|
92
|
-
? this._capacity << 1
|
|
93
|
-
: this._capacity
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
let hashCode = HASH<T>(key);
|
|
98
|
-
let mask = this.capacityMask;
|
|
99
|
-
let start = hashCode & mask;
|
|
100
|
-
let i = start;
|
|
101
|
-
let data = this.dataPtr;
|
|
102
|
-
let slotSize = FS_SLOT_SIZE<T>();
|
|
103
|
-
let firstDeleted: i32 = -1;
|
|
104
|
-
|
|
105
|
-
do {
|
|
106
|
-
let slot = changetype<FixedSetSlot<T>>(data + <usize>i * slotSize);
|
|
107
|
-
let state = slot.state;
|
|
108
|
-
|
|
109
|
-
if (state == SLOT_OCCUPIED) {
|
|
110
|
-
if (slot.hash == hashCode && slot.key == key) {
|
|
111
|
-
return this; // already exists
|
|
112
|
-
}
|
|
113
|
-
} else if (state == SLOT_EMPTY) {
|
|
114
|
-
let insertIdx: u32 = firstDeleted != -1 ? <u32>firstDeleted : i;
|
|
115
|
-
let insertSlot = changetype<FixedSetSlot<T>>(data + <usize>insertIdx * slotSize);
|
|
116
|
-
insertSlot.hash = hashCode;
|
|
117
|
-
insertSlot.state = SLOT_OCCUPIED;
|
|
118
|
-
insertSlot.key = key;
|
|
119
|
-
++this._count;
|
|
120
|
-
if (firstDeleted == -1) ++this._entriesUsed;
|
|
121
|
-
if (isManaged<T>()) {
|
|
122
|
-
if (ASC_RUNTIME != Runtime.Memory) {
|
|
123
|
-
__link(changetype<usize>(this), changetype<usize>(key), true);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return this;
|
|
127
|
-
} else { // DELETED
|
|
128
|
-
if (firstDeleted == -1) firstDeleted = <i32>i;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
i = (i + 1) & mask;
|
|
132
|
-
} while (i != start);
|
|
133
|
-
|
|
134
|
-
// Fallback: insert at firstDeleted
|
|
135
|
-
if (firstDeleted != -1) {
|
|
136
|
-
let insertSlot = changetype<FixedSetSlot<T>>(data + <usize>firstDeleted * slotSize);
|
|
137
|
-
insertSlot.hash = hashCode;
|
|
138
|
-
insertSlot.state = SLOT_OCCUPIED;
|
|
139
|
-
insertSlot.key = key;
|
|
140
|
-
++this._count;
|
|
141
|
-
if (isManaged<T>()) {
|
|
142
|
-
if (ASC_RUNTIME != Runtime.Memory) {
|
|
143
|
-
__link(changetype<usize>(this), changetype<usize>(key), true);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
return this;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
@operator("[]=")
|
|
151
|
-
private __set(key: T, value: bool): void {
|
|
152
|
-
if (value) this.add(key);
|
|
153
|
-
else this.delete(key);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
delete(key: T): bool {
|
|
157
|
-
let idx = this.findSlot(key, HASH<T>(key));
|
|
158
|
-
if (idx == -1) return false;
|
|
159
|
-
let slot = changetype<FixedSetSlot<T>>(
|
|
160
|
-
this.dataPtr + <usize>idx * FS_SLOT_SIZE<T>()
|
|
161
|
-
);
|
|
162
|
-
slot.state = SLOT_DELETED;
|
|
163
|
-
--this._count;
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
clear(): void {
|
|
168
|
-
memory.fill(this.dataPtr, 0, <usize>this._capacity * FS_SLOT_SIZE<T>());
|
|
169
|
-
this._count = 0;
|
|
170
|
-
this._entriesUsed = 0;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
values(): T[] {
|
|
174
|
-
let data = this.dataPtr;
|
|
175
|
-
let cap = this._capacity;
|
|
176
|
-
let slotSize = FS_SLOT_SIZE<T>();
|
|
177
|
-
let values = new Array<T>(this._count);
|
|
178
|
-
let length = 0;
|
|
179
|
-
for (let i = 0; i < cap; ++i) {
|
|
180
|
-
let slot = changetype<FixedSetSlot<T>>(data + <usize>i * slotSize);
|
|
181
|
-
if (slot.state == SLOT_OCCUPIED) {
|
|
182
|
-
unchecked(values[length++] = slot.key);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
values.length = length;
|
|
186
|
-
return values;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
toString(): string {
|
|
190
|
-
return "[object FixedSet]";
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
@inline
|
|
194
|
-
private findSlot(key: T, hashCode: u32): i32 {
|
|
195
|
-
let mask = this.capacityMask;
|
|
196
|
-
let start = hashCode & mask;
|
|
197
|
-
let i = start;
|
|
198
|
-
let data = this.dataPtr;
|
|
199
|
-
let slotSize = FS_SLOT_SIZE<T>();
|
|
200
|
-
do {
|
|
201
|
-
let slot = changetype<FixedSetSlot<T>>(data + <usize>i * slotSize);
|
|
202
|
-
let state = slot.state;
|
|
203
|
-
if (state == SLOT_EMPTY) return -1;
|
|
204
|
-
if (state == SLOT_OCCUPIED && slot.hash == hashCode && slot.key == key) {
|
|
205
|
-
return <i32>i;
|
|
206
|
-
}
|
|
207
|
-
i = (i + 1) & mask;
|
|
208
|
-
} while (i != start);
|
|
209
|
-
return -1;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
private rehash(newCapacity: i32): void {
|
|
213
|
-
let oldData = this.dataPtr;
|
|
214
|
-
let oldCapacity = this._capacity;
|
|
215
|
-
let slotSize = FS_SLOT_SIZE<T>();
|
|
216
|
-
let newMask = <u32>(newCapacity - 1);
|
|
217
|
-
let bufferSize = <usize>newCapacity * slotSize;
|
|
218
|
-
|
|
219
|
-
let newData: usize;
|
|
220
|
-
if (ASC_RUNTIME == Runtime.Memory) {
|
|
221
|
-
newData = __alloc(bufferSize);
|
|
222
|
-
} else {
|
|
223
|
-
newData = __new(bufferSize, idof<ArrayBuffer>());
|
|
224
|
-
}
|
|
225
|
-
memory.fill(newData, 0, bufferSize);
|
|
226
|
-
|
|
227
|
-
for (let i = 0; i < oldCapacity; ++i) {
|
|
228
|
-
let oldSlot = changetype<FixedSetSlot<T>>(oldData + <usize>i * slotSize);
|
|
229
|
-
if (oldSlot.state == SLOT_OCCUPIED) {
|
|
230
|
-
let h = oldSlot.hash;
|
|
231
|
-
let j = h & newMask;
|
|
232
|
-
while (changetype<FixedSetSlot<T>>(newData + <usize>j * slotSize).state != SLOT_EMPTY) {
|
|
233
|
-
j = (j + 1) & newMask;
|
|
234
|
-
}
|
|
235
|
-
let newSlot = changetype<FixedSetSlot<T>>(newData + <usize>j * slotSize);
|
|
236
|
-
newSlot.hash = h;
|
|
237
|
-
newSlot.state = SLOT_OCCUPIED;
|
|
238
|
-
newSlot.key = oldSlot.key;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
this.dataPtr = newData;
|
|
243
|
-
this._capacity = newCapacity;
|
|
244
|
-
this.capacityMask = newMask;
|
|
245
|
-
this._entriesUsed = this._count;
|
|
246
|
-
|
|
247
|
-
if (ASC_RUNTIME != Runtime.Memory) {
|
|
248
|
-
__link(changetype<usize>(this), newData, false);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// RT integration
|
|
253
|
-
|
|
254
|
-
@unsafe private __visit(cookie: u32): void {
|
|
255
|
-
if (ASC_RUNTIME != Runtime.Memory) {
|
|
256
|
-
let data = this.dataPtr;
|
|
257
|
-
if (data) {
|
|
258
|
-
if (isManaged<T>()) {
|
|
259
|
-
let cap = this._capacity;
|
|
260
|
-
let slotSize = FS_SLOT_SIZE<T>();
|
|
261
|
-
for (let i = 0; i < cap; ++i) {
|
|
262
|
-
let slot = changetype<FixedSetSlot<T>>(data + <usize>i * slotSize);
|
|
263
|
-
if (slot.state == SLOT_OCCUPIED) {
|
|
264
|
-
let val = changetype<usize>(slot.key);
|
|
265
|
-
if (isNullable<T>()) {
|
|
266
|
-
if (val) __visit(val, cookie);
|
|
267
|
-
} else __visit(val, cookie);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
__visit(data, cookie);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
1
|
+
/// <reference path="./rt/index.d.ts" />
|
|
2
|
+
|
|
3
|
+
import { HASH } from "./util/hash";
|
|
4
|
+
import { Runtime } from "shared/runtime";
|
|
5
|
+
|
|
6
|
+
// Open-addressing hash set with linear probing.
|
|
7
|
+
// Single contiguous buffer, cache-friendly, zero GC overhead under runtime=memory.
|
|
8
|
+
|
|
9
|
+
// @ts-ignore: decorator
|
|
10
|
+
@inline const SLOT_EMPTY: u8 = 0;
|
|
11
|
+
// @ts-ignore: decorator
|
|
12
|
+
@inline const SLOT_OCCUPIED: u8 = 1;
|
|
13
|
+
// @ts-ignore: decorator
|
|
14
|
+
@inline const SLOT_DELETED: u8 = 2;
|
|
15
|
+
|
|
16
|
+
// @ts-ignore: decorator
|
|
17
|
+
@inline const FS_INITIAL_CAPACITY: i32 = 16;
|
|
18
|
+
|
|
19
|
+
// Max load factor 75% = 3/4
|
|
20
|
+
// @ts-ignore: decorator
|
|
21
|
+
@inline const FS_LOAD_N: i32 = 3;
|
|
22
|
+
// @ts-ignore: decorator
|
|
23
|
+
@inline const FS_LOAD_D: i32 = 4;
|
|
24
|
+
|
|
25
|
+
/** Structure of a FixedSet slot. */
|
|
26
|
+
@unmanaged class FixedSetSlot<T> {
|
|
27
|
+
hash: u32;
|
|
28
|
+
state: u8;
|
|
29
|
+
key: T;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Computes the alignment of a slot. */
|
|
33
|
+
// @ts-ignore: decorator
|
|
34
|
+
@inline
|
|
35
|
+
function FS_SLOT_ALIGN<T>(): usize {
|
|
36
|
+
const maxAll = sizeof<T>() > sizeof<u32>() ? sizeof<T>() : sizeof<u32>();
|
|
37
|
+
return maxAll - 1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Computes the aligned size of a slot. */
|
|
41
|
+
// @ts-ignore: decorator
|
|
42
|
+
@inline
|
|
43
|
+
function FS_SLOT_SIZE<T>(): usize {
|
|
44
|
+
const align = FS_SLOT_ALIGN<T>();
|
|
45
|
+
return (offsetof<FixedSetSlot<T>>() + align) & ~align;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@final
|
|
49
|
+
export class FixedSet<T> {
|
|
50
|
+
|
|
51
|
+
private dataPtr: usize = 0;
|
|
52
|
+
private _capacity: i32 = 0;
|
|
53
|
+
private capacityMask: u32 = 0;
|
|
54
|
+
private _count: i32 = 0;
|
|
55
|
+
private _entriesUsed: i32 = 0;
|
|
56
|
+
|
|
57
|
+
constructor(initialCapacity: i32 = FS_INITIAL_CAPACITY) {
|
|
58
|
+
if (initialCapacity < 4) initialCapacity = 4;
|
|
59
|
+
let cap: i32 = 4;
|
|
60
|
+
while (cap < initialCapacity) cap <<= 1;
|
|
61
|
+
|
|
62
|
+
let bufferSize = <usize>cap * FS_SLOT_SIZE<T>();
|
|
63
|
+
let ptr: usize;
|
|
64
|
+
if (ASC_RUNTIME == Runtime.Memory) {
|
|
65
|
+
ptr = __alloc(bufferSize);
|
|
66
|
+
} else {
|
|
67
|
+
ptr = __new(bufferSize, idof<ArrayBuffer>());
|
|
68
|
+
}
|
|
69
|
+
memory.fill(ptr, 0, bufferSize);
|
|
70
|
+
this.dataPtr = ptr;
|
|
71
|
+
this._capacity = cap;
|
|
72
|
+
this.capacityMask = <u32>(cap - 1);
|
|
73
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
74
|
+
__link(changetype<usize>(this), ptr, false);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get size(): i32 {
|
|
79
|
+
return this._count;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@operator("[]")
|
|
83
|
+
has(key: T): bool {
|
|
84
|
+
return this.findSlot(key, HASH<T>(key)) != -1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
add(key: T): this {
|
|
88
|
+
// Check load factor before insert
|
|
89
|
+
if (this._entriesUsed * FS_LOAD_D >= this._capacity * FS_LOAD_N) {
|
|
90
|
+
this.rehash(
|
|
91
|
+
this._count * 2 > this._capacity
|
|
92
|
+
? this._capacity << 1
|
|
93
|
+
: this._capacity
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let hashCode = HASH<T>(key);
|
|
98
|
+
let mask = this.capacityMask;
|
|
99
|
+
let start = hashCode & mask;
|
|
100
|
+
let i = start;
|
|
101
|
+
let data = this.dataPtr;
|
|
102
|
+
let slotSize = FS_SLOT_SIZE<T>();
|
|
103
|
+
let firstDeleted: i32 = -1;
|
|
104
|
+
|
|
105
|
+
do {
|
|
106
|
+
let slot = changetype<FixedSetSlot<T>>(data + <usize>i * slotSize);
|
|
107
|
+
let state = slot.state;
|
|
108
|
+
|
|
109
|
+
if (state == SLOT_OCCUPIED) {
|
|
110
|
+
if (slot.hash == hashCode && slot.key == key) {
|
|
111
|
+
return this; // already exists
|
|
112
|
+
}
|
|
113
|
+
} else if (state == SLOT_EMPTY) {
|
|
114
|
+
let insertIdx: u32 = firstDeleted != -1 ? <u32>firstDeleted : i;
|
|
115
|
+
let insertSlot = changetype<FixedSetSlot<T>>(data + <usize>insertIdx * slotSize);
|
|
116
|
+
insertSlot.hash = hashCode;
|
|
117
|
+
insertSlot.state = SLOT_OCCUPIED;
|
|
118
|
+
insertSlot.key = key;
|
|
119
|
+
++this._count;
|
|
120
|
+
if (firstDeleted == -1) ++this._entriesUsed;
|
|
121
|
+
if (isManaged<T>()) {
|
|
122
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
123
|
+
__link(changetype<usize>(this), changetype<usize>(key), true);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return this;
|
|
127
|
+
} else { // DELETED
|
|
128
|
+
if (firstDeleted == -1) firstDeleted = <i32>i;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
i = (i + 1) & mask;
|
|
132
|
+
} while (i != start);
|
|
133
|
+
|
|
134
|
+
// Fallback: insert at firstDeleted
|
|
135
|
+
if (firstDeleted != -1) {
|
|
136
|
+
let insertSlot = changetype<FixedSetSlot<T>>(data + <usize>firstDeleted * slotSize);
|
|
137
|
+
insertSlot.hash = hashCode;
|
|
138
|
+
insertSlot.state = SLOT_OCCUPIED;
|
|
139
|
+
insertSlot.key = key;
|
|
140
|
+
++this._count;
|
|
141
|
+
if (isManaged<T>()) {
|
|
142
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
143
|
+
__link(changetype<usize>(this), changetype<usize>(key), true);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@operator("[]=")
|
|
151
|
+
private __set(key: T, value: bool): void {
|
|
152
|
+
if (value) this.add(key);
|
|
153
|
+
else this.delete(key);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
delete(key: T): bool {
|
|
157
|
+
let idx = this.findSlot(key, HASH<T>(key));
|
|
158
|
+
if (idx == -1) return false;
|
|
159
|
+
let slot = changetype<FixedSetSlot<T>>(
|
|
160
|
+
this.dataPtr + <usize>idx * FS_SLOT_SIZE<T>()
|
|
161
|
+
);
|
|
162
|
+
slot.state = SLOT_DELETED;
|
|
163
|
+
--this._count;
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
clear(): void {
|
|
168
|
+
memory.fill(this.dataPtr, 0, <usize>this._capacity * FS_SLOT_SIZE<T>());
|
|
169
|
+
this._count = 0;
|
|
170
|
+
this._entriesUsed = 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
values(): T[] {
|
|
174
|
+
let data = this.dataPtr;
|
|
175
|
+
let cap = this._capacity;
|
|
176
|
+
let slotSize = FS_SLOT_SIZE<T>();
|
|
177
|
+
let values = new Array<T>(this._count);
|
|
178
|
+
let length = 0;
|
|
179
|
+
for (let i = 0; i < cap; ++i) {
|
|
180
|
+
let slot = changetype<FixedSetSlot<T>>(data + <usize>i * slotSize);
|
|
181
|
+
if (slot.state == SLOT_OCCUPIED) {
|
|
182
|
+
unchecked(values[length++] = slot.key);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
values.length = length;
|
|
186
|
+
return values;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
toString(): string {
|
|
190
|
+
return "[object FixedSet]";
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@inline
|
|
194
|
+
private findSlot(key: T, hashCode: u32): i32 {
|
|
195
|
+
let mask = this.capacityMask;
|
|
196
|
+
let start = hashCode & mask;
|
|
197
|
+
let i = start;
|
|
198
|
+
let data = this.dataPtr;
|
|
199
|
+
let slotSize = FS_SLOT_SIZE<T>();
|
|
200
|
+
do {
|
|
201
|
+
let slot = changetype<FixedSetSlot<T>>(data + <usize>i * slotSize);
|
|
202
|
+
let state = slot.state;
|
|
203
|
+
if (state == SLOT_EMPTY) return -1;
|
|
204
|
+
if (state == SLOT_OCCUPIED && slot.hash == hashCode && slot.key == key) {
|
|
205
|
+
return <i32>i;
|
|
206
|
+
}
|
|
207
|
+
i = (i + 1) & mask;
|
|
208
|
+
} while (i != start);
|
|
209
|
+
return -1;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private rehash(newCapacity: i32): void {
|
|
213
|
+
let oldData = this.dataPtr;
|
|
214
|
+
let oldCapacity = this._capacity;
|
|
215
|
+
let slotSize = FS_SLOT_SIZE<T>();
|
|
216
|
+
let newMask = <u32>(newCapacity - 1);
|
|
217
|
+
let bufferSize = <usize>newCapacity * slotSize;
|
|
218
|
+
|
|
219
|
+
let newData: usize;
|
|
220
|
+
if (ASC_RUNTIME == Runtime.Memory) {
|
|
221
|
+
newData = __alloc(bufferSize);
|
|
222
|
+
} else {
|
|
223
|
+
newData = __new(bufferSize, idof<ArrayBuffer>());
|
|
224
|
+
}
|
|
225
|
+
memory.fill(newData, 0, bufferSize);
|
|
226
|
+
|
|
227
|
+
for (let i = 0; i < oldCapacity; ++i) {
|
|
228
|
+
let oldSlot = changetype<FixedSetSlot<T>>(oldData + <usize>i * slotSize);
|
|
229
|
+
if (oldSlot.state == SLOT_OCCUPIED) {
|
|
230
|
+
let h = oldSlot.hash;
|
|
231
|
+
let j = h & newMask;
|
|
232
|
+
while (changetype<FixedSetSlot<T>>(newData + <usize>j * slotSize).state != SLOT_EMPTY) {
|
|
233
|
+
j = (j + 1) & newMask;
|
|
234
|
+
}
|
|
235
|
+
let newSlot = changetype<FixedSetSlot<T>>(newData + <usize>j * slotSize);
|
|
236
|
+
newSlot.hash = h;
|
|
237
|
+
newSlot.state = SLOT_OCCUPIED;
|
|
238
|
+
newSlot.key = oldSlot.key;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
this.dataPtr = newData;
|
|
243
|
+
this._capacity = newCapacity;
|
|
244
|
+
this.capacityMask = newMask;
|
|
245
|
+
this._entriesUsed = this._count;
|
|
246
|
+
|
|
247
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
248
|
+
__link(changetype<usize>(this), newData, false);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// RT integration
|
|
253
|
+
|
|
254
|
+
@unsafe private __visit(cookie: u32): void {
|
|
255
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
256
|
+
let data = this.dataPtr;
|
|
257
|
+
if (data) {
|
|
258
|
+
if (isManaged<T>()) {
|
|
259
|
+
let cap = this._capacity;
|
|
260
|
+
let slotSize = FS_SLOT_SIZE<T>();
|
|
261
|
+
for (let i = 0; i < cap; ++i) {
|
|
262
|
+
let slot = changetype<FixedSetSlot<T>>(data + <usize>i * slotSize);
|
|
263
|
+
if (slot.state == SLOT_OCCUPIED) {
|
|
264
|
+
let val = changetype<usize>(slot.key);
|
|
265
|
+
if (isNullable<T>()) {
|
|
266
|
+
if (val) __visit(val, cookie);
|
|
267
|
+
} else __visit(val, cookie);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
__visit(data, cookie);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
package/std/assembly/function.ts
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import { Runtime } from "shared/runtime";
|
|
2
|
-
|
|
3
|
-
type auto = i32;
|
|
4
|
-
|
|
5
|
-
@final export abstract class Function<T> {
|
|
6
|
-
private _index: u32;
|
|
7
|
-
private _env: usize;
|
|
8
|
-
|
|
9
|
-
// @ts-ignore: this on getter
|
|
10
|
-
get index(this: T): u32 {
|
|
11
|
-
return load<u32>(changetype<usize>(this), offsetof<Function<T>>("_index"));
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// @ts-ignore: this on getter
|
|
15
|
-
get name(this: T): string {
|
|
16
|
-
return "";
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// @ts-ignore: this on getter
|
|
20
|
-
get length(this: T): i32 {
|
|
21
|
-
// @ts-ignore: T is function
|
|
22
|
-
return lengthof<T>();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// @ts-ignore: T is function
|
|
26
|
-
@builtin call(thisArg: thisof<T> | null, ...args: auto[]): returnof<T> {
|
|
27
|
-
return unreachable();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
toString(this: T): string {
|
|
31
|
-
return "function() { [native code] }";
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// RT integration
|
|
35
|
-
|
|
36
|
-
@unsafe private __visit(cookie: u32): void {
|
|
37
|
-
if (ASC_RUNTIME != Runtime.Memory) {
|
|
38
|
-
// Env is either `null` (nop) or compiler-generated
|
|
39
|
-
__visit(this._env, cookie);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
1
|
+
import { Runtime } from "shared/runtime";
|
|
2
|
+
|
|
3
|
+
type auto = i32;
|
|
4
|
+
|
|
5
|
+
@final export abstract class Function<T> {
|
|
6
|
+
private _index: u32;
|
|
7
|
+
private _env: usize;
|
|
8
|
+
|
|
9
|
+
// @ts-ignore: this on getter
|
|
10
|
+
get index(this: T): u32 {
|
|
11
|
+
return load<u32>(changetype<usize>(this), offsetof<Function<T>>("_index"));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// @ts-ignore: this on getter
|
|
15
|
+
get name(this: T): string {
|
|
16
|
+
return "";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// @ts-ignore: this on getter
|
|
20
|
+
get length(this: T): i32 {
|
|
21
|
+
// @ts-ignore: T is function
|
|
22
|
+
return lengthof<T>();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// @ts-ignore: T is function
|
|
26
|
+
@builtin call(thisArg: thisof<T> | null, ...args: auto[]): returnof<T> {
|
|
27
|
+
return unreachable();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
toString(this: T): string {
|
|
31
|
+
return "function() { [native code] }";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// RT integration
|
|
35
|
+
|
|
36
|
+
@unsafe private __visit(cookie: u32): void {
|
|
37
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
38
|
+
// Env is either `null` (nop) or compiler-generated
|
|
39
|
+
__visit(this._env, cookie);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|