Skip to content

Commit 13349cc

Browse files
authored
Implement Array#flat() (AssemblyScript#1203)
1 parent 02892c7 commit 13349cc

File tree

5 files changed

+1541
-374
lines changed

5 files changed

+1541
-374
lines changed

std/assembly/array.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,64 @@ export class Array<T> {
493493
return <string>unreachable();
494494
}
495495

496+
flat(): T {
497+
if (!isArray<T>()) {
498+
ERROR("Cannot call flat() on Array<T> where T is not an Array.");
499+
}
500+
// Get the length and data start values
501+
var length = this.length_;
502+
var selfDataStart = this.dataStart;
503+
504+
// calculate the end size with an initial pass
505+
var size = 0;
506+
for (let i = 0; i < length; i++) {
507+
let child = load<usize>(selfDataStart + (i << alignof<T>()));
508+
size += child == 0 ? 0 : load<i32>(child, offsetof<T>("length_"));
509+
}
510+
511+
// calculate the byteLength of the resulting backing ArrayBuffer
512+
var byteLength = <usize>size << usize(alignof<valueof<T>>());
513+
var dataStart = __alloc(byteLength, idof<ArrayBuffer>());
514+
515+
// create the return value and initialize it
516+
var result = __alloc(offsetof<T>(), idof<T>());
517+
store<i32>(result, size, offsetof<T>("length_"));
518+
519+
// byteLength, dataStart, and buffer are all readonly
520+
store<i32>(result, byteLength, offsetof<T>("byteLength"));
521+
store<usize>(result, dataStart, offsetof<T>("dataStart"));
522+
store<usize>(result, __retain(dataStart), offsetof<T>("buffer"));
523+
524+
// set the elements
525+
var resultOffset: usize = 0;
526+
for (let i = 0; i < length; i++) { // for each child
527+
let child = load<usize>(selfDataStart + (<usize>i << alignof<T>()));
528+
529+
// ignore null arrays
530+
if (child == 0) continue;
531+
532+
// copy the underlying buffer data to the result buffer
533+
let childDataLength = load<i32>(child, offsetof<T>("byteLength"));
534+
memory.copy(
535+
dataStart + resultOffset,
536+
load<usize>(child, offsetof<T>("dataStart")),
537+
<usize>childDataLength
538+
);
539+
540+
// advance the result length
541+
resultOffset += childDataLength;
542+
}
543+
544+
// if the `valueof<T>` type is managed, we must call __retain() on each reference
545+
if (isManaged<valueof<T>>()) {
546+
for (let i = 0; i < size; i++) {
547+
__retain(load<usize>(dataStart + (<usize>i << usize(alignof<valueof<T>>()))));
548+
}
549+
}
550+
551+
return changetype<T>(result);
552+
}
553+
496554
toString(): string {
497555
return this.join();
498556
}

std/assembly/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,8 @@ declare class Array<T> {
13991399
sort(comparator?: (a: T, b: T) => i32): this;
14001400
join(separator?: string): string;
14011401
reverse(): T[];
1402+
/** Flattens an array of arrays. If any null entries exist in the array, they are ignored, unlike JavaScript's version of Array#flat(). */
1403+
flat(): valueof<T>[];
14021404
toString(): string;
14031405
}
14041406

0 commit comments

Comments
 (0)