toilscript 0.0.1 → 0.1.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.
Files changed (120) hide show
  1. package/LICENSE +201 -201
  2. package/NOTICE +94 -94
  3. package/README.md +101 -114
  4. package/bin/asc.js +0 -0
  5. package/bin/asinit.js +0 -0
  6. package/dist/asc.generated.d.ts +10022 -0
  7. package/dist/asc.js +24457 -0
  8. package/dist/asc.js.map +7 -0
  9. package/dist/importmap.json +9 -0
  10. package/dist/toilscript.generated.d.ts +11237 -0
  11. package/dist/toilscript.js +337 -0
  12. package/dist/toilscript.js.map +7 -0
  13. package/dist/web.js +22 -0
  14. package/lib/binaryen.d.ts +2 -2
  15. package/lib/binaryen.js +2 -2
  16. package/package.json +115 -114
  17. package/std/README.md +6 -6
  18. package/std/assembly/array.ts +550 -550
  19. package/std/assembly/arraybuffer.ts +77 -77
  20. package/std/assembly/atomics.ts +127 -127
  21. package/std/assembly/bindings/asyncify.ts +16 -16
  22. package/std/assembly/bindings/dom.ts +291 -291
  23. package/std/assembly/bindings/node.ts +6 -6
  24. package/std/assembly/bitflags.ts +53 -53
  25. package/std/assembly/builtins.ts +2650 -2650
  26. package/std/assembly/byteslice.ts +177 -177
  27. package/std/assembly/compat.ts +2 -2
  28. package/std/assembly/console.ts +42 -42
  29. package/std/assembly/crypto.ts +9 -9
  30. package/std/assembly/dataview.ts +181 -181
  31. package/std/assembly/date.ts +375 -375
  32. package/std/assembly/diagnostics.ts +11 -11
  33. package/std/assembly/encoding.ts +151 -151
  34. package/std/assembly/endian.ts +45 -45
  35. package/std/assembly/error.ts +44 -44
  36. package/std/assembly/fixedarray.ts +173 -173
  37. package/std/assembly/fixedmap.ts +326 -326
  38. package/std/assembly/fixedset.ts +275 -275
  39. package/std/assembly/function.ts +42 -42
  40. package/std/assembly/index.d.ts +2891 -2891
  41. package/std/assembly/iterator.ts +35 -35
  42. package/std/assembly/map.ts +269 -269
  43. package/std/assembly/math.ts +3289 -3289
  44. package/std/assembly/memory.ts +123 -123
  45. package/std/assembly/number.ts +388 -388
  46. package/std/assembly/object.ts +36 -36
  47. package/std/assembly/performance.ts +9 -9
  48. package/std/assembly/pointer.ts +80 -80
  49. package/std/assembly/polyfills.ts +27 -27
  50. package/std/assembly/process.ts +50 -50
  51. package/std/assembly/reference.ts +48 -48
  52. package/std/assembly/regexp.ts +12 -12
  53. package/std/assembly/rt/README.md +83 -83
  54. package/std/assembly/rt/common.ts +81 -81
  55. package/std/assembly/rt/index-incremental.ts +2 -2
  56. package/std/assembly/rt/index-memory.ts +1 -1
  57. package/std/assembly/rt/index-minimal.ts +2 -2
  58. package/std/assembly/rt/index-stub.ts +1 -1
  59. package/std/assembly/rt/index.d.ts +37 -37
  60. package/std/assembly/rt/itcms.ts +419 -419
  61. package/std/assembly/rt/memory-runtime.ts +94 -94
  62. package/std/assembly/rt/rtrace.ts +15 -15
  63. package/std/assembly/rt/stub.ts +133 -133
  64. package/std/assembly/rt/tcms.ts +254 -254
  65. package/std/assembly/rt/tlsf.ts +592 -592
  66. package/std/assembly/rt.ts +90 -90
  67. package/std/assembly/set.ts +225 -225
  68. package/std/assembly/shared/feature.ts +68 -68
  69. package/std/assembly/shared/runtime.ts +13 -13
  70. package/std/assembly/shared/target.ts +11 -11
  71. package/std/assembly/shared/tsconfig.json +11 -11
  72. package/std/assembly/shared/typeinfo.ts +72 -72
  73. package/std/assembly/staticarray.ts +423 -423
  74. package/std/assembly/string.ts +850 -850
  75. package/std/assembly/symbol.ts +114 -114
  76. package/std/assembly/table.ts +16 -16
  77. package/std/assembly/tsconfig.json +6 -6
  78. package/std/assembly/typedarray.ts +1954 -1954
  79. package/std/assembly/uri.ts +17 -17
  80. package/std/assembly/util/bytes.ts +107 -107
  81. package/std/assembly/util/casemap.ts +497 -497
  82. package/std/assembly/util/error.ts +58 -58
  83. package/std/assembly/util/hash.ts +117 -117
  84. package/std/assembly/util/math.ts +1922 -1922
  85. package/std/assembly/util/memory.ts +290 -290
  86. package/std/assembly/util/number.ts +873 -873
  87. package/std/assembly/util/sort.ts +313 -313
  88. package/std/assembly/util/string.ts +1202 -1202
  89. package/std/assembly/util/uri.ts +275 -275
  90. package/std/assembly/vector.ts +4 -4
  91. package/std/assembly.json +16 -16
  92. package/std/portable/index.d.ts +461 -461
  93. package/std/portable/index.js +416 -416
  94. package/std/portable.json +11 -11
  95. package/std/types/assembly/index.d.ts +1 -1
  96. package/std/types/assembly/package.json +2 -2
  97. package/std/types/portable/index.d.ts +1 -1
  98. package/std/types/portable/package.json +2 -2
  99. package/tsconfig-base.json +13 -13
  100. package/util/README.md +23 -23
  101. package/util/browser/fs.js +1 -1
  102. package/util/browser/module.js +5 -5
  103. package/util/browser/path.js +520 -520
  104. package/util/browser/process.js +59 -59
  105. package/util/browser/url.js +23 -23
  106. package/util/cpu.d.ts +9 -9
  107. package/util/cpu.js +42 -42
  108. package/util/find.d.ts +6 -6
  109. package/util/find.js +20 -20
  110. package/util/node.d.ts +21 -21
  111. package/util/node.js +34 -34
  112. package/util/options.d.ts +70 -70
  113. package/util/options.js +262 -262
  114. package/util/terminal.d.ts +52 -52
  115. package/util/terminal.js +35 -35
  116. package/util/text.d.ts +26 -26
  117. package/util/text.js +114 -114
  118. package/util/tsconfig.json +9 -9
  119. package/util/web.d.ts +11 -11
  120. package/util/web.js +33 -33
