Add array methods: findIndex, reduce, some, every (#49)

This commit is contained in:
Igor 2018-03-25 13:13:53 +02:00 committed by Daniel Wirtz
parent 38a025950e
commit 710fcefd72
6 changed files with 2949 additions and 4 deletions

4
std/assembly.d.ts vendored
View File

@ -273,12 +273,16 @@ declare class Array<T> {
length: i32;
/** Constructs a new array. */
constructor(capacity?: i32);
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
findIndex(predicate: (element: T, index: i32, array?: Array<T>) => bool): i32;
includes(searchElement: T, fromIndex?: i32): bool;
indexOf(searchElement: T, fromIndex?: i32): i32;
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
push(element: T): void;
pop(): T;
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U, initialValue: U): U;
shift(): T;
some(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
unshift(element: T): i32;
slice(from: i32, to?: i32): T[];
splice(start: i32, deleteCount?: i32): void;

View File

@ -25,6 +25,30 @@ export class Array<T> {
this.__capacity = this.__length = capacity;
}
every(callbackfn: (element: T, index: i32, array: Array<T>) => bool): bool {
var toIndex: i32 = this.__length;
var i: i32 = 0;
while (i < toIndex && i < this.__length) {
if (!callbackfn(load<T>(this.__memory + <usize>i * sizeof<T>()), i, this)) {
return false;
}
i += 1;
}
return true;
}
findIndex(predicate: (element: T, index: i32, array: Array<T>) => bool): i32 {
var toIndex: i32 = this.__length;
var i: i32 = 0;
while (i < toIndex && i < this.__length) {
if (predicate(load<T>(this.__memory + <usize>i * sizeof<T>()), i, this)) {
return i;
}
i += 1;
}
return -1;
}
get length(): i32 {
return this.__length;
}
@ -129,6 +153,20 @@ export class Array<T> {
return load<T>(this.__memory + <usize>--this.__length * sizeof<T>());
}
reduce<U>(
callbackfn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U,
initialValue: U
): U {
var accumulator: U = initialValue;
var toIndex: i32 = this.__length;
var i: i32 = 0;
while (i < toIndex && i < this.__length) {
accumulator = callbackfn(accumulator, load<T>(this.__memory + <usize>i * sizeof<T>()), i, this);
i += 1;
}
return accumulator;
}
shift(): T {
if (this.__length < 1) {
throw new RangeError("Array is empty"); // return changetype<T>(0) ?
@ -148,6 +186,18 @@ export class Array<T> {
return element;
}
some(callbackfn: (element: T, index: i32, array: Array<T>) => bool): bool {
var toIndex: i32 = this.__length;
var i: i32 = 0;
while (i < toIndex && i < this.__length) {
if (callbackfn(load<T>(this.__memory + <usize>i * sizeof<T>()), i, this)) {
return true;
}
i += 1;
}
return false;
}
unshift(element: T): i32 {
var oldCapacity = this.__capacity;
if (this.__length == oldCapacity) {

4
std/portable.d.ts vendored
View File

@ -218,12 +218,16 @@ declare class Array<T> {
[key: number]: T;
length: i32;
constructor(capacity?: i32);
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
findIndex(predicate: (element: T, index: i32, array?: Array<T>) => bool): i32;
includes(searchElement: T, fromIndex?: i32): bool;
indexOf(searchElement: T, fromIndex?: i32): i32;
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
push(element: T): void;
pop(): T;
reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: i32, array: Array<T>) => U, initialValue: U): U;
shift(): T;
some(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
unshift(element: T): i32;
slice(from: i32, to?: i32): T[];
splice(start: i32, deleteCount?: i32): void;

File diff suppressed because it is too large Load Diff

View File

@ -173,3 +173,153 @@ assert(arr.length == 4);
assert(arr.__capacity == 8);
assert(arr[0] == 44);
assert(arr[1] == 42);
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);
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => value == 1);
assert(i == 1);
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => value == 100);
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
return value == 100;
});
// array should be changed, but this method result should be calculated for old array length
assert(i == -1);
assert(arr.length == 8);
i = arr.findIndex((value: i32, index: i32, array: Array<i32>): bool => value == 100);
assert(i != -1);
arr.pop();
arr.pop();
arr.pop();
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
return value == 100;
});
// only 2 first items was looked up, since last 2 was removed by .pop()
assert(i == -1);
assert(arr.length == 2);
arr.push(2);
arr.push(3);
/*=============================== every ==========================*/
var every = arr.every((value: i32, index: i32, array: Array<i32>): bool => value >= 0);
assert(every == true);
every = arr.every((value: i32, index: i32, array: Array<i32>): bool => value <= 0);
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
return value < 10;
});
// array should be changed, but this method result should be calculated for old array length
assert(every == true);
assert(arr.length == 8);
every = arr.every((value: i32, index: i32, array: Array<i32>): bool => value < 10);
assert(every == false);
arr.pop();
arr.pop();
arr.pop();
arr.pop();
// Test side effect pop
every = arr.every((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
return value < 3;
});
// only 2 first items was looked up, since last 2 was removed by .pop()
assert(every == true);
assert(arr.length == 2);
arr.push(2);
arr.push(3);
/*=============================== some ==========================*/
var some = arr.some((value: i32, index: i32, array: Array<i32>): bool => value >= 3);
assert(some == true);
some = arr.some((value: i32, index: i32, array: Array<i32>): bool => value <= -1);
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
return value > 10;
});
// array should be changed, but this method result should be calculated for old array length
assert(some == false);
assert(arr.length == 8);
some = arr.some((value: i32, index: i32, array: Array<i32>): bool => value > 10);
assert(some == true);
arr.pop();
arr.pop();
arr.pop();
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
return value > 3;
});
// only 2 first items was looked up, since last 2 was removed by .pop()
assert(some == false);
assert(arr.length == 2);
arr.push(2);
arr.push(3);
/*=============================== reduce ==========================*/
i = arr.reduce<i32>(((prev: i32, current: i32, index: i32, array: Array<i32>): i32 => prev + current), 0);
assert(i == 6);
// init value
i = arr.reduce<i32>(((prev: i32, current: i32, index: i32, array: Array<i32>): i32 => prev + current), 4);
assert(i == 10);
var boolVal = arr.reduce<bool>(((prev: bool, current: i32, index: i32, array: Array<i32>): bool => prev || current > 2), false);
assert(boolVal == true);
boolVal = arr.reduce<bool>(((prev: bool, current: i32, index: i32, array: Array<i32>): bool => prev || current > 100), false);
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
return prev + current;
}), 0);
// array should be changed, but this method result should be calculated for old array length
assert(i == 6);
assert(arr.length == 8);
i = arr.reduce<i32>(((prev: i32, current: i32, index: i32, array: Array<i32>): i32 => prev + current), 0);
assert(i == 10);
arr.pop();
arr.pop();
arr.pop();
arr.pop();
// Test side effect pop
i = arr.reduce<i32>(((prev: i32, current: i32, index: i32, array: Array<i32>): i32 => {
array.pop(); //poped items shouldn't be reduced, and we shouldn't go out of bounds
return prev + current;
}), 0);
// only 2 first items was reduced, since last 2 was removed by .pop()
assert(i == 1);
assert(arr.length == 2);

File diff suppressed because it is too large Load Diff