diff --git a/bin/asc.js b/bin/asc.js index 69b096cc..bf2b3fa8 100644 --- a/bin/asc.js +++ b/bin/asc.js @@ -93,9 +93,8 @@ function checkDiagnostics(parser) { if (!args.noLib) { var stdlibDir = path.join(__dirname + "..", "std", "assembly"); glob.sync("*.ts", { cwd: stdlibDir }).forEach(file => { - var nextPath = "std/" + file; var nextText = fs.readFileSync(path.join(stdlibDir, file), { encoding: "utf8" }); - parser = assemblyscript.parseFile(nextText, nextPath, parser, false); + parser = assemblyscript.parseFile(nextText, "std:" + file, parser, false); }); } diff --git a/package.json b/package.json index 53e060f2..9352d80a 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "url": "https://github.com/AssemblyScript/next/issues" }, "dependencies": { - "@types/node": "^8.5.1", "binaryen": "40.0.0-nightly.20171209", "glob": "^7.1.2", "minimist": "^1.2.0", @@ -23,6 +22,7 @@ "@types/glob": "^5.0.34", "@types/long": "^3.0.32", "@types/minimist": "^1.2.0", + "@types/node": "^8.5.1", "chalk": "^2.3.0", "diff": "^3.4.0", "long": "^3.2.0", diff --git a/src/program.ts b/src/program.ts index 80d25e52..f6cc9a39 100644 --- a/src/program.ts +++ b/src/program.ts @@ -914,7 +914,13 @@ export enum ElementFlags { /** Is global. */ GLOBAL = 1 << 11, /** Is read-only. */ - READONLY = 1 << 12 + READONLY = 1 << 12, + /** Is a public member. */ + PUBLIC = 1 << 13, + /** Is a protected member. */ + PROTECTED = 1 << 14, + /** Is a private member. */ + PRIVATE = 1 << 15 } /** Base class of all program elements. */ @@ -1441,8 +1447,11 @@ export class FieldPrototype extends Element { switch (this.declaration.modifiers[i].modifierKind) { case ModifierKind.EXPORT: this.isExported = true; break; case ModifierKind.READONLY: this.isReadonly = true; break; + case ModifierKind.PRIVATE: + case ModifierKind.PROTECTED: + case ModifierKind.PUBLIC: case ModifierKind.STATIC: break; // already handled - default: throw new Error("unexpected modifier"); + default: throw new Error("unexpected modifier: " + this.declaration.modifiers[i]); } } } diff --git a/std/assembly.d.ts b/std/assembly.d.ts index cd0e7fc8..94856253 100644 --- a/std/assembly.d.ts +++ b/std/assembly.d.ts @@ -191,10 +191,25 @@ declare class Array { /** Class representing a sequence of characters. */ declare class String { + static fromCharCode(ls: i32, hs?: i32): string; static fromCharCodes(arr: u16[]): string; static fromCodePoint(cp: i32): string; static fromCodePoints(arr: i32[]): string; + + readonly length: u32; + + charAt(index: u32): string; + charCodeAt(index: u32): u16; + concat(other: string): string; + endsWith(other: string): bool; + indexOf(other: string): u32; + startsWith(other: string): bool; + substr(start: u32, length?: u32): string; + substring(start: u32, end?: u32): string; + trim(): string; + trimLeft(): string; + trimRight(): string; } /** Class for representing a runtime error. Base class of all errors. */ @@ -237,6 +252,12 @@ declare class Heap { /** Copies a chunk of memory from one location to another. */ static copy(dest: usize, src: usize, n: usize): usize; + /** Fills a chunk of memory with the specified byte value. */ + static fill(dest: usize, c: u8, n: usize): usize; + + /** Compares two chunks of memory. Returns `0` if equal, otherwise the difference of the first differing bytes. */ + static compare(vl: usize, vr: usize, n: usize): i32; + private constructor(); } @@ -251,3 +272,6 @@ interface RegExp {} /** Annotates an element being part of the global namespace. */ declare function global(): any; + +/** Annotates a method being an operator overload. */ +declare function operator(token: string): any; diff --git a/std/assembly/heap.ts b/std/assembly/heap.ts index f6c0a1ec..e0181545 100644 --- a/std/assembly/heap.ts +++ b/std/assembly/heap.ts @@ -29,7 +29,7 @@ export class Heap { // just a big chunk of non-disposable memory for now } - static copy(dest: usize, src: usize, n: usize): usize { + static copy(dest: usize, src: usize, n: usize): usize { // TODO: use move_memory op once available assert(dest >= HEAP_BASE); // the following is based on musl's implementation of memcpy @@ -174,5 +174,76 @@ export class Heap { return dest; } + static fill(dest: usize, c: u8, n: usize): usize { // TODO: use set_memory op once available + assert(dest >= HEAP_BASE); + + // the following is based on musl's implementation of memset + if (!n) return dest; + + let s: usize = dest; + + // Fill head and tail with minimal branching + store(s, c); store(s + n - 1, c); + if (n <= 2) return dest; + store(s + 1, c); store(s + n - 2, c); + store(s + 2, c); store(s + n - 3, c); + if (n <= 6) return dest; + store(s + 3, c); store(s + n - 4, c); + if (n <= 8) return dest; + + // Align to 4 bytes + let k: usize = -s & 3; + s += k; + n -= k; + n &= -4; + + let c32: u32 = -1 / 255 * c; + + // Fill head and tail in preparation of setting 32 bytes at a time + store(s, c32); + store(s + n - 4, c32); + if (n <= 8) return dest; + store(s + 4, c32); + store(s + 8, c32); + store(s + n - 12, c32); + store(s + n - 8, c32); + if (n <= 24) return dest; + store(s + 12, c32); + store(s + 16, c32); + store(s + 20, c32); + store(s + 24, c32); + store(s + n - 28, c32); + store(s + n - 24, c32); + store(s + n - 20, c32); + store(s + n - 16, c32); + + // Align to 8 bytes + k = 24 + (s & 4); + s += k; + n -= k; + + // Set 32 bytes at a time + let c64: u64 = c32 | (c32 << 32); + while (n >= 32) { + store(s, c64); + store(s + 8, c64); + store(s + 16, c64); + store(s + 24, c64); + n -= 32; s += 32; + } + + return dest; + } + + static compare(vl: usize, vr: usize, n: usize): i32 { + if (vl == vr) return 0; + + // the following is based on musl's implementation of memcmp + while (n && load(vl) == load(vr)) { + n--; vl++; vr++; + } + return n ? load(vl) - load(vr) : 0; + } + private constructor() {} } diff --git a/std/assembly/string.ts b/std/assembly/string.ts index ecd560a4..7db5e5d5 100644 --- a/std/assembly/string.ts +++ b/std/assembly/string.ts @@ -1,4 +1,98 @@ @global() export class String { - // TODO + + private ptr: usize; + readonly length: u32; + + constructor(ptr: usize, len: u32) { + this.ptr = ptr; + this.length = len; + } + + charAt(index: u32): String { + assert(this != null && index < this.length); + return new String(this.ptr + (index << 1), 1); + } + + charCodeAt(index: u32): u16 { + assert(this != null && index < this.length); + return load(this.ptr + (index << 1)); + } + + @operator("+") + concat(other: String): String { + assert(this != null && other != null); + const len: u32 = this.length + other.length; + const ptr: usize = Heap.allocate(len << 1); + Heap.copy(ptr, this.ptr, this.length << 1); + Heap.copy(ptr, this.ptr + (len << 1), other.length << 1); + return new String(ptr, len); + } + + endsWith(other: String): bool { + assert(this != null && other != null); + if (other.length > this.length) + return false; + for (let i: u32 = this.length - other.length, j: u32 = 0, k: u32 = this.length; i < k;) + if (this.charCodeAt(i++) != other.charCodeAt(j++)) + return false; + return true; + } + + @operator("==") + equals(other: String): bool { + assert(this != null && other != null); + if (this.length != other.length) + return false; + for (let i: u32 = 0, k: u32 = this.length; i < k; ++i) + if (this.charCodeAt(i) != other.charCodeAt(i)) + return false; + return true; + } + + indexOf(other: String): u32 { + assert(this != null && other != null); + throw new Error("not implemented"); + } + + startsWith(other: String): bool { + assert(this != null && other != null); + if (other.length > this.length) + return false; + for (let i: u32 = 0, k: u32 = other.length; i < k; ++i) + if (this.charCodeAt(i) != other.charCodeAt(i)) + return false; + return true; + } + + substr(start: u32, length: u32 = -1): String { + assert(this != null); + if (start >= this.length) + return changetype(""); + const len: u32 = min(length, this.length - start); + return new String(this.ptr + (start << 1), len); + } + + substring(start: u32, end: u32 = -1): String { + assert(this != null); + if (start >= this.length || end <= start) + return changetype(""); + const len: u32 = min(end - start, this.length - start); + return new String(this.ptr + (start << 1), len); + } + + trim(): string { + assert(this != null); + throw new Error("not implemented"); + } + + trimLeft(): string { + assert(this != null); + throw new Error("not implemented"); + } + + trimRight(): string { + assert(this != null); + throw new Error("not implemented"); + } } diff --git a/tests/compiler.js b/tests/compiler.js index 9c9f98f4..20927475 100644 --- a/tests/compiler.js +++ b/tests/compiler.js @@ -26,7 +26,7 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => { var parser = new Parser(); if (filename.startsWith("std/")) { stdFiles.forEach(file => { - parser.parseFile(fs.readFileSync(__dirname + "/../std/assembly/" + file, { encoding: "utf8" }), file, false); + parser.parseFile(fs.readFileSync(__dirname + "/../std/assembly/" + file, { encoding: "utf8" }), "std:" + path.basename(file), false); }); fixture = "std/" + fixture; } diff --git a/tests/compiler/recursive.optimized.wast b/tests/compiler/recursive.optimized.wast new file mode 100644 index 00000000..9606cf22 --- /dev/null +++ b/tests/compiler/recursive.optimized.wast @@ -0,0 +1,31 @@ +(module + (type $ii (func (param i32) (result i32))) + (memory $0 1) + (export "fib" (func $recursive/fib)) + (export "memory" (memory $0)) + (func $recursive/fib (; 0 ;) (type $ii) (param $0 i32) (result i32) + (if + (i32.le_s + (get_local $0) + (i32.const 1) + ) + (return + (i32.const 1) + ) + ) + (i32.add + (call $recursive/fib + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (call $recursive/fib + (i32.sub + (get_local $0) + (i32.const 2) + ) + ) + ) + ) +) diff --git a/tests/compiler/recursive.ts b/tests/compiler/recursive.ts new file mode 100644 index 00000000..3d05cbe3 --- /dev/null +++ b/tests/compiler/recursive.ts @@ -0,0 +1,4 @@ +export function fib(n: i32): i32 { + if (n <= 1) return 1; + return fib(n - 1) + fib(n - 2); +} diff --git a/tests/compiler/recursive.wast b/tests/compiler/recursive.wast new file mode 100644 index 00000000..ad137f13 --- /dev/null +++ b/tests/compiler/recursive.wast @@ -0,0 +1,84 @@ +(module + (type $ii (func (param i32) (result i32))) + (global $HEAP_BASE i32 (i32.const 4)) + (memory $0 1) + (export "fib" (func $recursive/fib)) + (export "memory" (memory $0)) + (func $recursive/fib (; 0 ;) (type $ii) (param $0 i32) (result i32) + (if + (i32.le_s + (get_local $0) + (i32.const 1) + ) + (return + (i32.const 1) + ) + ) + (return + (i32.add + (call $recursive/fib + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (call $recursive/fib + (i32.sub + (get_local $0) + (i32.const 2) + ) + ) + ) + ) + ) +) +(; +[program.elements] + NaN + Infinity + isNaN + isFinite + clz + ctz + popcnt + rotl + rotr + abs + max + min + ceil + floor + copysign + nearest + reinterpret + sqrt + trunc + load + store + sizeof + select + unreachable + current_memory + grow_memory + parseInt + parseFloat + changetype + assert + i8 + i16 + i32 + i64 + u8 + u16 + u32 + u64 + bool + f32 + f64 + isize + usize + HEAP_BASE + recursive/fib +[program.exports] + recursive/fib +;) diff --git a/tests/compiler/std/array.wast b/tests/compiler/std/array.wast index 14e90d53..dcb229a2 100644 --- a/tests/compiler/std/array.wast +++ b/tests/compiler/std/array.wast @@ -49,36 +49,38 @@ isize usize HEAP_BASE - array/Array + std:array/Array Array - error/Error + std:error/Error Error - error/RangeError + std:error/RangeError RangeError - heap/ALIGN_LOG2 - heap/ALIGN_SIZE - heap/ALIGN_MASK - heap/HEAP_OFFSET - heap/Heap + std:heap/ALIGN_LOG2 + std:heap/ALIGN_SIZE + std:heap/ALIGN_MASK + std:heap/HEAP_OFFSET + std:heap/Heap Heap - heap/Heap.used - heap/Heap.free - heap/Heap.size - heap/Heap.allocate - heap/Heap.dispose - heap/Heap.copy - map/Map + std:heap/Heap.used + std:heap/Heap.free + std:heap/Heap.size + std:heap/Heap.allocate + std:heap/Heap.dispose + std:heap/Heap.copy + std:heap/Heap.fill + std:heap/Heap.compare + std:map/Map Map - set/Set + std:set/Set Set - string/String + std:string/String String [program.exports] - array/Array - error/Error - error/RangeError - heap/Heap - map/Map - set/Set - string/String + std:array/Array + std:error/Error + std:error/RangeError + std:heap/Heap + std:map/Map + std:set/Set + std:string/String ;) diff --git a/tests/compiler/std/heap.optimized-inlined.wast b/tests/compiler/std/heap.optimized-inlined.wast deleted file mode 100644 index 74f402ca..00000000 --- a/tests/compiler/std/heap.optimized-inlined.wast +++ /dev/null @@ -1,119 +0,0 @@ -(module - (type $ii (func (param i32) (result i32))) - (type $iv (func (param i32))) - (type $v (func)) - (global $heap/HEAP_OFFSET (mut i32) (i32.const 0)) - (global $std/heap/ptr (mut i32) (i32.const 0)) - (global $HEAP_BASE i32 (i32.const 4)) - (memory $0 1) - (export "memory" (memory $0)) - (start $start) - (func $heap/Heap.allocate (; 0 ;) (type $ii) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (if - (i32.eqz - (get_local $0) - ) - (return - (i32.const 0) - ) - ) - (set_local $1 - (current_memory) - ) - (if - (i32.gt_u - (i32.add - (get_global $heap/HEAP_OFFSET) - (get_local $0) - ) - (i32.shl - (get_local $1) - (i32.const 16) - ) - ) - (if - (i32.lt_s - (grow_memory - (select - (tee_local $2 - (i32.trunc_s/f64 - (f64.ceil - (f64.div - (f64.convert_u/i32 - (get_local $0) - ) - (f64.const 65536) - ) - ) - ) - ) - (tee_local $1 - (i32.sub - (i32.mul - (get_local $1) - (i32.const 2) - ) - (get_local $1) - ) - ) - (i32.gt_s - (get_local $2) - (get_local $1) - ) - ) - ) - (i32.const 0) - ) - (unreachable) - ) - ) - (set_local $1 - (get_global $heap/HEAP_OFFSET) - ) - (if - (block (result i32) - (set_global $heap/HEAP_OFFSET - (i32.add - (get_global $heap/HEAP_OFFSET) - (get_local $0) - ) - ) - (i32.and - (get_global $heap/HEAP_OFFSET) - (i32.const 7) - ) - ) - (set_global $heap/HEAP_OFFSET - (i32.add - (i32.or - (get_global $heap/HEAP_OFFSET) - (i32.const 7) - ) - (i32.const 1) - ) - ) - ) - (get_local $1) - ) - (func $start (; 1 ;) (type $v) - (local $0 i32) - (set_global $heap/HEAP_OFFSET - (get_global $HEAP_BASE) - ) - (set_global $std/heap/ptr - (call $heap/Heap.allocate - (i32.const 10) - ) - ) - (block - (block $__inlined_func$heap/Heap.dispose - (set_local $0 - (get_global $std/heap/ptr) - ) - (nop) - ) - ) - ) -) diff --git a/tests/compiler/std/heap.optimized.wast b/tests/compiler/std/heap.optimized.wast index 3e61b325..d9352cc8 100644 --- a/tests/compiler/std/heap.optimized.wast +++ b/tests/compiler/std/heap.optimized.wast @@ -1,14 +1,17 @@ (module (type $ii (func (param i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) (type $iv (func (param i32))) (type $v (func)) - (global $heap/HEAP_OFFSET (mut i32) (i32.const 0)) - (global $std/heap/ptr (mut i32) (i32.const 0)) + (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) + (global $std/heap/ptr1 (mut i32) (i32.const 0)) + (global $std/heap/ptr2 (mut i32) (i32.const 0)) + (global $std/heap/i (mut i32) (i32.const 0)) (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) (export "memory" (memory $0)) (start $start) - (func $heap/Heap.allocate (; 0 ;) (type $ii) (param $0 i32) (result i32) + (func $std:heap/Heap.allocate (; 0 ;) (type $ii) (param $0 i32) (result i32) (local $1 i32) (local $2 i32) (if @@ -25,7 +28,7 @@ (if (i32.gt_u (i32.add - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) (get_local $0) ) (i32.shl @@ -70,25 +73,25 @@ ) ) (set_local $1 - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) ) (if (block (result i32) - (set_global $heap/HEAP_OFFSET + (set_global $std:heap/HEAP_OFFSET (i32.add - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) (get_local $0) ) ) (i32.and - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) (i32.const 7) ) ) - (set_global $heap/HEAP_OFFSET + (set_global $std:heap/HEAP_OFFSET (i32.add (i32.or - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) (i32.const 7) ) (i32.const 1) @@ -97,20 +100,2132 @@ ) (get_local $1) ) - (func $heap/Heap.dispose (; 1 ;) (type $iv) (param $0 i32) - (nop) - ) - (func $start (; 2 ;) (type $v) - (set_global $heap/HEAP_OFFSET - (get_global $HEAP_BASE) + (func $std:heap/Heap.fill (; 1 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i64) + (local $5 i32) + (if + (i32.lt_u + (get_local $0) + (get_global $HEAP_BASE) + ) + (unreachable) ) - (set_global $std/heap/ptr - (call $heap/Heap.allocate - (i32.const 10) + (if + (i32.eqz + (get_local $2) + ) + (return + (get_local $0) ) ) - (call $heap/Heap.dispose - (get_global $std/heap/ptr) + (i32.store8 + (tee_local $3 + (get_local $0) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 1) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 2) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 1) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 3) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 6) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 3) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 4) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (i32.store + (tee_local $3 + (i32.add + (get_local $3) + (tee_local $5 + (i32.and + (i32.sub + (i32.const 0) + (get_local $3) + ) + (i32.const 3) + ) + ) + ) + ) + (tee_local $1 + (i32.mul + (get_local $1) + (i32.const 16843009) + ) + ) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (tee_local $2 + (i32.and + (i32.sub + (get_local $2) + (get_local $5) + ) + (i32.const -4) + ) + ) + ) + (i32.const 4) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 12) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 8) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 24) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 20) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 28) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 24) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 20) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 16) + ) + (get_local $1) + ) + (set_local $3 + (i32.add + (get_local $3) + (tee_local $5 + (i32.add + (i32.and + (get_local $3) + (i32.const 4) + ) + (i32.const 24) + ) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (get_local $5) + ) + ) + (set_local $4 + (i64.or + (i64.extend_u/i32 + (get_local $1) + ) + (i64.shl + (i64.extend_u/i32 + (get_local $1) + ) + (i64.const 32) + ) + ) + ) + (loop $continue|0 + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block + (i64.store + (get_local $3) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $4) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 32) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 32) + ) + ) + (br $continue|0) + ) + ) + ) + (get_local $0) + ) + (func $std:heap/Heap.copy (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.lt_u + (get_local $0) + (get_global $HEAP_BASE) + ) + (unreachable) + ) + (set_local $4 + (get_local $0) + ) + (loop $continue|0 + (if + (if (result i32) + (tee_local $3 + (get_local $2) + ) + (i32.rem_u + (get_local $1) + (i32.const 4) + ) + (get_local $3) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + (if + (i32.eqz + (i32.rem_u + (get_local $4) + (i32.const 4) + ) + ) + (block + (loop $continue|1 + (if + (i32.ge_u + (get_local $2) + (i32.const 16) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 12) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|1) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 8) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 4) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (i32.store16 + (get_local $4) + (i32.load16_u + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 2) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (block + (set_local $3 + (get_local $4) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $3 + (get_local $1) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + ) + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block $break|2 + (block $case2|2 + (block $case1|2 + (block $case0|2 + (block $tablify|0 + (br_table $case0|2 $case1|2 $case2|2 $tablify|0 + (i32.sub + (i32.rem_u + (get_local $4) + (i32.const 4) + ) + (i32.const 1) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 3) + ) + ) + (loop $continue|3 + (if + (i32.ge_u + (get_local $2) + (i32.const 17) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 24) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 5) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 9) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 24) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 13) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|3) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 2) + ) + ) + (loop $continue|4 + (if + (i32.ge_u + (get_local $2) + (i32.const 18) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 16) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 6) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 10) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 16) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 14) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|4) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (loop $continue|5 + (if + (i32.ge_u + (get_local $2) + (i32.const 19) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 3) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 8) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 7) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 11) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 8) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 15) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|5) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 16) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (block + (set_local $3 + (get_local $4) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $3 + (get_local $1) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (get_local $0) + ) + (func $std:heap/Heap.compare (; 3 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if + (i32.eq + (get_local $0) + (get_local $1) + ) + (return + (i32.const 0) + ) + ) + (loop $continue|0 + (if + (if (result i32) + (tee_local $3 + (get_local $2) + ) + (i32.eq + (i32.load8_u + (get_local $0) + ) + (i32.load8_u + (get_local $1) + ) + ) + (get_local $3) + ) + (block + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (set_local $0 + (i32.add + (get_local $0) + (i32.const 1) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + (if (result i32) + (get_local $2) + (i32.sub + (i32.load8_u + (get_local $0) + ) + (i32.load8_u + (get_local $1) + ) + ) + (i32.const 0) + ) + ) + (func $std:heap/Heap.dispose (; 4 ;) (type $iv) (param $0 i32) + (nop) + ) + (func $start (; 5 ;) (type $v) + (set_global $std:heap/HEAP_OFFSET + (get_global $HEAP_BASE) + ) + (set_global $std/heap/ptr1 + (call $std:heap/Heap.allocate + (i32.const 42) + ) + ) + (set_global $std/heap/ptr2 + (call $std:heap/Heap.allocate + (i32.const 42) + ) + ) + (if + (i32.eq + (get_global $std/heap/ptr1) + (get_global $std/heap/ptr2) + ) + (unreachable) + ) + (drop + (call $std:heap/Heap.fill + (get_global $std/heap/ptr1) + (i32.const 18) + (i32.const 42) + ) + ) + (set_global $std/heap/i + (i32.const 0) + ) + (loop $continue|0 + (if + (i32.lt_u + (get_global $std/heap/i) + (i32.const 42) + ) + (block + (if + (i32.ne + (i32.load8_u + (i32.add + (get_global $std/heap/ptr1) + (get_global $std/heap/i) + ) + ) + (i32.const 18) + ) + (unreachable) + ) + (set_global $std/heap/i + (i32.add + (get_global $std/heap/i) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + (drop + (call $std:heap/Heap.copy + (get_global $std/heap/ptr2) + (get_global $std/heap/ptr1) + (i32.const 42) + ) + ) + (set_global $std/heap/i + (i32.const 0) + ) + (loop $continue|1 + (if + (i32.lt_u + (get_global $std/heap/i) + (i32.const 42) + ) + (block + (if + (i32.ne + (i32.load8_u + (i32.add + (get_global $std/heap/ptr2) + (get_global $std/heap/i) + ) + ) + (i32.const 18) + ) + (unreachable) + ) + (set_global $std/heap/i + (i32.add + (get_global $std/heap/i) + (i32.const 1) + ) + ) + (br $continue|1) + ) + ) + ) + (if + (call $std:heap/Heap.compare + (get_global $std/heap/ptr1) + (get_global $std/heap/ptr2) + (i32.const 42) + ) + (unreachable) + ) + (call $std:heap/Heap.dispose + (get_global $std/heap/ptr1) + ) + (call $std:heap/Heap.dispose + (get_global $std/heap/ptr2) ) ) ) diff --git a/tests/compiler/std/heap.ts b/tests/compiler/std/heap.ts index 4ecd5e69..8f45bd08 100644 --- a/tests/compiler/std/heap.ts +++ b/tests/compiler/std/heap.ts @@ -1,2 +1,21 @@ -let ptr: usize = Heap.allocate(10); -Heap.dispose(ptr); +const size: usize = 42; +let ptr1: usize = Heap.allocate(size); +let ptr2: usize = Heap.allocate(size); + +assert(ptr1 != ptr2); + +Heap.fill(ptr1, 0x12, size); + +let i: usize; +for (i = 0; i < size; ++i) + assert(load(ptr1 + i) == 0x12); + +Heap.copy(ptr2, ptr1, size); + +for (i = 0; i < size; ++i) + assert(load(ptr2 + i) == 0x12); + +assert(Heap.compare(ptr1, ptr2, size) == 0); + +Heap.dispose(ptr1); +Heap.dispose(ptr2); diff --git a/tests/compiler/std/heap.wast b/tests/compiler/std/heap.wast index 2da6477e..69e8d181 100644 --- a/tests/compiler/std/heap.wast +++ b/tests/compiler/std/heap.wast @@ -1,18 +1,22 @@ (module (type $i (func (result i32))) (type $ii (func (param i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) (type $iv (func (param i32))) (type $v (func)) - (global $heap/HEAP_OFFSET (mut i32) (i32.const 0)) - (global $heap/ALIGN_LOG2 i32 (i32.const 3)) - (global $heap/ALIGN_SIZE i32 (i32.const 8)) - (global $heap/ALIGN_MASK i32 (i32.const 7)) - (global $std/heap/ptr (mut i32) (i32.const 0)) + (global $std/heap/size i32 (i32.const 42)) + (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) + (global $std:heap/ALIGN_LOG2 i32 (i32.const 3)) + (global $std:heap/ALIGN_SIZE i32 (i32.const 8)) + (global $std:heap/ALIGN_MASK i32 (i32.const 7)) + (global $std/heap/ptr1 (mut i32) (i32.const 0)) + (global $std/heap/ptr2 (mut i32) (i32.const 0)) + (global $std/heap/i (mut i32) (i32.const 0)) (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) (export "memory" (memory $0)) (start $start) - (func $heap/Heap.allocate (; 0 ;) (type $ii) (param $0 i32) (result i32) + (func $std:heap/Heap.allocate (; 0 ;) (type $ii) (param $0 i32) (result i32) (local $1 i32) (local $2 i32) (local $3 i32) @@ -33,7 +37,7 @@ (if (i32.gt_u (i32.add - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) (get_local $0) ) (i32.shl @@ -79,26 +83,26 @@ ) (block (set_local $4 - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) ) ) (if (i32.and (block (result i32) - (set_global $heap/HEAP_OFFSET + (set_global $std:heap/HEAP_OFFSET (i32.add - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) (get_local $0) ) ) - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) ) (i32.const 7) ) - (set_global $heap/HEAP_OFFSET + (set_global $std:heap/HEAP_OFFSET (i32.add (i32.or - (get_global $heap/HEAP_OFFSET) + (get_global $std:heap/HEAP_OFFSET) (i32.const 7) ) (i32.const 1) @@ -109,19 +113,2446 @@ (get_local $4) ) ) - (func $heap/Heap.dispose (; 1 ;) (type $iv) (param $0 i32) - ) - (func $start (; 2 ;) (type $v) - (set_global $heap/HEAP_OFFSET - (get_global $HEAP_BASE) + (func $std:heap/Heap.fill (; 1 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i64) + (if + (i32.eqz + (i32.ge_u + (get_local $0) + (get_global $HEAP_BASE) + ) + ) + (unreachable) ) - (set_global $std/heap/ptr - (call $heap/Heap.allocate - (i32.const 10) + (if + (i32.eqz + (get_local $2) + ) + (return + (get_local $0) ) ) - (call $heap/Heap.dispose - (get_global $std/heap/ptr) + (block + (set_local $3 + (get_local $0) + ) + ) + (i32.store8 + (get_local $3) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 1) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 2) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 1) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 3) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 6) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 3) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 4) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (block + (set_local $4 + (i32.and + (i32.sub + (i32.const 0) + (get_local $3) + ) + (i32.const 3) + ) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (get_local $4) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (get_local $4) + ) + ) + (set_local $2 + (i32.and + (get_local $2) + (i32.sub + (i32.const 0) + (i32.const 4) + ) + ) + ) + (block + (set_local $5 + (i32.mul + (i32.div_u + (i32.sub + (i32.const 0) + (i32.const 1) + ) + (i32.const 255) + ) + (get_local $1) + ) + ) + ) + (i32.store + (get_local $3) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 4) + ) + (get_local $5) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (get_local $5) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 12) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 8) + ) + (get_local $5) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 24) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (get_local $5) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $5) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 20) + ) + (get_local $5) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 28) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 24) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 20) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 16) + ) + (get_local $5) + ) + (set_local $4 + (i32.add + (i32.const 24) + (i32.and + (get_local $3) + (i32.const 4) + ) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (get_local $4) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (get_local $4) + ) + ) + (block + (set_local $6 + (i64.or + (i64.extend_u/i32 + (get_local $5) + ) + (i64.shl + (i64.extend_u/i32 + (get_local $5) + ) + (i64.const 32) + ) + ) + ) + ) + (block $break|0 + (loop $continue|0 + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block + (block + (i64.store + (get_local $3) + (get_local $6) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $6) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $6) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $6) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 32) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 32) + ) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + (func $std:heap/Heap.copy (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.eqz + (i32.ge_u + (get_local $0) + (get_global $HEAP_BASE) + ) + ) + (unreachable) + ) + (block + (set_local $3 + (get_local $0) + ) + ) + (nop) + (block $break|0 + (loop $continue|0 + (if + (if (result i32) + (tee_local $6 + (get_local $2) + ) + (i32.rem_u + (get_local $1) + (i32.const 4) + ) + (get_local $6) + ) + (block + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (drop + (block (result i32) + (set_local $6 + (get_local $2) + ) + (set_local $2 + (i32.sub + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (if + (i32.eq + (i32.rem_u + (get_local $3) + (i32.const 4) + ) + (i32.const 0) + ) + (block + (block $break|1 + (loop $continue|1 + (if + (i32.ge_u + (get_local $2) + (i32.const 16) + ) + (block + (block + (i32.store + (get_local $3) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 12) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + ) + (br $continue|1) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (i32.store + (get_local $3) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 8) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (i32.store + (get_local $3) + (i32.load + (get_local $1) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 4) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (i32.store16 + (get_local $3) + (i32.load16_u + (get_local $1) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 2) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + ) + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block $break|2 + (block $case2|2 + (block $case1|2 + (block $case0|2 + (set_local $6 + (i32.rem_u + (get_local $3) + (i32.const 4) + ) + ) + (br_if $case0|2 + (i32.eq + (get_local $6) + (i32.const 1) + ) + ) + (br_if $case1|2 + (i32.eq + (get_local $6) + (i32.const 2) + ) + ) + (br_if $case2|2 + (i32.eq + (get_local $6) + (i32.const 3) + ) + ) + (br $break|2) + ) + (set_local $4 + (i32.load + (get_local $1) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 3) + ) + ) + (block $break|3 + (loop $continue|3 + (if + (i32.ge_u + (get_local $2) + (i32.const 17) + ) + (block + (block + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + ) + (i32.store + (get_local $3) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 24) + ) + (i32.shl + (get_local $5) + (i32.const 8) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 5) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (get_local $4) + (i32.const 8) + ) + ) + ) + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 9) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 24) + ) + (i32.shl + (get_local $5) + (i32.const 8) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 13) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (get_local $4) + (i32.const 8) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + ) + (br $continue|3) + ) + ) + ) + ) + (br $break|2) + ) + (set_local $4 + (i32.load + (get_local $1) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 2) + ) + ) + (block $break|4 + (loop $continue|4 + (if + (i32.ge_u + (get_local $2) + (i32.const 18) + ) + (block + (block + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + (i32.store + (get_local $3) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 16) + ) + (i32.shl + (get_local $5) + (i32.const 16) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 6) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (get_local $4) + (i32.const 16) + ) + ) + ) + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 10) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 16) + ) + (i32.shl + (get_local $5) + (i32.const 16) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 14) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (get_local $4) + (i32.const 16) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + ) + (br $continue|4) + ) + ) + ) + ) + (br $break|2) + ) + (set_local $4 + (i32.load + (get_local $1) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (block $break|5 + (loop $continue|5 + (if + (i32.ge_u + (get_local $2) + (i32.const 19) + ) + (block + (block + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 3) + ) + ) + ) + (i32.store + (get_local $3) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 8) + ) + (i32.shl + (get_local $5) + (i32.const 24) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 7) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (get_local $4) + (i32.const 24) + ) + ) + ) + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 11) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 8) + ) + (i32.shl + (get_local $5) + (i32.const 24) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 15) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (get_local $4) + (i32.const 24) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + ) + (br $continue|5) + ) + ) + ) + ) + (br $break|2) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 16) + ) + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + (func $std:heap/Heap.compare (; 3 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if + (i32.eq + (get_local $0) + (get_local $1) + ) + (return + (i32.const 0) + ) + ) + (block $break|0 + (loop $continue|0 + (if + (if (result i32) + (tee_local $3 + (get_local $2) + ) + (i32.eq + (i32.load8_u + (get_local $0) + ) + (i32.load8_u + (get_local $1) + ) + ) + (get_local $3) + ) + (block + (block + (drop + (block (result i32) + (set_local $3 + (get_local $2) + ) + (set_local $2 + (i32.sub + (get_local $3) + (i32.const 1) + ) + ) + (get_local $3) + ) + ) + (drop + (block (result i32) + (set_local $3 + (get_local $0) + ) + (set_local $0 + (i32.add + (get_local $3) + (i32.const 1) + ) + ) + (get_local $3) + ) + ) + (drop + (block (result i32) + (set_local $3 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $3) + (i32.const 1) + ) + ) + (get_local $3) + ) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (return + (if (result i32) + (get_local $2) + (i32.sub + (i32.load8_u + (get_local $0) + ) + (i32.load8_u + (get_local $1) + ) + ) + (i32.const 0) + ) + ) + ) + (func $std:heap/Heap.dispose (; 4 ;) (type $iv) (param $0 i32) + ) + (func $start (; 5 ;) (type $v) + (set_global $std:heap/HEAP_OFFSET + (get_global $HEAP_BASE) + ) + (set_global $std/heap/ptr1 + (call $std:heap/Heap.allocate + (i32.const 42) + ) + ) + (set_global $std/heap/ptr2 + (call $std:heap/Heap.allocate + (i32.const 42) + ) + ) + (if + (i32.eqz + (i32.ne + (get_global $std/heap/ptr1) + (get_global $std/heap/ptr2) + ) + ) + (unreachable) + ) + (drop + (call $std:heap/Heap.fill + (get_global $std/heap/ptr1) + (i32.const 18) + (i32.const 42) + ) + ) + (block $break|0 + (set_global $std/heap/i + (i32.const 0) + ) + (loop $continue|0 + (if + (i32.lt_u + (get_global $std/heap/i) + (i32.const 42) + ) + (block + (if + (i32.eqz + (i32.eq + (i32.load8_u + (i32.add + (get_global $std/heap/ptr1) + (get_global $std/heap/i) + ) + ) + (i32.const 18) + ) + ) + (unreachable) + ) + (set_global $std/heap/i + (i32.add + (get_global $std/heap/i) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (drop + (call $std:heap/Heap.copy + (get_global $std/heap/ptr2) + (get_global $std/heap/ptr1) + (i32.const 42) + ) + ) + (block $break|1 + (set_global $std/heap/i + (i32.const 0) + ) + (loop $continue|1 + (if + (i32.lt_u + (get_global $std/heap/i) + (i32.const 42) + ) + (block + (if + (i32.eqz + (i32.eq + (i32.load8_u + (i32.add + (get_global $std/heap/ptr2) + (get_global $std/heap/i) + ) + ) + (i32.const 18) + ) + ) + (unreachable) + ) + (set_global $std/heap/i + (i32.add + (get_global $std/heap/i) + (i32.const 1) + ) + ) + (br $continue|1) + ) + ) + ) + ) + (if + (i32.eqz + (i32.eq + (call $std:heap/Heap.compare + (get_global $std/heap/ptr1) + (get_global $std/heap/ptr2) + (i32.const 42) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (call $std:heap/Heap.dispose + (get_global $std/heap/ptr1) + ) + (call $std:heap/Heap.dispose + (get_global $std/heap/ptr2) ) ) ) @@ -171,37 +2602,42 @@ isize usize HEAP_BASE - array/Array + std:array/Array Array - error/Error + std:error/Error Error - error/RangeError + std:error/RangeError RangeError - heap/ALIGN_LOG2 - heap/ALIGN_SIZE - heap/ALIGN_MASK - heap/HEAP_OFFSET - heap/Heap + std:heap/ALIGN_LOG2 + std:heap/ALIGN_SIZE + std:heap/ALIGN_MASK + std:heap/HEAP_OFFSET + std:heap/Heap Heap - heap/Heap.used - heap/Heap.free - heap/Heap.size - heap/Heap.allocate - heap/Heap.dispose - heap/Heap.copy - map/Map + std:heap/Heap.used + std:heap/Heap.free + std:heap/Heap.size + std:heap/Heap.allocate + std:heap/Heap.dispose + std:heap/Heap.copy + std:heap/Heap.fill + std:heap/Heap.compare + std:map/Map Map - set/Set + std:set/Set Set - string/String + std:string/String String - std/heap/ptr + std/heap/size + std/heap/ptr1 + std/heap/ptr2 + std/heap/i [program.exports] - array/Array - error/Error - error/RangeError - heap/Heap - map/Map - set/Set - string/String + std:array/Array + std:error/Error + std:error/RangeError + std:heap/Heap + std:map/Map + std:set/Set + std:string/String ;) diff --git a/tests/parser/string-binding.ts b/tests/parser/string-binding.ts new file mode 100644 index 00000000..1a90c58e --- /dev/null +++ b/tests/parser/string-binding.ts @@ -0,0 +1,52 @@ +// a host-bindings syntax experiment + +@binding(BindingCall.NEW, [ BindingType.STRING ], BindingType.OBJECT_HANDLE) +export class ExternalString { + + @binding(BindingCall.FUNCTION, [ BindingType.U32, BindingType.U32 ], BindingType.OBJECT_HANDLE) + static fromCharCode(char: u16, schar: u16 = -1): String { return unreachable(); } + + @binding(BindingCall.FUNCTION, [ BindingType.U32 ], BindingType.OBJECT_HANDLE) + static fromCodePoint(codepoint: u32): String { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.U32 ], BindingType.OBJECT_HANDLE) + charAt(index: u32): String { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.U32 ], BindingType.PASS_THRU) + charCodeAt(index: u32): u16 { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.U32 ], BindingType.PASS_THRU) + codePointAt(index: u32): u32 { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.OBJECT_HANDLE ], BindingType.OBJECT_HANDLE) + @operator("+") + concat(other: String): String { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.OBJECT_HANDLE ], BindingType.PASS_THRU) + endsWith(other: String): bool { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.OBJECT_HANDLE ], BindingType.PASS_THRU) + indexOf(other: String): i32 { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.OBJECT_HANDLE ], BindingType.PASS_THRU) + startsWith(other: String): bool { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.U32, BindingType.U32 ], BindingType.OBJECT_HANDLE) + substr(start: i32, length: i32): String { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.U32, BindingType.U32 ], BindingType.OBJECT_HANDLE) + substring(start: i32, end: i32): String { return unreachable(); } + + @binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE) + trim(): String { return unreachable(); } + + @binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE) + trimLeft(): String { return unreachable(); } + + @binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE) + trimRight(): String { return unreachable(); } + + @binding(BindingCall.THIS, [ BindingType.OBJECT_HANDLE ], BindingType.PASS_THRU) + @operator("==") + equals(other: String): bool { return unreachable(); } +} diff --git a/tests/parser/string-binding.ts.fixture.ts b/tests/parser/string-binding.ts.fixture.ts new file mode 100644 index 00000000..57da0d99 --- /dev/null +++ b/tests/parser/string-binding.ts.fixture.ts @@ -0,0 +1,65 @@ +@binding(BindingCall.NEW, [BindingType.STRING], BindingType.OBJECT_HANDLE) +export class ExternalString { +@binding(BindingCall.FUNCTION, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE) +static fromCharCode(char: u16, schar: u16 = -1): String { +return unreachable(); +} +@binding(BindingCall.FUNCTION, [BindingType.U32], BindingType.OBJECT_HANDLE) +static fromCodePoint(codepoint: u32): String { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.U32], BindingType.OBJECT_HANDLE) +charAt(index: u32): String { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU) +charCodeAt(index: u32): u16 { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.U32], BindingType.PASS_THRU) +codePointAt(index: u32): u32 { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.OBJECT_HANDLE) +@operator("+") +concat(other: String): String { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU) +endsWith(other: String): bool { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU) +indexOf(other: String): i32 { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU) +startsWith(other: String): bool { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE) +substr(start: i32, length: i32): String { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE) +substring(start: i32, end: i32): String { +return unreachable(); +} +@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE) +trim(): String { +return unreachable(); +} +@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE) +trimLeft(): String { +return unreachable(); +} +@binding(BindingCall.THIS, [], BindingType.OBJECT_HANDLE) +trimRight(): String { +return unreachable(); +} +@binding(BindingCall.THIS, [BindingType.OBJECT_HANDLE], BindingType.PASS_THRU) +@operator("==") +equals(other: String): bool { +return unreachable(); +} +}