@@ -1,550 +1,550 @@
1
- /// <reference path="./rt/index.d.ts" />
2
-
3
- import { BLOCK_MAXSIZE } from "./rt/common";
4
- import { Runtime } from "shared/runtime";
5
- import { COMPARATOR, SORT } from "./util/sort";
6
- import { REVERSE, FILL } from "./util/bytes";
7
- import { joinBooleanArray, joinIntegerArray, joinFloatArray, joinStringArray, joinReferenceArray } from "./util/string";
8
- import { idof, isArray as builtin_isArray } from "./builtins";
9
- import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_EMPTYARRAY, E_HOLEYARRAY } from "./util/error";
10
-
11
- // @ts-ignore: decorator
12
- @inline @lazy const MIN_SIZE: usize = 8;
13
-
14
- /** Ensures that the given array has _at least_ the specified backing size. */
15
- function ensureCapacity(array: usize, newSize: usize, alignLog2: u32, canGrow: bool = true): void {
16
- // Depends on the fact that Arrays mimic ArrayBufferView
17
- let oldCapacity = <usize>changetype<ArrayBufferView>(array).byteLength;
18
- if (newSize > oldCapacity >>> alignLog2) {
19
- if (newSize > BLOCK_MAXSIZE >>> alignLog2) throw new RangeError(E_INVALIDLENGTH);
20
- let oldData = changetype<usize>(changetype<ArrayBufferView>(array).buffer);
21
- // Grows old capacity by factor of two.
22
- // Make sure we don't reach BLOCK_MAXSIZE for new growed capacity.
23
- let newCapacity = max(newSize, MIN_SIZE) << alignLog2;
24
- if (canGrow) newCapacity = max(min(oldCapacity << 1, BLOCK_MAXSIZE), newCapacity);
25
- let newData = __renew(oldData, newCapacity);
26
- // __new / __renew already init memory range as zeros in Incremental runtime.
27
- // So try to avoid this.
28
- if (ASC_RUNTIME != Runtime.Incremental) {
29
- memory.fill(newData + oldCapacity, 0, newCapacity - oldCapacity);
30
- }
31
- if (newData != oldData) { // oldData has been free'd
32
- store<usize>(array, newData, offsetof<ArrayBufferView>("buffer"));
33
- store<usize>(array, newData, offsetof<ArrayBufferView>("dataStart"));
34
- if (ASC_RUNTIME != Runtime.Memory) {
35
- __link(array, changetype<usize>(newData), false);
36
- }
37
- }
38
- store<u32>(array, <u32>newCapacity, offsetof<ArrayBufferView>("byteLength"));
39
- }
40
- }
41
-
42
- export class Array<T> {
43
- [key: number]: T;
44
-
45
- // Mimicking ArrayBufferView isn't strictly necessary here but is done to allow glue code
46
- // to work with typed and normal arrays interchangeably. Technically, normal arrays do not need
47
- // `dataStart` (equals `buffer`) and `byteLength` (equals computed `buffer.byteLength`), but the
48
- // block is 16 bytes anyway so it's fine to have a couple extra fields in there.
49
-
50
- private buffer: ArrayBuffer;
51
- @unsafe readonly dataStart: usize;
52
- private byteLength: i32; // Uses here as capacity
53
-
54
- // Also note that Array<T> with non-nullable T must guard against uninitialized null values
55
- // whenever an element is accessed. Otherwise, the compiler wouldn't be able to guarantee
56
- // type-safety anymore. For lack of a better word, such an array is "holey".
57
-
58
- private length_: i32;
59
-
60
- static isArray<U>(value: U): bool {
61
- return isReference<U>() ? changetype<usize>(value) != 0 && builtin_isArray(value) : false;
62
- }
63
-
64
- static create<T>(capacity: i32 = 0): Array<T> {
65
- WARNING("'Array.create' is deprecated. Use 'new Array' instead, making sure initial elements are initialized.");
66
- let array = new Array<T>(capacity);
67
- array.length = 0;
68
- return array;
69
- }
70
-
71
- constructor(length: i32 = 0) {
72
- if (<u32>length > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new RangeError(E_INVALIDLENGTH);
73
- // reserve capacity for at least MIN_SIZE elements
74
- let bufferSize = max(<usize>length, MIN_SIZE) << alignof<T>();
75
- let buffer = changetype<ArrayBuffer>(__new(bufferSize, idof<ArrayBuffer>()));
76
- if (ASC_RUNTIME != Runtime.Incremental) {
77
- memory.fill(changetype<usize>(buffer), 0, bufferSize);
78
- }
79
- this.buffer = buffer; // links
80
- this.dataStart = changetype<usize>(buffer);
81
- this.byteLength = <i32>bufferSize;
82
- this.length_ = length;
83
- }
84
-
85
- get length(): i32 {
86
- return this.length_;
87
- }
88
-
89
- set length(newLength: i32) {
90
- ensureCapacity(changetype<usize>(this), newLength, alignof<T>(), false);
91
- this.length_ = newLength;
92
- }
93
-
94
- every(fn: (value: T, index: i32, array: Array<T>) => bool): bool {
95
- for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
96
- if (!fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this)) return false;
97
- }
98
- return true;
99
- }
100
-
101
- findIndex(fn: (value: T, index: i32, array: Array<T>) => bool): i32 {
102
- for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
103
- if (fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this)) return i;
104
- }
105
- return -1;
106
- }
107
-
108
- findLastIndex(fn: (value: T, index: i32, array: Array<T>) => bool): i32 {
109
- for (let i = this.length_ - 1; i >= 0; --i) {
110
- if (fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this)) return i;
111
- }
112
- return -1;
113
- }
114
-
115
- @operator("[]") private __get(index: i32): T {
116
- if (<u32>index >= <u32>this.length_) throw new RangeError(E_INDEXOUTOFRANGE);
117
- let value = load<T>(this.dataStart + (<usize>index << alignof<T>()));
118
- if (isReference<T>()) {
119
- if (!isNullable<T>()) {
120
- if (!changetype<usize>(value)) throw new Error(E_HOLEYARRAY);
121
- }
122
- }
123
- return value;
124
- }
125
-
126
- @unsafe @operator("{}") private __uget(index: i32): T {
127
- return load<T>(this.dataStart + (<usize>index << alignof<T>()));
128
- }
129
-
130
- @operator("[]=") private __set(index: i32, value: T): void {
131
- if (<u32>index >= <u32>this.length_) {
132
- if (index < 0) throw new RangeError(E_INDEXOUTOFRANGE);
133
- ensureCapacity(changetype<usize>(this), index + 1, alignof<T>());
134
- this.length_ = index + 1;
135
- }
136
- store<T>(this.dataStart + (<usize>index << alignof<T>()), value);
137
- if (isManaged<T>()) {
138
- if (ASC_RUNTIME != Runtime.Memory) {
139
- __link(changetype<usize>(this), changetype<usize>(value), true);
140
- }
141
- }
142
- }
143
-
144
- at(index: i32): T {
145
- let len = this.length_;
146
- index += select(0, len, index >= 0);
147
- if (<u32>index >= <u32>len) throw new RangeError(E_INDEXOUTOFRANGE);
148
- let value = load<T>(this.dataStart + (<usize>index << alignof<T>()));
149
- if (isReference<T>()) {
150
- if (!isNullable<T>()) {
151
- if (!changetype<usize>(value)) throw new Error(E_HOLEYARRAY);
152
- }
153
- }
154
- return value;
155
- }
156
-
157
- fill(value: T, start: i32 = 0, end: i32 = i32.MAX_VALUE): Array<T> {
158
- if (isManaged<T>()) {
159
- FILL<usize>(this.dataStart, this.length_, changetype<usize>(value), start, end);
160
- if (ASC_RUNTIME != Runtime.Memory) {
161
- __link(changetype<usize>(this), changetype<usize>(value), false);
162
- }
163
- } else {
164
- FILL<T>(this.dataStart, this.length_, value, start, end);
165
- }
166
- return this;
167
- }
168
-
169
- includes(value: T, fromIndex: i32 = 0): bool {
170
- if (isFloat<T>()) {
171
- let len = this.length_;
172
- if (len == 0 || fromIndex >= len) return false;
173
- if (fromIndex < 0) fromIndex = max(len + fromIndex, 0);
174
- let ptr = this.dataStart;
175
- while (fromIndex < len) {
176
- let elem = load<T>(ptr + (<usize>fromIndex << alignof<T>()));
177
- // @ts-ignore
178
- if (elem == value || isNaN(elem) & isNaN(value)) return true;
179
- ++fromIndex;
180
- }
181
- return false;
182
- } else {
183
- return this.indexOf(value, fromIndex) >= 0;
184
- }
185
- }
186
-
187
- indexOf(value: T, fromIndex: i32 = 0): i32 {
188
- let len = this.length_;
189
- if (len == 0 || fromIndex >= len) return -1;
190
- if (fromIndex < 0) fromIndex = max(len + fromIndex, 0);
191
- let ptr = this.dataStart;
192
- while (fromIndex < len) {
193
- if (load<T>(ptr + (<usize>fromIndex << alignof<T>())) == value) return fromIndex;
194
- ++fromIndex;
195
- }
196
- return -1;
197
- }
198
-
199
- lastIndexOf(value: T, fromIndex: i32 = this.length_): i32 {
200
- let len = this.length_;
201
- if (len == 0) return -1;
202
- if (fromIndex < 0) fromIndex = len + fromIndex;
203
- else if (fromIndex >= len) fromIndex = len - 1;
204
- let ptr = this.dataStart;
205
- while (fromIndex >= 0) {
206
- if (load<T>(ptr + (<usize>fromIndex << alignof<T>())) == value) return fromIndex;
207
- --fromIndex;
208
- }
209
- return -1;
210
- }
211
-
212
- push(value: T): i32 {
213
- let oldLen = this.length_;
214
- let len = oldLen + 1;
215
- ensureCapacity(changetype<usize>(this), len, alignof<T>());
216
- if (isManaged<T>()) {
217
- store<usize>(this.dataStart + (<usize>oldLen << alignof<T>()), changetype<usize>(value));
218
- if (ASC_RUNTIME != Runtime.Memory) {
219
- __link(changetype<usize>(this), changetype<usize>(value), true);
220
- }
221
- } else {
222
- store<T>(this.dataStart + (<usize>oldLen << alignof<T>()), value);
223
- }
224
- this.length_ = len;
225
- return len;
226
- }
227
-
228
- concat(other: Array<T>): Array<T> {
229
- let thisLen = this.length_;
230
- let otherLen = other.length_;
231
- let outLen = thisLen + otherLen;
232
- if (<u32>outLen > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new Error(E_INVALIDLENGTH);
233
- let out = changetype<Array<T>>(__newArray(outLen, alignof<T>(), idof<Array<T>>()));
234
- let outStart = out.dataStart;
235
- let thisSize = <usize>thisLen << alignof<T>();
236
- if (isManaged<T>()) {
237
- let thisStart = this.dataStart;
238
- for (let offset: usize = 0; offset < thisSize; offset += sizeof<T>()) {
239
- let ref = load<usize>(thisStart + offset);
240
- store<usize>(outStart + offset, ref);
241
- if (ASC_RUNTIME != Runtime.Memory) {
242
- __link(changetype<usize>(out), ref, true);
243
- }
244
- }
245
- outStart += thisSize;
246
- let otherStart = other.dataStart;
247
- let otherSize = <usize>otherLen << alignof<T>();
248
- for (let offset: usize = 0; offset < otherSize; offset += sizeof<T>()) {
249
- let ref = load<usize>(otherStart + offset);
250
- store<usize>(outStart + offset, ref);
251
- if (ASC_RUNTIME != Runtime.Memory) {
252
- __link(changetype<usize>(out), ref, true);
253
- }
254
- }
255
- } else {
256
- memory.copy(outStart, this.dataStart, thisSize);
257
- memory.copy(outStart + thisSize, other.dataStart, <usize>otherLen << alignof<T>());
258
- }
259
- return out;
260
- }
261
-
262
- copyWithin(target: i32, start: i32, end: i32 = i32.MAX_VALUE): Array<T> {
263
- let ptr = this.dataStart;
264
- let len = this.length_;
265
-
266
- end = min<i32>(end, len);
267
-
268
- let to = target < 0 ? max(len + target, 0) : min(target, len);
269
- let from = start < 0 ? max(len + start, 0) : min(start, len);
270
- let last = end < 0 ? max(len + end, 0) : min(end, len);
271
- let count = min(last - from, len - to);
272
-
273
- memory.copy( // is memmove
274
- ptr + (<usize>to << alignof<T>()),
275
- ptr + (<usize>from << alignof<T>()),
276
- <usize>count << alignof<T>()
277
- );
278
- return this;
279
- }
280
-
281
- pop(): T {
282
- let len = this.length_;
283
- if (len < 1) throw new RangeError(E_EMPTYARRAY);
284
- let val = load<T>(this.dataStart + (<usize>(--len) << alignof<T>()));
285
- this.length_ = len;
286
- return val;
287
- }
288
-
289
- forEach(fn: (value: T, index: i32, array: Array<T>) => void): void {
290
- for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
291
- fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this);
292
- }
293
- }
294
-
295
- map<U>(fn: (value: T, index: i32, array: Array<T>) => U): Array<U> {
296
- let len = this.length_;
297
- let out = changetype<Array<U>>(__newArray(len, alignof<U>(), idof<Array<U>>()));
298
- let outStart = out.dataStart;
299
- for (let i = 0; i < min(len, this.length_); ++i) {
300
- let result = fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this);
301
- store<U>(outStart + (<usize>i << alignof<U>()), result);
302
- if (isManaged<U>()) {
303
- if (ASC_RUNTIME != Runtime.Memory) {
304
- __link(changetype<usize>(out), changetype<usize>(result), true);
305
- }
306
- }
307
- }
308
- return out;
309
- }
310
-
311
- filter(fn: (value: T, index: i32, array: Array<T>) => bool): Array<T> {
312
- let result = changetype<Array<T>>(__newArray(0, alignof<T>(), idof<Array<T>>()));
313
- for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
314
- let value = load<T>(this.dataStart + (<usize>i << alignof<T>()));
315
- if (fn(value, i, this)) result.push(value);
316
- }
317
- return result;
318
- }
319
-
320
- reduce<U>(
321
- fn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U,
322
- initialValue: U
323
- ): U {
324
- let acc = initialValue;
325
- for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
326
- acc = fn(acc, load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this);
327
- }
328
- return acc;
329
- }
330
-
331
- reduceRight<U>(
332
- fn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U,
333
- initialValue: U
334
- ): U {
335
- let acc = initialValue;
336
- for (let i = this.length_ - 1; i >= 0; --i) {
337
- acc = fn(acc, load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this);
338
- }
339
- return acc;
340
- }
341
-
342
- shift(): T {
343
- let len = this.length_;
344
- if (len < 1) throw new RangeError(E_EMPTYARRAY);
345
- let base = this.dataStart;
346
- let element = load<T>(base);
347
- let lastIndex = len - 1;
348
- memory.copy(
349
- base,
350
- base + sizeof<T>(),
351
- <usize>lastIndex << alignof<T>()
352
- );
353
- if (isReference<T>()) {
354
- store<usize>(base + (<usize>lastIndex << alignof<T>()), 0);
355
- } else {
356
- // @ts-ignore
357
- store<T>(base + (<usize>lastIndex << alignof<T>()), <T>0);
358
- }
359
- this.length_ = lastIndex;
360
- return element;
361
- }
362
-
363
- some(fn: (value: T, index: i32, array: Array<T>) => bool): bool {
364
- for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
365
- if (fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this)) return true;
366
- }
367
- return false;
368
- }
369
-
370
- unshift(value: T): i32 {
371
- let len = this.length_ + 1;
372
- ensureCapacity(changetype<usize>(this), len, alignof<T>());
373
- let ptr = this.dataStart;
374
- memory.copy(
375
- ptr + sizeof<T>(),
376
- ptr,
377
- <usize>(len - 1) << alignof<T>()
378
- );
379
- store<T>(ptr, value);
380
- if (isManaged<T>()) {
381
- if (ASC_RUNTIME != Runtime.Memory) {
382
- __link(changetype<usize>(this), changetype<usize>(value), true);
383
- }
384
- }
385
- this.length_ = len;
386
- return len;
387
- }
388
-
389
- slice(start: i32 = 0, end: i32 = i32.MAX_VALUE): Array<T> {
390
- let len = this.length_;
391
- start = start < 0 ? max(start + len, 0) : min(start, len);
392
- end = end < 0 ? max(end + len, 0) : min(end , len);
393
- len = max(end - start, 0);
394
- let slice = changetype<Array<T>>(__newArray(len, alignof<T>(), idof<Array<T>>()));
395
- let sliceBase = slice.dataStart;
396
- let thisBase = this.dataStart + (<usize>start << alignof<T>());
397
- if (isManaged<T>()) {
398
- let off = <usize>0;
399
- let end = <usize>len << alignof<usize>();
400
- while (off < end) {
401
- let ref = load<usize>(thisBase + off);
402
- store<usize>(sliceBase + off, ref);
403
- if (ASC_RUNTIME != Runtime.Memory) {
404
- __link(changetype<usize>(slice), ref, true);
405
- }
406
- off += sizeof<usize>();
407
- }
408
- } else {
409
- memory.copy(sliceBase, thisBase, len << alignof<T>());
410
- }
411
- return slice;
412
- }
413
-
414
- splice(start: i32, deleteCount: i32 = i32.MAX_VALUE): Array<T> {
415
- let len = this.length_;
416
- start = start < 0 ? max<i32>(len + start, 0) : min<i32>(start, len);
417
- deleteCount = max<i32>(min<i32>(deleteCount, len - start), 0);
418
- let result = changetype<Array<T>>(__newArray(deleteCount, alignof<T>(), idof<Array<T>>()));
419
- let resultStart = result.dataStart;
420
- let thisStart = this.dataStart;
421
- let thisBase = thisStart + (<usize>start << alignof<T>());
422
- memory.copy(
423
- resultStart,
424
- thisBase,
425
- <usize>deleteCount << alignof<T>()
426
- );
427
- let offset = start + deleteCount;
428
- if (len != offset) {
429
- memory.copy(
430
- thisBase,
431
- thisStart + (<usize>offset << alignof<T>()),
432
- <usize>(len - offset) << alignof<T>()
433
- );
434
- }
435
- this.length_ = len - deleteCount;
436
- return result;
437
- }
438
-
439
- reverse(): Array<T> {
440
- REVERSE<T>(this.dataStart, this.length_);
441
- return this;
442
- }
443
-
444
- sort(comparator: (a: T, b: T) => i32 = COMPARATOR<T>()): Array<T> {
445
- SORT<T>(this.dataStart, this.length_, comparator);
446
- return this;
447
- }
448
-
449
- join(separator: string = ","): string {
450
- let ptr = this.dataStart;
451
- let len = this.length_;
452
- if (isBoolean<T>()) return joinBooleanArray(ptr, len, separator);
453
- if (isInteger<T>()) return joinIntegerArray<T>(ptr, len, separator);
454
- if (isFloat<T>()) return joinFloatArray<T>(ptr, len, separator);
455
-
456
- if (ASC_SHRINK_LEVEL < 1) {
457
- if (isString<T>()) return joinStringArray(ptr, len, separator);
458
- }
459
- // For rest objects and arrays use general join routine
460
- if (isReference<T>()) return joinReferenceArray<T>(ptr, len, separator);
461
- ERROR("unspported element type");
462
- return <string>unreachable();
463
- }
464
-
465
- flat(): T {
466
- if (!isArray<T>()) {
467
- ERROR("Cannot call flat() on Array<T> where T is not an Array.");
468
- }
469
- // Get the length and data start values
470
- let ptr = this.dataStart;
471
- let len = this.length_;
472
-
473
- // calculate the end size with an initial pass
474
- let size = 0;
475
- for (let i = 0; i < len; ++i) {
476
- let child = load<usize>(ptr + (i << alignof<T>()));
477
- size += child == 0 ? 0 : load<i32>(child, offsetof<T>("length_"));
478
- }
479
-
480
- // calculate the byteLength of the resulting backing ArrayBuffer
481
- const align = alignof<valueof<T>>();
482
- let byteLength = <usize>size << align;
483
- let outBuffer = changetype<ArrayBuffer>(__new(byteLength, idof<ArrayBuffer>()));
484
-
485
- // create the return value and initialize it
486
- let outArray = changetype<T>(__new(offsetof<T>(), idof<T>()));
487
- store<i32>(changetype<usize>(outArray), size, offsetof<T>("length_"));
488
-
489
- // byteLength, dataStart, and buffer are all readonly
490
- store<i32>(changetype<usize>(outArray), byteLength, offsetof<T>("byteLength"));
491
- store<usize>(changetype<usize>(outArray), changetype<usize>(outBuffer), offsetof<T>("dataStart"));
492
- store<usize>(changetype<usize>(outArray), changetype<usize>(outBuffer), offsetof<T>("buffer"));
493
- if (ASC_RUNTIME != Runtime.Memory) {
494
- __link(changetype<usize>(outArray), changetype<usize>(outBuffer), false);
495
- }
496
-
497
- // set the elements
498
- let resultOffset: usize = 0;
499
- for (let i = 0; i < len; ++i) { // for each child
500
- let child = load<usize>(ptr + (<usize>i << alignof<T>()));
501
-
502
- // ignore null arrays
503
- if (!child) continue;
504
-
505
- // copy the underlying buffer data to the result buffer
506
- let childDataLength = <usize>load<i32>(child, offsetof<T>("length_")) << align;
507
- memory.copy(
508
- changetype<usize>(outBuffer) + resultOffset,
509
- load<usize>(child, offsetof<T>("dataStart")),
510
- childDataLength
511
- );
512
-
513
- // advance the result length
514
- resultOffset += childDataLength;
515
- }
516
-
517
- // if the `valueof<T>` type is managed, we must link each reference
518
- if (isManaged<valueof<T>>()) {
519
- for (let i = 0; i < size; ++i) {
520
- let ref = load<usize>(changetype<usize>(outBuffer) + (<usize>i << usize(alignof<valueof<T>>())));
521
- if (ASC_RUNTIME != Runtime.Memory) {
522
- __link(changetype<usize>(outBuffer), ref, true);
523
- }
524
- }
525
- }
526
-
527
- return outArray;
528
- }
529
-
530
- toString(): string {
531
- return this.join();
532
- }
533
-
534
- // RT integration
535
-
536
- @unsafe private __visit(cookie: u32): void {
537
- if (ASC_RUNTIME != Runtime.Memory) {
538
- if (isManaged<T>()) {
539
- let cur = this.dataStart;
540
- let end = cur + (<usize>this.length_ << alignof<T>());
541
- while (cur < end) {
542
- let val = load<usize>(cur);
543
- if (val) __visit(val, cookie);
544
- cur += sizeof<usize>();
545
- }
546
- }
547
- __visit(changetype<usize>(this.buffer), cookie);
548
- }
549
- }
550
- }
1
+ /// <reference path="./rt/index.d.ts" />
2
+
3
+ import { BLOCK_MAXSIZE } from "./rt/common";
4
+ import { Runtime } from "shared/runtime";
5
+ import { COMPARATOR, SORT } from "./util/sort";
6
+ import { REVERSE, FILL } from "./util/bytes";
7
+ import { joinBooleanArray, joinIntegerArray, joinFloatArray, joinStringArray, joinReferenceArray } from "./util/string";
8
+ import { idof, isArray as builtin_isArray } from "./builtins";
9
+ import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_EMPTYARRAY, E_HOLEYARRAY } from "./util/error";
10
+
11
+ // @ts-ignore: decorator
12
+ @inline @lazy const MIN_SIZE: usize = 8;
13
+
14
+ /** Ensures that the given array has _at least_ the specified backing size. */
15
+ function ensureCapacity(array: usize, newSize: usize, alignLog2: u32, canGrow: bool = true): void {
16
+ // Depends on the fact that Arrays mimic ArrayBufferView
17
+ let oldCapacity = <usize>changetype<ArrayBufferView>(array).byteLength;
18
+ if (newSize > oldCapacity >>> alignLog2) {
19
+ if (newSize > BLOCK_MAXSIZE >>> alignLog2) throw new RangeError(E_INVALIDLENGTH);
20
+ let oldData = changetype<usize>(changetype<ArrayBufferView>(array).buffer);
21
+ // Grows old capacity by factor of two.
22
+ // Make sure we don't reach BLOCK_MAXSIZE for new growed capacity.
23
+ let newCapacity = max(newSize, MIN_SIZE) << alignLog2;
24
+ if (canGrow) newCapacity = max(min(oldCapacity << 1, BLOCK_MAXSIZE), newCapacity);
25
+ let newData = __renew(oldData, newCapacity);
26
+ // __new / __renew already init memory range as zeros in Incremental runtime.
27
+ // So try to avoid this.
28
+ if (ASC_RUNTIME != Runtime.Incremental) {
29
+ memory.fill(newData + oldCapacity, 0, newCapacity - oldCapacity);
30
+ }
31
+ if (newData != oldData) { // oldData has been free'd
32
+ store<usize>(array, newData, offsetof<ArrayBufferView>("buffer"));
33
+ store<usize>(array, newData, offsetof<ArrayBufferView>("dataStart"));
34
+ if (ASC_RUNTIME != Runtime.Memory) {
35
+ __link(array, changetype<usize>(newData), false);
36
+ }
37
+ }
38
+ store<u32>(array, <u32>newCapacity, offsetof<ArrayBufferView>("byteLength"));
39
+ }
40
+ }
41
+
42
+ export class Array<T> {
43
+ [key: number]: T;
44
+
45
+ // Mimicking ArrayBufferView isn't strictly necessary here but is done to allow glue code
46
+ // to work with typed and normal arrays interchangeably. Technically, normal arrays do not need
47
+ // `dataStart` (equals `buffer`) and `byteLength` (equals computed `buffer.byteLength`), but the
48
+ // block is 16 bytes anyway so it's fine to have a couple extra fields in there.
49
+
50
+ private buffer: ArrayBuffer;
51
+ @unsafe readonly dataStart: usize;
52
+ private byteLength: i32; // Uses here as capacity
53
+
54
+ // Also note that Array<T> with non-nullable T must guard against uninitialized null values
55
+ // whenever an element is accessed. Otherwise, the compiler wouldn't be able to guarantee
56
+ // type-safety anymore. For lack of a better word, such an array is "holey".
57
+
58
+ private length_: i32;
59
+
60
+ static isArray<U>(value: U): bool {
61
+ return isReference<U>() ? changetype<usize>(value) != 0 && builtin_isArray(value) : false;
62
+ }
63
+
64
+ static create<T>(capacity: i32 = 0): Array<T> {
65
+ WARNING("'Array.create' is deprecated. Use 'new Array' instead, making sure initial elements are initialized.");
66
+ let array = new Array<T>(capacity);
67
+ array.length = 0;
68
+ return array;
69
+ }
70
+
71
+ constructor(length: i32 = 0) {
72
+ if (<u32>length > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new RangeError(E_INVALIDLENGTH);
73
+ // reserve capacity for at least MIN_SIZE elements
74
+ let bufferSize = max(<usize>length, MIN_SIZE) << alignof<T>();
75
+ let buffer = changetype<ArrayBuffer>(__new(bufferSize, idof<ArrayBuffer>()));
76
+ if (ASC_RUNTIME != Runtime.Incremental) {
77
+ memory.fill(changetype<usize>(buffer), 0, bufferSize);
78
+ }
79
+ this.buffer = buffer; // links
80
+ this.dataStart = changetype<usize>(buffer);
81
+ this.byteLength = <i32>bufferSize;
82
+ this.length_ = length;
83
+ }
84
+
85
+ get length(): i32 {
86
+ return this.length_;
87
+ }
88
+
89
+ set length(newLength: i32) {
90
+ ensureCapacity(changetype<usize>(this), newLength, alignof<T>(), false);
91
+ this.length_ = newLength;
92
+ }
93
+
94
+ every(fn: (value: T, index: i32, array: Array<T>) => bool): bool {
95
+ for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
96
+ if (!fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this)) return false;
97
+ }
98
+ return true;
99
+ }
100
+
101
+ findIndex(fn: (value: T, index: i32, array: Array<T>) => bool): i32 {
102
+ for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
103
+ if (fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this)) return i;
104
+ }
105
+ return -1;
106
+ }
107
+
108
+ findLastIndex(fn: (value: T, index: i32, array: Array<T>) => bool): i32 {
109
+ for (let i = this.length_ - 1; i >= 0; --i) {
110
+ if (fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this)) return i;
111
+ }
112
+ return -1;
113
+ }
114
+
115
+ @operator("[]") private __get(index: i32): T {
116
+ if (<u32>index >= <u32>this.length_) throw new RangeError(E_INDEXOUTOFRANGE);
117
+ let value = load<T>(this.dataStart + (<usize>index << alignof<T>()));
118
+ if (isReference<T>()) {
119
+ if (!isNullable<T>()) {
120
+ if (!changetype<usize>(value)) throw new Error(E_HOLEYARRAY);
121
+ }
122
+ }
123
+ return value;
124
+ }
125
+
126
+ @unsafe @operator("{}") private __uget(index: i32): T {
127
+ return load<T>(this.dataStart + (<usize>index << alignof<T>()));
128
+ }
129
+
130
+ @operator("[]=") private __set(index: i32, value: T): void {
131
+ if (<u32>index >= <u32>this.length_) {
132
+ if (index < 0) throw new RangeError(E_INDEXOUTOFRANGE);
133
+ ensureCapacity(changetype<usize>(this), index + 1, alignof<T>());
134
+ this.length_ = index + 1;
135
+ }
136
+ store<T>(this.dataStart + (<usize>index << alignof<T>()), value);
137
+ if (isManaged<T>()) {
138
+ if (ASC_RUNTIME != Runtime.Memory) {
139
+ __link(changetype<usize>(this), changetype<usize>(value), true);
140
+ }
141
+ }
142
+ }
143
+
144
+ at(index: i32): T {
145
+ let len = this.length_;
146
+ index += select(0, len, index >= 0);
147
+ if (<u32>index >= <u32>len) throw new RangeError(E_INDEXOUTOFRANGE);
148
+ let value = load<T>(this.dataStart + (<usize>index << alignof<T>()));
149
+ if (isReference<T>()) {
150
+ if (!isNullable<T>()) {
151
+ if (!changetype<usize>(value)) throw new Error(E_HOLEYARRAY);
152
+ }
153
+ }
154
+ return value;
155
+ }
156
+
157
+ fill(value: T, start: i32 = 0, end: i32 = i32.MAX_VALUE): Array<T> {
158
+ if (isManaged<T>()) {
159
+ FILL<usize>(this.dataStart, this.length_, changetype<usize>(value), start, end);
160
+ if (ASC_RUNTIME != Runtime.Memory) {
161
+ __link(changetype<usize>(this), changetype<usize>(value), false);
162
+ }
163
+ } else {
164
+ FILL<T>(this.dataStart, this.length_, value, start, end);
165
+ }
166
+ return this;
167
+ }
168
+
169
+ includes(value: T, fromIndex: i32 = 0): bool {
170
+ if (isFloat<T>()) {
171
+ let len = this.length_;
172
+ if (len == 0 || fromIndex >= len) return false;
173
+ if (fromIndex < 0) fromIndex = max(len + fromIndex, 0);
174
+ let ptr = this.dataStart;
175
+ while (fromIndex < len) {
176
+ let elem = load<T>(ptr + (<usize>fromIndex << alignof<T>()));
177
+ // @ts-ignore
178
+ if (elem == value || isNaN(elem) & isNaN(value)) return true;
179
+ ++fromIndex;
180
+ }
181
+ return false;
182
+ } else {
183
+ return this.indexOf(value, fromIndex) >= 0;
184
+ }
185
+ }
186
+
187
+ indexOf(value: T, fromIndex: i32 = 0): i32 {
188
+ let len = this.length_;
189
+ if (len == 0 || fromIndex >= len) return -1;
190
+ if (fromIndex < 0) fromIndex = max(len + fromIndex, 0);
191
+ let ptr = this.dataStart;
192
+ while (fromIndex < len) {
193
+ if (load<T>(ptr + (<usize>fromIndex << alignof<T>())) == value) return fromIndex;
194
+ ++fromIndex;
195
+ }
196
+ return -1;
197
+ }
198
+
199
+ lastIndexOf(value: T, fromIndex: i32 = this.length_): i32 {
200
+ let len = this.length_;
201
+ if (len == 0) return -1;
202
+ if (fromIndex < 0) fromIndex = len + fromIndex;
203
+ else if (fromIndex >= len) fromIndex = len - 1;
204
+ let ptr = this.dataStart;
205
+ while (fromIndex >= 0) {
206
+ if (load<T>(ptr + (<usize>fromIndex << alignof<T>())) == value) return fromIndex;
207
+ --fromIndex;
208
+ }
209
+ return -1;
210
+ }
211
+
212
+ push(value: T): i32 {
213
+ let oldLen = this.length_;
214
+ let len = oldLen + 1;
215
+ ensureCapacity(changetype<usize>(this), len, alignof<T>());
216
+ if (isManaged<T>()) {
217
+ store<usize>(this.dataStart + (<usize>oldLen << alignof<T>()), changetype<usize>(value));
218
+ if (ASC_RUNTIME != Runtime.Memory) {
219
+ __link(changetype<usize>(this), changetype<usize>(value), true);
220
+ }
221
+ } else {
222
+ store<T>(this.dataStart + (<usize>oldLen << alignof<T>()), value);
223
+ }
224
+ this.length_ = len;
225
+ return len;
226
+ }
227
+
228
+ concat(other: Array<T>): Array<T> {
229
+ let thisLen = this.length_;
230
+ let otherLen = other.length_;
231
+ let outLen = thisLen + otherLen;
232
+ if (<u32>outLen > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new Error(E_INVALIDLENGTH);
233
+ let out = changetype<Array<T>>(__newArray(outLen, alignof<T>(), idof<Array<T>>()));
234
+ let outStart = out.dataStart;
235
+ let thisSize = <usize>thisLen << alignof<T>();
236
+ if (isManaged<T>()) {
237
+ let thisStart = this.dataStart;
238
+ for (let offset: usize = 0; offset < thisSize; offset += sizeof<T>()) {
239
+ let ref = load<usize>(thisStart + offset);
240
+ store<usize>(outStart + offset, ref);
241
+ if (ASC_RUNTIME != Runtime.Memory) {
242
+ __link(changetype<usize>(out), ref, true);
243
+ }
244
+ }
245
+ outStart += thisSize;
246
+ let otherStart = other.dataStart;
247
+ let otherSize = <usize>otherLen << alignof<T>();
248
+ for (let offset: usize = 0; offset < otherSize; offset += sizeof<T>()) {
249
+ let ref = load<usize>(otherStart + offset);
250
+ store<usize>(outStart + offset, ref);
251
+ if (ASC_RUNTIME != Runtime.Memory) {
252
+ __link(changetype<usize>(out), ref, true);
253
+ }
254
+ }
255
+ } else {
256
+ memory.copy(outStart, this.dataStart, thisSize);
257
+ memory.copy(outStart + thisSize, other.dataStart, <usize>otherLen << alignof<T>());
258
+ }
259
+ return out;
260
+ }
261
+
262
+ copyWithin(target: i32, start: i32, end: i32 = i32.MAX_VALUE): Array<T> {
263
+ let ptr = this.dataStart;
264
+ let len = this.length_;
265
+
266
+ end = min<i32>(end, len);
267
+
268
+ let to = target < 0 ? max(len + target, 0) : min(target, len);
269
+ let from = start < 0 ? max(len + start, 0) : min(start, len);
270
+ let last = end < 0 ? max(len + end, 0) : min(end, len);
271
+ let count = min(last - from, len - to);
272
+
273
+ memory.copy( // is memmove
274
+ ptr + (<usize>to << alignof<T>()),
275
+ ptr + (<usize>from << alignof<T>()),
276
+ <usize>count << alignof<T>()
277
+ );
278
+ return this;
279
+ }
280
+
281
+ pop(): T {
282
+ let len = this.length_;
283
+ if (len < 1) throw new RangeError(E_EMPTYARRAY);
284
+ let val = load<T>(this.dataStart + (<usize>(--len) << alignof<T>()));
285
+ this.length_ = len;
286
+ return val;
287
+ }
288
+
289
+ forEach(fn: (value: T, index: i32, array: Array<T>) => void): void {
290
+ for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
291
+ fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this);
292
+ }
293
+ }
294
+
295
+ map<U>(fn: (value: T, index: i32, array: Array<T>) => U): Array<U> {
296
+ let len = this.length_;
297
+ let out = changetype<Array<U>>(__newArray(len, alignof<U>(), idof<Array<U>>()));
298
+ let outStart = out.dataStart;
299
+ for (let i = 0; i < min(len, this.length_); ++i) {
300
+ let result = fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this);
301
+ store<U>(outStart + (<usize>i << alignof<U>()), result);
302
+ if (isManaged<U>()) {
303
+ if (ASC_RUNTIME != Runtime.Memory) {
304
+ __link(changetype<usize>(out), changetype<usize>(result), true);
305
+ }
306
+ }
307
+ }
308
+ return out;
309
+ }
310
+
311
+ filter(fn: (value: T, index: i32, array: Array<T>) => bool): Array<T> {
312
+ let result = changetype<Array<T>>(__newArray(0, alignof<T>(), idof<Array<T>>()));
313
+ for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
314
+ let value = load<T>(this.dataStart + (<usize>i << alignof<T>()));
315
+ if (fn(value, i, this)) result.push(value);
316
+ }
317
+ return result;
318
+ }
319
+
320
+ reduce<U>(
321
+ fn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U,
322
+ initialValue: U
323
+ ): U {
324
+ let acc = initialValue;
325
+ for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
326
+ acc = fn(acc, load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this);
327
+ }
328
+ return acc;
329
+ }
330
+
331
+ reduceRight<U>(
332
+ fn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U,
333
+ initialValue: U
334
+ ): U {
335
+ let acc = initialValue;
336
+ for (let i = this.length_ - 1; i >= 0; --i) {
337
+ acc = fn(acc, load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this);
338
+ }
339
+ return acc;
340
+ }
341
+
342
+ shift(): T {
343
+ let len = this.length_;
344
+ if (len < 1) throw new RangeError(E_EMPTYARRAY);
345
+ let base = this.dataStart;
346
+ let element = load<T>(base);
347
+ let lastIndex = len - 1;
348
+ memory.copy(
349
+ base,
350
+ base + sizeof<T>(),
351
+ <usize>lastIndex << alignof<T>()
352
+ );
353
+ if (isReference<T>()) {
354
+ store<usize>(base + (<usize>lastIndex << alignof<T>()), 0);
355
+ } else {
356
+ // @ts-ignore
357
+ store<T>(base + (<usize>lastIndex << alignof<T>()), <T>0);
358
+ }
359
+ this.length_ = lastIndex;
360
+ return element;
361
+ }
362
+
363
+ some(fn: (value: T, index: i32, array: Array<T>) => bool): bool {
364
+ for (let i = 0, len = this.length_; i < min(len, this.length_); ++i) {
365
+ if (fn(load<T>(this.dataStart + (<usize>i << alignof<T>())), i, this)) return true;
366
+ }
367
+ return false;
368
+ }
369
+
370
+ unshift(value: T): i32 {
371
+ let len = this.length_ + 1;
372
+ ensureCapacity(changetype<usize>(this), len, alignof<T>());
373
+ let ptr = this.dataStart;
374
+ memory.copy(
375
+ ptr + sizeof<T>(),
376
+ ptr,
377
+ <usize>(len - 1) << alignof<T>()
378
+ );
379
+ store<T>(ptr, value);
380
+ if (isManaged<T>()) {
381
+ if (ASC_RUNTIME != Runtime.Memory) {
382
+ __link(changetype<usize>(this), changetype<usize>(value), true);
383
+ }
384
+ }
385
+ this.length_ = len;
386
+ return len;
387
+ }
388
+
389
+ slice(start: i32 = 0, end: i32 = i32.MAX_VALUE): Array<T> {
390
+ let len = this.length_;
391
+ start = start < 0 ? max(start + len, 0) : min(start, len);
392
+ end = end < 0 ? max(end + len, 0) : min(end , len);
393
+ len = max(end - start, 0);
394
+ let slice = changetype<Array<T>>(__newArray(len, alignof<T>(), idof<Array<T>>()));
395
+ let sliceBase = slice.dataStart;
396
+ let thisBase = this.dataStart + (<usize>start << alignof<T>());
397
+ if (isManaged<T>()) {
398
+ let off = <usize>0;
399
+ let end = <usize>len << alignof<usize>();
400
+ while (off < end) {
401
+ let ref = load<usize>(thisBase + off);
402
+ store<usize>(sliceBase + off, ref);
403
+ if (ASC_RUNTIME != Runtime.Memory) {
404
+ __link(changetype<usize>(slice), ref, true);
405
+ }
406
+ off += sizeof<usize>();
407
+ }
408
+ } else {
409
+ memory.copy(sliceBase, thisBase, len << alignof<T>());
410
+ }
411
+ return slice;
412
+ }
413
+
414
+ splice(start: i32, deleteCount: i32 = i32.MAX_VALUE): Array<T> {
415
+ let len = this.length_;
416
+ start = start < 0 ? max<i32>(len + start, 0) : min<i32>(start, len);
417
+ deleteCount = max<i32>(min<i32>(deleteCount, len - start), 0);
418
+ let result = changetype<Array<T>>(__newArray(deleteCount, alignof<T>(), idof<Array<T>>()));
419
+ let resultStart = result.dataStart;
420
+ let thisStart = this.dataStart;
421
+ let thisBase = thisStart + (<usize>start << alignof<T>());
422
+ memory.copy(
423
+ resultStart,
424
+ thisBase,
425
+ <usize>deleteCount << alignof<T>()
426
+ );
427
+ let offset = start + deleteCount;
428
+ if (len != offset) {
429
+ memory.copy(
430
+ thisBase,
431
+ thisStart + (<usize>offset << alignof<T>()),
432
+ <usize>(len - offset) << alignof<T>()
433
+ );
434
+ }
435
+ this.length_ = len - deleteCount;
436
+ return result;
437
+ }
438
+
439
+ reverse(): Array<T> {
440
+ REVERSE<T>(this.dataStart, this.length_);
441
+ return this;
442
+ }
443
+
444
+ sort(comparator: (a: T, b: T) => i32 = COMPARATOR<T>()): Array<T> {
445
+ SORT<T>(this.dataStart, this.length_, comparator);
446
+ return this;
447
+ }
448
+
449
+ join(separator: string = ","): string {
450
+ let ptr = this.dataStart;
451
+ let len = this.length_;
452
+ if (isBoolean<T>()) return joinBooleanArray(ptr, len, separator);
453
+ if (isInteger<T>()) return joinIntegerArray<T>(ptr, len, separator);
454
+ if (isFloat<T>()) return joinFloatArray<T>(ptr, len, separator);
455
+
456
+ if (ASC_SHRINK_LEVEL < 1) {
457
+ if (isString<T>()) return joinStringArray(ptr, len, separator);
458
+ }
459
+ // For rest objects and arrays use general join routine
460
+ if (isReference<T>()) return joinReferenceArray<T>(ptr, len, separator);
461
+ ERROR("unspported element type");
462
+ return <string>unreachable();
463
+ }
464
+
465
+ flat(): T {
466
+ if (!isArray<T>()) {
467
+ ERROR("Cannot call flat() on Array<T> where T is not an Array.");
468
+ }
469
+ // Get the length and data start values
470
+ let ptr = this.dataStart;
471
+ let len = this.length_;
472
+
473
+ // calculate the end size with an initial pass
474
+ let size = 0;
475
+ for (let i = 0; i < len; ++i) {
476
+ let child = load<usize>(ptr + (i << alignof<T>()));
477
+ size += child == 0 ? 0 : load<i32>(child, offsetof<T>("length_"));
478
+ }
479
+
480
+ // calculate the byteLength of the resulting backing ArrayBuffer
481
+ const align = alignof<valueof<T>>();
482
+ let byteLength = <usize>size << align;
483
+ let outBuffer = changetype<ArrayBuffer>(__new(byteLength, idof<ArrayBuffer>()));
484
+
485
+ // create the return value and initialize it
486
+ let outArray = changetype<T>(__new(offsetof<T>(), idof<T>()));
487
+ store<i32>(changetype<usize>(outArray), size, offsetof<T>("length_"));
488
+
489
+ // byteLength, dataStart, and buffer are all readonly
490
+ store<i32>(changetype<usize>(outArray), byteLength, offsetof<T>("byteLength"));
491
+ store<usize>(changetype<usize>(outArray), changetype<usize>(outBuffer), offsetof<T>("dataStart"));
492
+ store<usize>(changetype<usize>(outArray), changetype<usize>(outBuffer), offsetof<T>("buffer"));
493
+ if (ASC_RUNTIME != Runtime.Memory) {
494
+ __link(changetype<usize>(outArray), changetype<usize>(outBuffer), false);
495
+ }
496
+
497
+ // set the elements
498
+ let resultOffset: usize = 0;
499
+ for (let i = 0; i < len; ++i) { // for each child
500
+ let child = load<usize>(ptr + (<usize>i << alignof<T>()));
501
+
502
+ // ignore null arrays
503
+ if (!child) continue;
504
+
505
+ // copy the underlying buffer data to the result buffer
506
+ let childDataLength = <usize>load<i32>(child, offsetof<T>("length_")) << align;
507
+ memory.copy(
508
+ changetype<usize>(outBuffer) + resultOffset,
509
+ load<usize>(child, offsetof<T>("dataStart")),
510
+ childDataLength
511
+ );
512
+
513
+ // advance the result length
514
+ resultOffset += childDataLength;
515
+ }
516
+
517
+ // if the `valueof<T>` type is managed, we must link each reference
518
+ if (isManaged<valueof<T>>()) {
519
+ for (let i = 0; i < size; ++i) {
520
+ let ref = load<usize>(changetype<usize>(outBuffer) + (<usize>i << usize(alignof<valueof<T>>())));
521
+ if (ASC_RUNTIME != Runtime.Memory) {
522
+ __link(changetype<usize>(outBuffer), ref, true);
523
+ }
524
+ }
525
+ }
526
+
527
+ return outArray;
528
+ }
529
+
530
+ toString(): string {
531
+ return this.join();
532
+ }
533
+
534
+ // RT integration
535
+
536
+ @unsafe private __visit(cookie: u32): void {
537
+ if (ASC_RUNTIME != Runtime.Memory) {
538
+ if (isManaged<T>()) {
539
+ let cur = this.dataStart;
540
+ let end = cur + (<usize>this.length_ << alignof<T>());
541
+ while (cur < end) {
542
+ let val = load<usize>(cur);
543
+ if (val) __visit(val, cookie);
544
+ cur += sizeof<usize>();
545
+ }
546
+ }
547
+ __visit(changetype<usize>(this.buffer), cookie);
548
+ }
549
+ }
550
+ }