mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-15 07:51:32 +00:00
Make the transition to ArrayBuffer backed Arrays (#70)
* Traverse base classes when resolving overloads * Implement preliminary TypedArray accessors * Extract decorator flags from common flags to make space * Add '**' overload * Implement basic explicit inlining * Support inlining of instance methods * Reduce number of required locals when inlining * Implement inlining of operator overloads * Fix issues when inlining generic functions
This commit is contained in:
@ -1,128 +1,61 @@
|
||||
import "allocator/arena";
|
||||
import { Array } from "array";
|
||||
import { defaultComparator } from "internal/array";
|
||||
|
||||
// Default comparator
|
||||
function createDefaultComparator<T>(): (a: T, b: T) => i32 {
|
||||
return (a: T, b: T): i32 => (
|
||||
<i32>(a > b) - <i32>(a < b)
|
||||
);
|
||||
// Obtains the internal capacity of an array from its backing buffer.
|
||||
function internalCapacity<T>(array: Array<T>): i32 {
|
||||
// the memory region used by the backing buffer might still be larger in that the ArrayBuffer
|
||||
// pre-allocates a power of 2 sized buffer itself and reuses it as long as it isn't exceeded.
|
||||
var buffer: ArrayBuffer = array.buffer_;
|
||||
return buffer.byteLength >> alignof<T>();
|
||||
}
|
||||
|
||||
// Check is array sorted
|
||||
function isSorted<T>(data: Array<T>, comparator: (a: T, b: T) => i32 = createDefaultComparator<T>()): bool {
|
||||
for (let i: i32 = 1, len: i32 = data.length; i < len; i++) {
|
||||
if (comparator(data[i - 1], data[i]) > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
var arr = new Array<i32>();
|
||||
|
||||
// Check is equality for arrays
|
||||
function isArraysEqual<T>(a: Array<T>, b: Array<T>, maxLen: i32 = 0): bool {
|
||||
var len = maxLen;
|
||||
if (!maxLen) {
|
||||
if (a.length != b.length) {
|
||||
return false;
|
||||
}
|
||||
len = <i32>a.length;
|
||||
}
|
||||
for (let i: i32 = 0; i < len; i++) {
|
||||
if (a[i] != b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function createReverseOrderedArray(size: i32): Array<i32> {
|
||||
var arr = new Array<i32>(size);
|
||||
for (let i: i32 = 0; i < arr.length; i++) {
|
||||
arr[i] = <i32>arr.length - 1 - i;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
NativeMath.seedRandom(reinterpret<u64>(JSMath.random()));
|
||||
|
||||
function createRandomOrderedArray(size: i32): Array<i32> {
|
||||
var arr = new Array<i32>(size);
|
||||
for (let i: i32 = 0; i < arr.length; i++) {
|
||||
arr[i] = <i32>(NativeMath.random() * arr.length);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/*
|
||||
function createReverseOrderedNestedArray(size: i32): Array<Array<i32>> {
|
||||
var arr = new Array<Array<i32>>(size);
|
||||
for (let i: i32 = 0; i < arr.length; i++) {
|
||||
arr[i] = new Array<i32>(1);
|
||||
arr[i][0] = arr.length - 1 - i;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
class Proxy<T> {
|
||||
constructor(public x: T) {}
|
||||
}
|
||||
|
||||
function createReverseOrderedElementsArray(size: i32): Proxy<i32>[] {
|
||||
var arr = new Array<Proxy<i32>>(size);
|
||||
for (let i: i32 = 0; i < arr.length; i++) {
|
||||
arr[i] = new Proxy<i32>(arr.length - 1 - i);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
*/
|
||||
|
||||
function assertSorted<T>(arr: Array<T>, comparator: (a: T, b: T) => i32): void {
|
||||
assert(isSorted<T>(arr.sort<T>(comparator), comparator));
|
||||
}
|
||||
|
||||
function assertSortedDefault<T>(arr: Array<T>): void {
|
||||
assertSorted<T>(arr, createDefaultComparator<T>());
|
||||
}
|
||||
|
||||
var arr = changetype<i32[]>(allocate_memory(sizeof<usize>() + 2 * sizeof<i32>()));
|
||||
// Array#push/pop //////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
assert(arr.length == 0);
|
||||
assert(arr.__capacity == 0);
|
||||
assert(internalCapacity<i32>(arr) == 0);
|
||||
|
||||
arr.push(42);
|
||||
|
||||
assert(arr[0] == 42);
|
||||
assert(arr.length == 1);
|
||||
assert(arr.__capacity == 1);
|
||||
assert(internalCapacity<i32>(arr) == 1);
|
||||
|
||||
var i = arr.pop();
|
||||
|
||||
assert(i == 42);
|
||||
assert(arr.length == 0);
|
||||
assert(arr.__capacity == 1);
|
||||
assert(internalCapacity<i32>(arr) == 1);
|
||||
|
||||
arr.push(43);
|
||||
|
||||
assert(arr.length == 1);
|
||||
assert(arr.__capacity == 1);
|
||||
assert(internalCapacity<i32>(arr) == 1);
|
||||
assert(arr[0] == 43);
|
||||
|
||||
arr.push(44);
|
||||
|
||||
assert(arr.length == 2);
|
||||
assert(arr.__capacity == 2);
|
||||
assert(internalCapacity<i32>(arr) == 2);
|
||||
assert(arr[0] == 43);
|
||||
assert(arr[1] == 44);
|
||||
|
||||
arr.push(45);
|
||||
|
||||
assert(arr.length == 3);
|
||||
assert(arr.__capacity == 4);
|
||||
assert(internalCapacity<i32>(arr) == 3);
|
||||
assert(arr[0] == 43);
|
||||
assert(arr[1] == 44);
|
||||
assert(arr[2] == 45);
|
||||
|
||||
// Array#unshift ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
arr.unshift(42);
|
||||
|
||||
assert(arr.length == 4);
|
||||
assert(arr.__capacity == 4);
|
||||
assert(internalCapacity<i32>(arr) == 4);
|
||||
assert(arr[0] == 42);
|
||||
assert(arr[1] == 43);
|
||||
assert(arr[2] == 44);
|
||||
@ -131,18 +64,20 @@ assert(arr[3] == 45);
|
||||
arr.unshift(41);
|
||||
|
||||
assert(arr.length == 5);
|
||||
assert(arr.__capacity == 8);
|
||||
assert(internalCapacity<i32>(arr) == 5);
|
||||
assert(arr[0] == 41);
|
||||
assert(arr[1] == 42);
|
||||
assert(arr[2] == 43);
|
||||
assert(arr[3] == 44);
|
||||
assert(arr[4] == 45);
|
||||
|
||||
// Array#shift /////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
i = arr.shift();
|
||||
|
||||
assert(i == 41);
|
||||
assert(arr.length == 4);
|
||||
assert(arr.__capacity == 8);
|
||||
assert(internalCapacity<i32>(arr) == 5);
|
||||
assert(arr[0] == 42);
|
||||
assert(arr[1] == 43);
|
||||
assert(arr[2] == 44);
|
||||
@ -152,15 +87,17 @@ i = arr.pop();
|
||||
|
||||
assert(i == 45);
|
||||
assert(arr.length == 3);
|
||||
assert(arr.__capacity == 8);
|
||||
assert(internalCapacity<i32>(arr) == 5);
|
||||
assert(arr[0] == 42);
|
||||
assert(arr[1] == 43);
|
||||
assert(arr[2] == 44);
|
||||
|
||||
// Array#reverse ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
arr.reverse();
|
||||
|
||||
assert(arr.length == 3);
|
||||
assert(arr.__capacity == 8);
|
||||
assert(internalCapacity<i32>(arr) == 5);
|
||||
assert(arr[0] == 44);
|
||||
assert(arr[1] == 43);
|
||||
assert(arr[2] == 42);
|
||||
@ -168,6 +105,8 @@ assert(arr[2] == 42);
|
||||
arr.push(43);
|
||||
arr.push(44);
|
||||
|
||||
// Array#indexOf ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
i = arr.indexOf(44);
|
||||
|
||||
assert(i == 0);
|
||||
@ -208,6 +147,8 @@ i = arr.indexOf(43, 2);
|
||||
|
||||
assert(i == 3);
|
||||
|
||||
// Array#includes //////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var includes = arr.includes(44);
|
||||
|
||||
assert(includes == true);
|
||||
@ -251,16 +192,17 @@ assert(includes == true);
|
||||
arr.splice(1, 1);
|
||||
|
||||
assert(arr.length == 4);
|
||||
assert(arr.__capacity == 8);
|
||||
assert(internalCapacity<i32>(arr) == 5);
|
||||
assert(arr[0] == 44);
|
||||
assert(arr[1] == 42);
|
||||
|
||||
// Array#findIndex /////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
arr[0] = 0;
|
||||
arr[1] = 1;
|
||||
arr[2] = 2;
|
||||
arr[3] = 3;
|
||||
/*=============================== findIndex ==========================*/
|
||||
|
||||
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => value == 0);
|
||||
assert(i == 0);
|
||||
|
||||
@ -272,7 +214,7 @@ assert(i == -1);
|
||||
|
||||
// Test side effect push
|
||||
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => {
|
||||
array.push(100); //push side effect should not affect this method by spec
|
||||
array.push(100); // push side effect should not affect this method by spec
|
||||
return value == 100;
|
||||
});
|
||||
// array should be changed, but this method result should be calculated for old array length
|
||||
@ -288,7 +230,7 @@ arr.pop();
|
||||
|
||||
// Test side effect pop
|
||||
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => {
|
||||
array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds
|
||||
array.pop(); // poped items shouldn't be looked up, and we shouldn't go out of bounds
|
||||
return value == 100;
|
||||
});
|
||||
// only 2 first items was looked up, since last 2 was removed by .pop()
|
||||
@ -297,7 +239,9 @@ assert(arr.length == 2);
|
||||
|
||||
arr.push(2);
|
||||
arr.push(3);
|
||||
/*=============================== every ==========================*/
|
||||
|
||||
// Array#every /////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var every = arr.every((value: i32, index: i32, array: Array<i32>): bool => value >= 0);
|
||||
assert(every == true);
|
||||
|
||||
@ -306,7 +250,7 @@ assert(every == false);
|
||||
|
||||
// Test side effect push
|
||||
every = arr.every((value: i32, index: i32, array: Array<i32>): bool => {
|
||||
array.push(100); //push side effect should not affect this method by spec
|
||||
array.push(100); // push side effect should not affect this method by spec
|
||||
return value < 10;
|
||||
});
|
||||
// array should be changed, but this method result should be calculated for old array length
|
||||
@ -331,7 +275,9 @@ assert(arr.length == 2);
|
||||
|
||||
arr.push(2);
|
||||
arr.push(3);
|
||||
/*=============================== some ==========================*/
|
||||
|
||||
// Array#some //////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var some = arr.some((value: i32, index: i32, array: Array<i32>): bool => value >= 3);
|
||||
assert(some == true);
|
||||
|
||||
@ -340,7 +286,7 @@ assert(some == false);
|
||||
|
||||
// Test side effect push
|
||||
some = arr.some((value: i32, index: i32, array: Array<i32>): bool => {
|
||||
array.push(100); //push side effect should not affect this method by spec
|
||||
array.push(100); // push side effect should not affect this method by spec
|
||||
return value > 10;
|
||||
});
|
||||
// array should be changed, but this method result should be calculated for old array length
|
||||
@ -356,7 +302,7 @@ arr.pop();
|
||||
|
||||
// Test side effect pop
|
||||
some = arr.some((value: i32, index: i32, array: Array<i32>): bool => {
|
||||
array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds
|
||||
array.pop(); // poped items shouldn't be looked up, and we shouldn't go out of bounds
|
||||
return value > 3;
|
||||
});
|
||||
// only 2 first items was looked up, since last 2 was removed by .pop()
|
||||
@ -365,7 +311,8 @@ assert(arr.length == 2);
|
||||
|
||||
arr.push(2);
|
||||
arr.push(3);
|
||||
/*=============================== reduce ==========================*/
|
||||
|
||||
// Array#reduce ////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
i = arr.reduce<i32>(((prev: i32, current: i32, index: i32, array: Array<i32>): i32 => prev + current), 0);
|
||||
assert(i == 6);
|
||||
@ -382,7 +329,7 @@ assert(boolVal == false);
|
||||
|
||||
// Test side effect push
|
||||
i = arr.reduce<i32>(((prev: i32, current: i32, index: i32, array: Array<i32>): i32 => {
|
||||
array.push(1); //push side effect should not affect this method by spec
|
||||
array.push(1); // push side effect should not affect this method by spec
|
||||
return prev + current;
|
||||
}), 0);
|
||||
// array should be changed, but this method result should be calculated for old array length
|
||||
@ -405,46 +352,115 @@ i = arr.reduce<i32>(((prev: i32, current: i32, index: i32, array: Array<i32>): i
|
||||
assert(i == 1);
|
||||
assert(arr.length == 2);
|
||||
|
||||
/*=============================== sort ==========================*/
|
||||
// Array#sort //////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var revesed0: Array<i32> = [];
|
||||
var revesed1: Array<i32> = [1];
|
||||
var revesed2: Array<i32> = [2, 1];
|
||||
var revesed4: Array<i32> = [3, 2, 1, 0];
|
||||
// Checks if an array is properly sorted
|
||||
function isSorted<T>(data: Array<T>, comparator: (a: T, b: T) => i32 = defaultComparator<T>()): bool {
|
||||
for (let i: i32 = 1, len: i32 = data.length; i < len; i++) {
|
||||
if (comparator(data[i - 1], data[i]) > 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks if two arrays are equal
|
||||
function isArraysEqual<T>(a: Array<T>, b: Array<T>, len: i32 = 0): bool {
|
||||
if (!len) {
|
||||
if (a.length != b.length) return false;
|
||||
len = a.length;
|
||||
}
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (a[i] != b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function createReverseOrderedArray(size: i32): Array<i32> {
|
||||
var arr = new Array<i32>(size);
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i] = arr.length - 1 - i;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
NativeMath.seedRandom(reinterpret<u64>(JSMath.random()));
|
||||
|
||||
function createRandomOrderedArray(size: i32): Array<i32> {
|
||||
var arr = new Array<i32>(size);
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i] = <i32>(NativeMath.random() * arr.length);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/*
|
||||
function createReverseOrderedNestedArray(size: i32): Array<Array<i32>> {
|
||||
var arr = new Array<Array<i32>>(size);
|
||||
for (let i: i32 = 0; i < arr.length; i++) {
|
||||
arr[i] = new Array<i32>(1);
|
||||
arr[i][0] = arr.length - 1 - i;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
class Proxy<T> {
|
||||
constructor(public x: T) {}
|
||||
}
|
||||
|
||||
function createReverseOrderedElementsArray(size: i32): Proxy<i32>[] {
|
||||
var arr = new Array<Proxy<i32>>(size);
|
||||
for (let i: i32 = 0; i < arr.length; i++) {
|
||||
arr[i] = new Proxy<i32>(arr.length - 1 - i);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
*/
|
||||
|
||||
function assertSorted<T>(arr: Array<T>, comparator: (a: T, b: T) => i32): void {
|
||||
assert(isSorted<T>(arr.sort(comparator), comparator));
|
||||
}
|
||||
|
||||
function assertSortedDefault<T>(arr: Array<T>): void {
|
||||
assertSorted<T>(arr, defaultComparator<T>());
|
||||
}
|
||||
|
||||
var reversed0: Array<i32> = [];
|
||||
var reversed1: Array<i32> = [1];
|
||||
var reversed2: Array<i32> = [2, 1];
|
||||
var reversed4: Array<i32> = [3, 2, 1, 0];
|
||||
|
||||
var expected4: Array<i32> = [0, 1, 2, 3];
|
||||
|
||||
var revesed64 = createReverseOrderedArray(64);
|
||||
var revesed128 = createReverseOrderedArray(128);
|
||||
var revesed1024 = createReverseOrderedArray(1024);
|
||||
var revesed10000 = createReverseOrderedArray(10000);
|
||||
var reversed64 = createReverseOrderedArray(64);
|
||||
var reversed128 = createReverseOrderedArray(128);
|
||||
var reversed1024 = createReverseOrderedArray(1024);
|
||||
var reversed10000 = createReverseOrderedArray(10000);
|
||||
|
||||
var randomized512 = createRandomOrderedArray(512);
|
||||
|
||||
// Test sorting with with default comparator
|
||||
|
||||
assertSortedDefault<i32>(revesed0);
|
||||
assertSortedDefault<i32>(reversed0);
|
||||
|
||||
assertSortedDefault<i32>(revesed1);
|
||||
assert(isArraysEqual<i32>(revesed1, <i32[]>[1]));
|
||||
assertSortedDefault<i32>(reversed1);
|
||||
assert(isArraysEqual<i32>(reversed1, <i32[]>[1]));
|
||||
|
||||
assertSortedDefault<i32>(revesed2);
|
||||
assert(isArraysEqual<i32>(revesed2, <i32[]>[1, 2]));
|
||||
assertSortedDefault<i32>(reversed2);
|
||||
assert(isArraysEqual<i32>(reversed2, <i32[]>[1, 2]));
|
||||
|
||||
assertSortedDefault<i32>(revesed4);
|
||||
assert(isArraysEqual<i32>(revesed4, expected4));
|
||||
assertSortedDefault<i32>(reversed4);
|
||||
assert(isArraysEqual<i32>(reversed4, expected4));
|
||||
|
||||
assertSortedDefault<i32>(revesed64);
|
||||
assert(isArraysEqual<i32>(revesed64, expected4, 4));
|
||||
assertSortedDefault<i32>(reversed64);
|
||||
assert(isArraysEqual<i32>(reversed64, expected4, 4));
|
||||
|
||||
assertSortedDefault<i32>(revesed128);
|
||||
assert(isArraysEqual<i32>(revesed128, expected4, 4));
|
||||
assertSortedDefault<i32>(reversed128);
|
||||
assert(isArraysEqual<i32>(reversed128, expected4, 4));
|
||||
|
||||
assertSortedDefault<i32>(revesed1024);
|
||||
assert(isArraysEqual<i32>(revesed1024, expected4, 4));
|
||||
assertSortedDefault<i32>(reversed1024);
|
||||
assert(isArraysEqual<i32>(reversed1024, expected4, 4));
|
||||
|
||||
assertSortedDefault<i32>(revesed10000);
|
||||
assert(isArraysEqual<i32>(revesed10000, expected4, 4));
|
||||
assertSortedDefault<i32>(reversed10000);
|
||||
assert(isArraysEqual<i32>(reversed10000, expected4, 4));
|
||||
|
||||
assertSortedDefault<i32>(randomized512);
|
||||
|
||||
|
Reference in New Issue
Block a user