From 49d29fc9f2b3591e0827b78ee80abcbc4cd2b15f Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Sun, 14 Jan 2018 21:17:43 +0100 Subject: [PATCH] More std array --- src/compiler.ts | 4 +- src/parser.ts | 2 +- src/program.ts | 11 +- std/assembly.d.ts | 14 +- std/assembly/array.ts | 172 +++++-- std/portable.d.ts | 12 +- tests/compiler.js | 2 + tests/compiler/.gitignore | 1 + tests/compiler/std/array.optimized.wast | 571 ++++++++++++++++----- tests/compiler/std/array.ts | 27 + tests/compiler/std/array.wast | 644 +++++++++++++++++++----- tests/compiler/std/carray.wast | 1 + tests/compiler/std/heap.wast | 1 + 13 files changed, 1149 insertions(+), 313 deletions(-) create mode 100644 tests/compiler/.gitignore diff --git a/src/compiler.ts b/src/compiler.ts index 0d696dbd..249d351a 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -2469,7 +2469,7 @@ export class Compiler extends DiagnosticEmitter { } else { // too few arguments this.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range, - (operandIndex + numParametersInclThis - numParameters).toString(10), + (operandIndex + numParameters - numParametersInclThis).toString(10), numArguments.toString(10) ); return this.module.createUnreachable(); @@ -2686,7 +2686,7 @@ export class Compiler extends DiagnosticEmitter { case ElementKind.PROPERTY: // instance property (here: getter) var getter = (element).getterPrototype; assert(getter != null); - var getterInstance = (getter).resolve(); // reports + var getterInstance = (getter).resolve(null); // reports if (!getterInstance) return this.module.createUnreachable(); assert(getterInstance.parameters.length == 0); diff --git a/src/parser.ts b/src/parser.ts index a61cb28e..7c01be58 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -564,7 +564,7 @@ export class Parser extends DiagnosticEmitter { } var initializer: Expression | null = null; if (tn.skip(Token.EQUALS)) { - initializer = this.parseExpression(tn); + initializer = this.parseExpression(tn, Precedence.COMMA + 1); if (!initializer) return null; } diff --git a/src/program.ts b/src/program.ts index 5907e2bd..9dcdd978 100644 --- a/src/program.ts +++ b/src/program.ts @@ -1562,7 +1562,7 @@ export class FunctionPrototype extends Element { if (typeNode = declaration.parameters[i].type) { var parameterType = this.program.resolveType(typeNode, contextualTypeArguments, true); // reports if (parameterType) { - parameters[i] = new Parameter(declaration.parameters[i].name.name, parameterType); + parameters[i] = new Parameter(declaration.parameters[i].name.name, parameterType, declaration.parameters[i].initializer); parameterTypes[i] = parameterType; } else return null; @@ -2006,10 +2006,15 @@ export class ClassPrototype extends Element { instance.members.set(member.simpleName, methodPrototype); break; - case ElementKind.PROPERTY: // instance properties are just copied because there is nothing to partially-resolve + case ElementKind.PROPERTY: // instance properties are cloned with partially resolved getters and setters if (!instance.members) instance.members = new Map(); - instance.members.set(member.simpleName, member); + assert((member).getterPrototype); + var instanceProperty = new Property(this.program, member.simpleName, member.internalName, this); + instanceProperty.getterPrototype = ((member).getterPrototype).resolvePartial(typeArguments); + if ((member).setterPrototype) + instanceProperty.setterPrototype = ((member).setterPrototype).resolvePartial(typeArguments); + instance.members.set(member.simpleName, instanceProperty); break; default: diff --git a/std/assembly.d.ts b/std/assembly.d.ts index 55fd5310..17061ba0 100644 --- a/std/assembly.d.ts +++ b/std/assembly.d.ts @@ -201,15 +201,19 @@ declare function parseFloat(str: string): f64; /** Class representing a sequence of values of type `T`. */ declare class Array { [key: number]: T; - - /** Current maximum capacity of the array. */ - readonly capacity: i32; - /** Current length of the array. */ length: i32; - /** Constructs a new array. */ constructor(capacity?: i32); + indexOf(searchElement: T, fromIndex?: i32): i32; + lastIndexOf(searchElement: T, fromIndex?: i32): i32; + push(element: T): void; + pop(): T; + shift(): T; + unshift(element: T): i32; + slice(from: i32, to?: i32): T[]; + splice(start: i32, deleteCount?: i32): void; + reverse(): T[]; } /** Class representing a C-like array of values of type `T` with limited capabilities. */ diff --git a/std/assembly/array.ts b/std/assembly/array.ts index e3c0243b..f4be3c74 100644 --- a/std/assembly/array.ts +++ b/std/assembly/array.ts @@ -1,38 +1,8 @@ export class Array { private __memory: usize; - private __capacity: i32; - length: i32; - - constructor(capacity: i32 = 0) { - if (capacity < 0) - throw new RangeError("invalid array length"); - this.__capacity = this.length = capacity; - this.__memory = capacity > 0 ? allocate_memory(capacity * sizeof()) : 0; - } - - @operator("[]") - private __get(index: i32): T { - if (index >= this.__capacity) - throw new RangeError("index out of range"); - return load(this.__memory + index * sizeof()); - } - - @operator("[]=") - private __set(index: i32, value: T): void { - if (index >= this.__capacity) - throw new RangeError("index out of range"); - store(this.__memory + index * sizeof(), value); - } - - indexOf(searchElement: T, fromIndex: i32 = 0): i32 { - if (fromIndex >= this.__capacity) - throw new RangeError("fromIndex out of range"); - for (var index: usize = fromIndex, length: usize = min(this.length, this.__capacity); index < length; ++index) - if (load(this.__memory + index * sizeof()) == searchElement) - return index; - return -1; - } + private __capacity: i32; // capped to [0, 0x7fffffff] + private __length: i32; // capped to [0, __capacity] private __grow(newCapacity: i32): void { assert(newCapacity > this.__capacity); @@ -45,35 +15,93 @@ export class Array { this.__capacity = newCapacity; } + constructor(capacity: i32 = 0) { + if (capacity < 0) + throw new RangeError("Invalid array length"); + this.__memory = capacity ? allocate_memory(capacity * sizeof()) : 0; + this.__capacity = this.__length = capacity; + } + + get length(): i32 { + return this.__length; + } + + set length(length: i32) { + if (length < 0) + throw new RangeError("Invalid array length"); + if (length > this.__capacity) + this.__grow(max(length, this.__capacity << 1)); + this.__length = length; + } + + @operator("[]") + private __get(index: i32): T { + if (index >= this.__capacity) + throw new Error("Index out of bounds"); // return changetype(0) ? + return load(this.__memory + index * sizeof()); + } + + @operator("[]=") + private __set(index: i32, value: T): void { + if (index < 0) + throw new Error("Index out of bounds"); + if (index >= this.__capacity) + this.__grow(max(index + 1, this.__capacity << 1)); + store(this.__memory + index * sizeof(), value); + } + + indexOf(searchElement: T, fromIndex: i32 = 0): i32 { + if (fromIndex < 0) + fromIndex = this.__length + fromIndex; + while (fromIndex < this.__length) { + if (load(this.__memory + fromIndex * sizeof()) == searchElement) + return fromIndex; + ++fromIndex; + } + return -1; + } + + lastIndexOf(searchElement: T, fromIndex: i32 = 0): i32 { + if (fromIndex < 0) + fromIndex = this.__length + fromIndex; + else if (fromIndex >= this.__length) + fromIndex = this.__length - 1; + while (fromIndex >= 0) { + if (load(this.__memory + fromIndex * sizeof()) == searchElement) + return fromIndex; + --fromIndex; + } + return -1; + } + push(element: T): i32 { - if (this.length >= this.__capacity) - this.__grow(max(this.length + 1, this.__capacity << 1)); - store(this.__memory + this.length * sizeof(), element); - return ++this.length; + if (this.__length == this.__capacity) + this.__grow(this.__capacity ? this.__capacity << 1 : 1); + store(this.__memory + this.__length * sizeof(), element); + return ++this.__length; } pop(): T { - if (this.length < 1 || this.length > this.__capacity) - throw new RangeError("index out of range"); - --this.length; - return load(this.__memory + this.length * sizeof()); + if (this.__length < 1) + throw new RangeError("Array is empty"); // return changetype(0) ? + return load(this.__memory + --this.__length * sizeof()); } shift(): T { - if (this.length < 1 || this.length > this.__capacity) - throw new RangeError("index out of range"); + if (this.__length < 1) + throw new RangeError("Array is empty"); // return changetype(0) ? var element = load(this.__memory); move_memory(this.__memory, this.__memory + sizeof(), (this.__capacity - 1) * sizeof()); set_memory(this.__memory + (this.__capacity - 1) * sizeof(), 0, sizeof()); - --this.length; + --this.__length; return element; } unshift(element: T): i32 { var oldCapacity = this.__capacity; - if (this.length >= oldCapacity) { - // inlined `this.__grow(max(this.length + 1, oldCapacity * 2))` (avoids moving twice) - var newCapacity = max(this.length + 1, oldCapacity * 2); + if (this.__length == oldCapacity) { + // inlined __grow (avoids moving twice) + var newCapacity: i32 = oldCapacity ? oldCapacity << 1 : 1; assert(newCapacity > this.__capacity); var newMemory = allocate_memory(newCapacity * sizeof()); if (this.__memory) { @@ -85,7 +113,53 @@ export class Array { } else move_memory(this.__memory + sizeof(), this.__memory, oldCapacity * sizeof()); store(this.__memory, element); - return ++this.length; + return ++this.__length; + } + + slice(begin: i32 = 0, end: i32 = i32.MAX_VALUE): Array { + if (begin < 0) { + begin = this.__length + begin; + if (begin < 0) + begin = 0; + } else if (begin > this.__length) + begin = this.__length; + if (end < 0) + end = this.__length + end; + else if (end > this.__length) + end = this.__length; + if (end < begin) + end = begin; + var capacity = end - begin; + assert(capacity >= 0); + var sliced = new Array(capacity); + if (capacity) + move_memory(sliced.__memory, this.__memory + begin * sizeof(), capacity * sizeof()); + return sliced; + } + + splice(start: i32, deleteCount: i32 = i32.MAX_VALUE): void { + if (deleteCount < 1) + return; + if (start < 0) { + start = this.__length + start; + if (start < 0) + start = 0; + else if (start >= this.__length) + return; + } else if (start >= this.__length) + return; + deleteCount = min(deleteCount, this.__length - start); + move_memory(this.__memory + start * sizeof(), this.__memory + (start + deleteCount) * sizeof(), deleteCount * sizeof()); + this.__length -= deleteCount; + } + + reverse(): Array { + for (var front: usize = 0, back: usize = this.__length - 1; front < back; ++front, --back) { + var temp = load(this.__memory + front * sizeof()); + store(this.__memory + front * sizeof(), load(this.__memory + back * sizeof())); + store(this.__memory + back * sizeof(), temp); + } + return this; } } @@ -97,14 +171,14 @@ export class CArray { @operator("[]") private __get(index: i32): T { if (index < 0) - throw new RangeError("index out of range"); + throw new RangeError("Index out of range"); return load(changetype(this) + index * sizeof()); } @operator("[]=") private __set(index: i32, value: T): void { if (index < 0) - throw new RangeError("index out of range"); + throw new RangeError("Index out of range"); store(changetype(this) + index * sizeof(), value); } } diff --git a/std/portable.d.ts b/std/portable.d.ts index ce0787aa..84a4668d 100644 --- a/std/portable.d.ts +++ b/std/portable.d.ts @@ -148,13 +148,17 @@ declare class Array { [key: number]: T; length: i32; constructor(capacity?: i32); - push(value: T): void; + indexOf(searchElement: T, fromIndex?: i32): i32; + lastIndexOf(searchElement: T, fromIndex?: i32): i32; + push(element: T): void; pop(): T; - unshift(value: T): void; shift(): T; - join(delim: string): string; + unshift(element: T): i32; slice(from: i32, to?: i32): T[]; - splice(index: i32, count: i32): T[]; + splice(start: i32, deleteCount?: i32): void; + reverse(): T[]; + + join(delim: string): string; } declare class Uint8Array extends Array {} diff --git a/tests/compiler.js b/tests/compiler.js index e5c0d063..265f9cb7 100644 --- a/tests/compiler.js +++ b/tests/compiler.js @@ -97,6 +97,8 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => { actualOptimized = module.toText(); module.runPasses([ "inlining" ]); actualInlined = module.toText(); + if (isCreate) + fs.writeFileSync(__dirname + "/compiler/" + fixture + ".optimized.wasm", module.toBinary()); } else { failed = true; console.log(chalk.red("validate ERROR")); diff --git a/tests/compiler/.gitignore b/tests/compiler/.gitignore new file mode 100644 index 00000000..19e1bced --- /dev/null +++ b/tests/compiler/.gitignore @@ -0,0 +1 @@ +*.wasm diff --git a/tests/compiler/std/array.optimized.wast b/tests/compiler/std/array.optimized.wast index 02857b39..c23f88d1 100644 --- a/tests/compiler/std/array.optimized.wast +++ b/tests/compiler/std/array.optimized.wast @@ -4,6 +4,7 @@ (type $iv (func (param i32))) (type $iiv (func (param i32 i32))) (type $iii (func (param i32 i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) (type $v (func)) (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) (global $std/array/arr (mut i32) (i32.const 0)) @@ -101,7 +102,12 @@ ) (get_local $1) ) - (func $std:heap/copy_memory (; 1 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (func $std:array/Array#get:length (; 1 ;) (type $ii) (param $0 i32) (result i32) + (i32.load offset=8 + (get_local $0) + ) + ) + (func $std:heap/copy_memory (; 2 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (local $4 i32) (loop $continue|0 @@ -1677,7 +1683,7 @@ ) ) ) - (func $std:heap/move_memory (; 2 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (func $std:heap/move_memory (; 3 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (if (i32.eq @@ -1967,10 +1973,10 @@ ) ) ) - (func $std:heap/free_memory (; 3 ;) (type $iv) (param $0 i32) + (func $std:heap/free_memory (; 4 ;) (type $iv) (param $0 i32) (nop) ) - (func $std:array/Array#__grow (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32) + (func $std:array/Array#__grow (; 5 ;) (type $iiv) (param $0 i32) (param $1 i32) (local $2 i32) (if (i32.le_s @@ -2022,11 +2028,10 @@ (get_local $1) ) ) - (func $std:array/Array#push (; 5 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (func $std:array/Array#push (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) - (local $3 i32) (if - (i32.ge_u + (i32.eq (i32.load offset=8 (get_local $0) ) @@ -2036,27 +2041,17 @@ ) (call $std:array/Array#__grow (get_local $0) - (select - (tee_local $2 - (i32.add - (i32.load offset=8 - (get_local $0) - ) - (i32.const 1) + (if (result i32) + (i32.load offset=4 + (get_local $0) + ) + (i32.shl + (i32.load offset=4 + (get_local $0) ) + (i32.const 1) ) - (tee_local $3 - (i32.shl - (i32.load offset=4 - (get_local $0) - ) - (i32.const 1) - ) - ) - (i32.gt_s - (get_local $2) - (get_local $3) - ) + (i32.const 1) ) ) ) @@ -2087,7 +2082,7 @@ ) (get_local $2) ) - (func $std:array/Array#__get (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (func $std:array/Array#__get (; 7 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (if (i32.ge_u (get_local $1) @@ -2109,66 +2104,52 @@ ) ) ) - (func $std:array/Array#pop (; 7 ;) (type $ii) (param $0 i32) (result i32) + (func $std:array/Array#pop (; 8 ;) (type $ii) (param $0 i32) (result i32) (local $1 i32) (if - (i32.and - (if (result i32) - (tee_local $1 - (i32.lt_s - (i32.load offset=8 - (get_local $0) - ) - (i32.const 1) - ) - ) - (get_local $1) - (i32.gt_u - (i32.load offset=8 - (get_local $0) - ) - (i32.load offset=4 - (get_local $0) - ) - ) - ) - (i32.const 1) - ) - (unreachable) - ) - (i32.store offset=8 - (get_local $0) - (i32.sub + (i32.lt_s (i32.load offset=8 (get_local $0) ) (i32.const 1) ) + (unreachable) ) (i32.load (i32.add (i32.load (get_local $0) ) - (i32.mul - (i32.load offset=8 + (block (result i32) + (i32.store offset=8 (get_local $0) + (tee_local $1 + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + ) + (i32.mul + (get_local $1) + (i32.const 4) ) - (i32.const 4) ) ) ) ) - (func $std:array/Array#unshift (; 8 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (func $std:array/Array#unshift (; 9 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) (local $4 i32) (if - (i32.ge_u + (i32.eq (i32.load offset=8 (get_local $0) ) - (tee_local $4 + (tee_local $2 (i32.load offset=4 (get_local $0) ) @@ -2177,26 +2158,14 @@ (block (if (i32.le_s - (tee_local $2 - (select - (tee_local $2 - (i32.add - (i32.load offset=8 - (get_local $0) - ) - (i32.const 1) - ) - ) - (tee_local $3 - (i32.mul - (get_local $4) - (i32.const 2) - ) - ) - (i32.gt_s + (tee_local $3 + (if (result i32) + (get_local $2) + (i32.shl (get_local $2) - (get_local $3) + (i32.const 1) ) + (i32.const 1) ) ) (i32.load offset=4 @@ -2205,10 +2174,10 @@ ) (unreachable) ) - (set_local $3 + (set_local $4 (call $std:heap/allocate_memory (i32.mul - (get_local $2) + (get_local $3) (i32.const 4) ) ) @@ -2220,14 +2189,14 @@ (block (call $std:heap/move_memory (i32.add - (get_local $3) + (get_local $4) (i32.const 4) ) (i32.load (get_local $0) ) (i32.mul - (get_local $4) + (get_local $2) (i32.const 4) ) ) @@ -2240,11 +2209,11 @@ ) (i32.store (get_local $0) - (get_local $3) + (get_local $4) ) (i32.store offset=4 (get_local $0) - (get_local $2) + (get_local $3) ) ) (call $std:heap/move_memory @@ -2258,7 +2227,7 @@ (get_local $0) ) (i32.mul - (get_local $4) + (get_local $2) (i32.const 4) ) ) @@ -2271,7 +2240,7 @@ ) (i32.store offset=8 (get_local $0) - (tee_local $2 + (tee_local $0 (i32.add (i32.load offset=8 (get_local $0) @@ -2280,9 +2249,9 @@ ) ) ) - (get_local $2) + (get_local $0) ) - (func $std:heap/set_memory (; 9 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (func $std:heap/set_memory (; 10 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i64) (local $4 i32) (if @@ -2615,28 +2584,12 @@ ) ) ) - (func $std:array/Array#shift (; 10 ;) (type $ii) (param $0 i32) (result i32) + (func $std:array/Array#shift (; 11 ;) (type $ii) (param $0 i32) (result i32) (local $1 i32) (if - (i32.and - (if (result i32) - (tee_local $1 - (i32.lt_s - (i32.load offset=8 - (get_local $0) - ) - (i32.const 1) - ) - ) - (get_local $1) - (i32.gt_u - (i32.load offset=8 - (get_local $0) - ) - (i32.load offset=4 - (get_local $0) - ) - ) + (i32.lt_s + (i32.load offset=8 + (get_local $0) ) (i32.const 1) ) @@ -2698,7 +2651,250 @@ ) (get_local $1) ) - (func $start (; 11 ;) (type $v) + (func $std:array/Array#reverse (; 12 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (set_local $1 + (i32.const 0) + ) + (set_local $2 + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (loop $continue|0 + (if + (i32.lt_u + (get_local $1) + (get_local $2) + ) + (block + (set_local $3 + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + ) + ) + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + (get_local $3) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + (get_local $0) + ) + (func $std:array/Array#indexOf (; 13 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (if + (i32.lt_s + (get_local $2) + (i32.const 0) + ) + (set_local $2 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (get_local $2) + ) + ) + ) + (loop $continue|0 + (if + (i32.lt_u + (get_local $2) + (i32.load offset=8 + (get_local $0) + ) + ) + (block + (if + (i32.eq + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + ) + (get_local $1) + ) + (return + (get_local $2) + ) + ) + (set_local $2 + (i32.add + (get_local $2) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + (i32.const -1) + ) + (func $std:array/Array#splice (; 14 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (if + (i32.lt_s + (get_local $2) + (i32.const 1) + ) + (return) + ) + (if + (i32.lt_s + (get_local $1) + (i32.const 0) + ) + (if + (i32.lt_s + (tee_local $1 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (get_local $1) + ) + ) + (i32.const 0) + ) + (set_local $1 + (i32.const 0) + ) + (if + (i32.ge_s + (get_local $1) + (i32.load offset=8 + (get_local $0) + ) + ) + (return) + ) + ) + (if + (i32.ge_s + (get_local $1) + (i32.load offset=8 + (get_local $0) + ) + ) + (return) + ) + ) + (call $std:heap/move_memory + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.add + (get_local $1) + (tee_local $2 + (select + (get_local $2) + (tee_local $1 + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (get_local $1) + ) + ) + (i32.lt_s + (get_local $2) + (get_local $1) + ) + ) + ) + ) + (i32.const 4) + ) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + (i32.store offset=8 + (get_local $0) + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (get_local $2) + ) + ) + ) + (func $start (; 15 ;) (type $v) (set_global $std:heap/HEAP_OFFSET (get_global $HEAP_BASE) ) @@ -2708,7 +2904,7 @@ ) ) (if - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (unreachable) @@ -2737,7 +2933,7 @@ ) (if (i32.ne - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 1) @@ -2766,7 +2962,7 @@ (unreachable) ) (if - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (unreachable) @@ -2788,7 +2984,7 @@ ) (if (i32.ne - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 1) @@ -2822,7 +3018,7 @@ ) (if (i32.ne - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 2) @@ -2866,7 +3062,7 @@ ) (if (i32.ne - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 3) @@ -2920,7 +3116,7 @@ ) (if (i32.ne - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 4) @@ -2984,7 +3180,7 @@ ) (if (i32.ne - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 5) @@ -3064,7 +3260,7 @@ ) (if (i32.ne - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 4) @@ -3134,7 +3330,7 @@ ) (if (i32.ne - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 3) @@ -3180,5 +3376,140 @@ ) (unreachable) ) + (drop + (call $std:array/Array#reverse + (get_global $std/array/arr) + ) + ) + (if + (i32.ne + (call $std:array/Array#get:length + (get_global $std/array/arr) + ) + (i32.const 3) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 42) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#indexOf + (get_global $std/array/arr) + (i32.const 44) + (i32.const 0) + ) + ) + (if + (get_global $std/array/i) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#indexOf + (get_global $std/array/arr) + (i32.const 42) + (i32.const 0) + ) + ) + (if + (i32.ne + (get_global $std/array/i) + (i32.const 2) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#indexOf + (get_global $std/array/arr) + (i32.const 45) + (i32.const 0) + ) + ) + (if + (i32.ne + (get_global $std/array/i) + (i32.const -1) + ) + (unreachable) + ) + (call $std:array/Array#splice + (get_global $std/array/arr) + (i32.const 1) + (i32.const 1) + ) + (if + (i32.ne + (call $std:array/Array#get:length + (get_global $std/array/arr) + ) + (i32.const 2) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 42) + ) + (unreachable) + ) ) ) diff --git a/tests/compiler/std/array.ts b/tests/compiler/std/array.ts index 3e27683b..4af7f747 100644 --- a/tests/compiler/std/array.ts +++ b/tests/compiler/std/array.ts @@ -73,3 +73,30 @@ assert(arr.__capacity == 8); assert(arr[0] == 42); assert(arr[1] == 43); assert(arr[2] == 44); + +arr.reverse(); + +assert(arr.length == 3); +assert(arr.__capacity == 8); +assert(arr[0] == 44); +assert(arr[1] == 43); +assert(arr[2] == 42); + +i = arr.indexOf(44); + +assert(i == 0); + +i = arr.indexOf(42); + +assert(i == 2); + +i = arr.indexOf(45); + +assert(i == - 1); + +arr.splice(1, 1); + +assert(arr.length == 2); +assert(arr.__capacity == 8); +assert(arr[0] == 44); +assert(arr[1] == 42); diff --git a/tests/compiler/std/array.wast b/tests/compiler/std/array.wast index ff34378a..7d096405 100644 --- a/tests/compiler/std/array.wast +++ b/tests/compiler/std/array.wast @@ -5,6 +5,7 @@ (type $iv (func (param i32))) (type $iiv (func (param i32 i32))) (type $iii (func (param i32 i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) (type $v (func)) (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) (global $std:heap/ALIGN_LOG2 i32 (i32.const 3)) @@ -113,7 +114,14 @@ (get_local $4) ) ) - (func $std:heap/copy_memory (; 1 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (func $std:array/Array#get:length (; 1 ;) (type $ii) (param $0 i32) (result i32) + (return + (i32.load offset=8 + (get_local $0) + ) + ) + ) + (func $std:heap/copy_memory (; 2 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (local $4 i32) (local $5 i32) @@ -1913,7 +1921,7 @@ ) ) ) - (func $std:heap/move_memory (; 2 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (func $std:heap/move_memory (; 3 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (if (i32.eq @@ -2237,9 +2245,9 @@ ) ) ) - (func $std:heap/free_memory (; 3 ;) (type $iv) (param $0 i32) + (func $std:heap/free_memory (; 4 ;) (type $iv) (param $0 i32) ) - (func $std:array/Array#__grow (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32) + (func $std:array/Array#__grow (; 5 ;) (type $iiv) (param $0 i32) (param $1 i32) (local $2 i32) (if (i32.eqz @@ -2295,11 +2303,10 @@ (get_local $1) ) ) - (func $std:array/Array#push (; 5 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (func $std:array/Array#push (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) - (local $3 i32) (if - (i32.ge_u + (i32.eq (i32.load offset=8 (get_local $0) ) @@ -2309,27 +2316,17 @@ ) (call $std:array/Array#__grow (get_local $0) - (select - (tee_local $2 - (i32.add - (i32.load offset=8 - (get_local $0) - ) - (i32.const 1) + (if (result i32) + (i32.load offset=4 + (get_local $0) + ) + (i32.shl + (i32.load offset=4 + (get_local $0) ) + (i32.const 1) ) - (tee_local $3 - (i32.shl - (i32.load offset=4 - (get_local $0) - ) - (i32.const 1) - ) - ) - (i32.gt_s - (get_local $2) - (get_local $3) - ) + (i32.const 1) ) ) ) @@ -2365,7 +2362,7 @@ ) ) ) - (func $std:array/Array#__get (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (func $std:array/Array#__get (; 7 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (if (i32.ge_u (get_local $1) @@ -2389,44 +2386,16 @@ ) ) ) - (func $std:array/Array#pop (; 7 ;) (type $ii) (param $0 i32) (result i32) + (func $std:array/Array#pop (; 8 ;) (type $ii) (param $0 i32) (result i32) (local $1 i32) (if - (i32.and - (if (result i32) - (i32.ne - (tee_local $1 - (i32.lt_s - (i32.load offset=8 - (get_local $0) - ) - (i32.const 1) - ) - ) - (i32.const 0) - ) - (get_local $1) - (i32.gt_u - (i32.load offset=8 - (get_local $0) - ) - (i32.load offset=4 - (get_local $0) - ) - ) - ) - (i32.const 1) - ) - (unreachable) - ) - (i32.store offset=8 - (get_local $0) - (i32.sub + (i32.lt_s (i32.load offset=8 (get_local $0) ) (i32.const 1) ) + (unreachable) ) (return (i32.load @@ -2435,8 +2404,20 @@ (get_local $0) ) (i32.mul - (i32.load offset=8 - (get_local $0) + (block (result i32) + (set_local $1 + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (i32.store offset=8 + (get_local $0) + (get_local $1) + ) + (get_local $1) ) (i32.const 4) ) @@ -2444,12 +2425,11 @@ ) ) ) - (func $std:array/Array#unshift (; 8 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (func $std:array/Array#unshift (; 9 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) (local $4 i32) (local $5 i32) - (local $6 i32) (block (set_local $2 (i32.load offset=4 @@ -2458,7 +2438,7 @@ ) ) (if - (i32.ge_u + (i32.eq (i32.load offset=8 (get_local $0) ) @@ -2466,33 +2446,21 @@ ) (block (block - (set_local $5 - (select - (tee_local $3 - (i32.add - (i32.load offset=8 - (get_local $0) - ) - (i32.const 1) - ) - ) - (tee_local $4 - (i32.mul - (get_local $2) - (i32.const 2) - ) - ) - (i32.gt_s - (get_local $3) - (get_local $4) + (set_local $3 + (if (result i32) + (get_local $2) + (i32.shl + (get_local $2) + (i32.const 1) ) + (i32.const 1) ) ) ) (if (i32.eqz (i32.gt_s - (get_local $5) + (get_local $3) (i32.load offset=4 (get_local $0) ) @@ -2501,10 +2469,10 @@ (unreachable) ) (block - (set_local $6 + (set_local $4 (call $std:heap/allocate_memory (i32.mul - (get_local $5) + (get_local $3) (i32.const 4) ) ) @@ -2517,7 +2485,7 @@ (block (call $std:heap/move_memory (i32.add - (get_local $6) + (get_local $4) (i32.const 4) ) (i32.load @@ -2537,11 +2505,11 @@ ) (i32.store (get_local $0) - (get_local $6) + (get_local $4) ) (i32.store offset=4 (get_local $0) - (get_local $5) + (get_local $3) ) ) (call $std:heap/move_memory @@ -2568,7 +2536,7 @@ ) (return (block (result i32) - (set_local $3 + (set_local $5 (i32.add (i32.load offset=8 (get_local $0) @@ -2578,13 +2546,13 @@ ) (i32.store offset=8 (get_local $0) - (get_local $3) + (get_local $5) ) - (get_local $3) + (get_local $5) ) ) ) - (func $std:heap/set_memory (; 9 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (func $std:heap/set_memory (; 10 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (local $4 i32) (local $5 i64) @@ -2945,39 +2913,19 @@ ) ) ) - (func $std:array/Array#shift (; 10 ;) (type $ii) (param $0 i32) (result i32) + (func $std:array/Array#shift (; 11 ;) (type $ii) (param $0 i32) (result i32) (local $1 i32) - (local $2 i32) (if - (i32.and - (if (result i32) - (i32.ne - (tee_local $1 - (i32.lt_s - (i32.load offset=8 - (get_local $0) - ) - (i32.const 1) - ) - ) - (i32.const 0) - ) - (get_local $1) - (i32.gt_u - (i32.load offset=8 - (get_local $0) - ) - (i32.load offset=4 - (get_local $0) - ) - ) + (i32.lt_s + (i32.load offset=8 + (get_local $0) ) (i32.const 1) ) (unreachable) ) (block - (set_local $2 + (set_local $1 (i32.load (i32.load (get_local $0) @@ -3033,10 +2981,282 @@ ) ) (return - (get_local $2) + (get_local $1) ) ) - (func $start (; 11 ;) (type $v) + (func $std:array/Array#reverse (; 12 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (block $break|0 + (block + (set_local $1 + (i32.const 0) + ) + (set_local $2 + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + ) + (loop $continue|0 + (if + (i32.lt_u + (get_local $1) + (get_local $2) + ) + (block + (block + (block + (set_local $3 + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + ) + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + ) + ) + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + (get_local $3) + ) + ) + (block + (set_local $1 + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + (func $std:array/Array#indexOf (; 13 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (if + (i32.lt_s + (get_local $2) + (i32.const 0) + ) + (set_local $2 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (get_local $2) + ) + ) + ) + (block $break|0 + (loop $continue|0 + (if + (i32.lt_u + (get_local $2) + (i32.load offset=8 + (get_local $0) + ) + ) + (block + (block + (if + (i32.eq + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + ) + (get_local $1) + ) + (return + (get_local $2) + ) + ) + (set_local $2 + (i32.add + (get_local $2) + (i32.const 1) + ) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (return + (i32.sub + (i32.const 0) + (i32.const 1) + ) + ) + ) + (func $std:array/Array#splice (; 14 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (if + (i32.lt_s + (get_local $2) + (i32.const 1) + ) + (return) + ) + (if + (i32.lt_s + (get_local $1) + (i32.const 0) + ) + (block + (set_local $1 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (get_local $1) + ) + ) + (if + (i32.lt_s + (get_local $1) + (i32.const 0) + ) + (set_local $1 + (i32.const 0) + ) + (if + (i32.ge_s + (get_local $1) + (i32.load offset=8 + (get_local $0) + ) + ) + (return) + ) + ) + ) + (if + (i32.ge_s + (get_local $1) + (i32.load offset=8 + (get_local $0) + ) + ) + (return) + ) + ) + (set_local $2 + (select + (tee_local $3 + (get_local $2) + ) + (tee_local $4 + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (get_local $1) + ) + ) + (i32.lt_s + (get_local $3) + (get_local $4) + ) + ) + ) + (call $std:heap/move_memory + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.add + (get_local $1) + (get_local $2) + ) + (i32.const 4) + ) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + (i32.store offset=8 + (get_local $0) + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (get_local $2) + ) + ) + ) + (func $start (; 15 ;) (type $v) (set_global $std:heap/HEAP_OFFSET (get_global $HEAP_BASE) ) @@ -3054,7 +3274,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 0) @@ -3094,7 +3314,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 1) @@ -3130,7 +3350,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 0) @@ -3158,7 +3378,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 1) @@ -3198,7 +3418,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 2) @@ -3250,7 +3470,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 3) @@ -3314,7 +3534,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 4) @@ -3390,7 +3610,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 5) @@ -3486,7 +3706,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 4) @@ -3570,7 +3790,7 @@ (if (i32.eqz (i32.eq - (i32.load offset=8 + (call $std:array/Array#get:length (get_global $std/array/arr) ) (i32.const 3) @@ -3625,6 +3845,171 @@ ) (unreachable) ) + (drop + (call $std:array/Array#reverse + (get_global $std/array/arr) + ) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#get:length + (get_global $std/array/arr) + ) + (i32.const 3) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 44) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 42) + ) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#indexOf + (get_global $std/array/arr) + (i32.const 44) + (i32.const 0) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $std/array/i) + (i32.const 0) + ) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#indexOf + (get_global $std/array/arr) + (i32.const 42) + (i32.const 0) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $std/array/i) + (i32.const 2) + ) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#indexOf + (get_global $std/array/arr) + (i32.const 45) + (i32.const 0) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $std/array/i) + (i32.sub + (i32.const 0) + (i32.const 1) + ) + ) + ) + (unreachable) + ) + (call $std:array/Array#splice + (get_global $std/array/arr) + (i32.const 1) + (i32.const 1) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#get:length + (get_global $std/array/arr) + ) + (i32.const 2) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 44) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 42) + ) + ) + (unreachable) + ) ) ) (; @@ -3673,6 +4058,7 @@ GLOBAL: HEAP_BASE CLASS_PROTOTYPE: std:array/Array CLASS_PROTOTYPE: Array + PROPERTY: std:array/Array#length CLASS_PROTOTYPE: std:array/CArray CLASS_PROTOTYPE: CArray CLASS_PROTOTYPE: std:error/Error diff --git a/tests/compiler/std/carray.wast b/tests/compiler/std/carray.wast index 73092756..b8a276d0 100644 --- a/tests/compiler/std/carray.wast +++ b/tests/compiler/std/carray.wast @@ -251,6 +251,7 @@ GLOBAL: HEAP_BASE CLASS_PROTOTYPE: std:array/Array CLASS_PROTOTYPE: Array + PROPERTY: std:array/Array#length CLASS_PROTOTYPE: std:array/CArray CLASS_PROTOTYPE: CArray CLASS_PROTOTYPE: std:error/Error diff --git a/tests/compiler/std/heap.wast b/tests/compiler/std/heap.wast index dd6957a6..4810c28b 100644 --- a/tests/compiler/std/heap.wast +++ b/tests/compiler/std/heap.wast @@ -2842,6 +2842,7 @@ GLOBAL: HEAP_BASE CLASS_PROTOTYPE: std:array/Array CLASS_PROTOTYPE: Array + PROPERTY: std:array/Array#length CLASS_PROTOTYPE: std:array/CArray CLASS_PROTOTYPE: CArray CLASS_PROTOTYPE: std:error/Error