From 70d2a0a4259da0a848b38a4a10bbea8f40b4adef Mon Sep 17 00:00:00 2001 From: Max Graey Date: Sun, 25 Mar 2018 14:14:53 +0300 Subject: [PATCH] Add more operator overloads + tests (#55) * operator '-' * operator '*' * operator '/' * operator '%' * operator '&' * operator '|' * operator '^' --- .travis.yml | 2 + src/compiler.ts | 82 +- src/program.ts | 42 + .../std/operator-overloading.optimized.wat | 848 ++++++++++++++++ tests/compiler/std/operator-overloading.ts | 111 +++ .../std/operator-overloading.untouched.wat | 910 ++++++++++++++++++ 6 files changed, 1988 insertions(+), 7 deletions(-) create mode 100644 tests/compiler/std/operator-overloading.optimized.wat create mode 100644 tests/compiler/std/operator-overloading.ts create mode 100644 tests/compiler/std/operator-overloading.untouched.wat diff --git a/.travis.yml b/.travis.yml index 6b5f9f69..e171700d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ jobs: script: npm run clean && node bin/asc -v && npm test env: Tests the sources on latest node.js LTS - node_js: node + script: npm run clean && node bin/asc -v && npm test env: Tests the sources on latest stable node.js - stage: build @@ -29,4 +30,5 @@ jobs: script: npm run build && node bin/asc -v && npm test env: Builds and tests the bundle on latest node.js LTS - node_js: node + script: npm run build && node bin/asc -v && npm test env: Builds and tests the bundle on latest stable node.js diff --git a/src/compiler.ts b/src/compiler.ts index 2b5fc98c..187d3062 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -2939,7 +2939,17 @@ export class Compiler extends DiagnosticEmitter { expr = module.createBinary(BinaryOp.SubI32, leftExpr, rightExpr); break; } - case TypeKind.USIZE: // TODO: check operator overload + case TypeKind.USIZE: { // check operator overload + if (this.currentType.is(TypeFlags.REFERENCE)) { + let classInstance = assert(this.currentType.classReference); + let operatorName = classInstance.prototype.fnSubtract; + if (operatorName != null) { + expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr); + break; + } + } + // fall-through + } case TypeKind.ISIZE: { expr = module.createBinary( this.options.isWasm64 @@ -3020,7 +3030,17 @@ export class Compiler extends DiagnosticEmitter { expr = module.createBinary(BinaryOp.MulI32, leftExpr, rightExpr); break; } - case TypeKind.USIZE: // TODO: check operator overload + case TypeKind.USIZE: { // check operator overload + if (this.currentType.is(TypeFlags.REFERENCE)) { + let classInstance = assert(this.currentType.classReference); + let operatorName = classInstance.prototype.fnMultiply; + if (operatorName != null) { + expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr); + break; + } + } + // fall-through + } case TypeKind.ISIZE: { expr = module.createBinary( this.options.isWasm64 @@ -3118,7 +3138,16 @@ export class Compiler extends DiagnosticEmitter { expr = module.createBinary(BinaryOp.DivU32, leftExpr, rightExpr); break; } - case TypeKind.USIZE: { // TODO: check operator overload + case TypeKind.USIZE: { // check operator overload + if (this.currentType.is(TypeFlags.REFERENCE)) { + let classInstance = assert(this.currentType.classReference); + let operatorName = classInstance.prototype.fnDivide; + if (operatorName != null) { + expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr); + break; + } + } + // fall-through expr = module.createBinary( this.options.isWasm64 ? BinaryOp.DivU64 @@ -3214,7 +3243,16 @@ export class Compiler extends DiagnosticEmitter { expr = module.createBinary(BinaryOp.RemU32, leftExpr, rightExpr); break; } - case TypeKind.USIZE: { // TODO: check operator overload + case TypeKind.USIZE: { // check operator overload + if (this.currentType.is(TypeFlags.REFERENCE)) { + let classInstance = assert(this.currentType.classReference); + let operatorName = classInstance.prototype.fnFractional; + if (operatorName != null) { + expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr); + break; + } + } + // fall-through expr = module.createBinary( this.options.isWasm64 ? BinaryOp.RemU64 @@ -3509,7 +3547,17 @@ export class Compiler extends DiagnosticEmitter { expr = module.createBinary(BinaryOp.AndI64, leftExpr, rightExpr); break; } - case TypeKind.USIZE: // TODO: check operator overload + case TypeKind.USIZE: { // check operator overload + if (this.currentType.is(TypeFlags.REFERENCE)) { + let classInstance = assert(this.currentType.classReference); + let operatorName = classInstance.prototype.fnBitwiseAnd; + if (operatorName != null) { + expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr); + break; + } + } + // fall-through + } case TypeKind.ISIZE: { expr = module.createBinary( this.options.isWasm64 @@ -3581,7 +3629,17 @@ export class Compiler extends DiagnosticEmitter { expr = module.createBinary(BinaryOp.OrI64, leftExpr, rightExpr); break; } - case TypeKind.USIZE: // TODO: check operator overload + case TypeKind.USIZE: { // check operator overload + if (this.currentType.is(TypeFlags.REFERENCE)) { + let classInstance = assert(this.currentType.classReference); + let operatorName = classInstance.prototype.fnBitwiseOr; + if (operatorName != null) { + expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr); + break; + } + } + // fall-through + } case TypeKind.ISIZE: { expr = module.createBinary( this.options.isWasm64 @@ -3653,7 +3711,17 @@ export class Compiler extends DiagnosticEmitter { expr = module.createBinary(BinaryOp.XorI64, leftExpr, rightExpr); break; } - case TypeKind.USIZE: // TODO: check operator overload + case TypeKind.USIZE: { // check operator overload + if (this.currentType.is(TypeFlags.REFERENCE)) { + let classInstance = assert(this.currentType.classReference); + let operatorName = classInstance.prototype.fnBitwiseXor; + if (operatorName != null) { + expr = this.compileOperatorOverload(classInstance, operatorName, leftExpr, rightExpr); + break; + } + } + // fall-through + } case TypeKind.ISIZE: { expr = module.createBinary( this.options.isWasm64 diff --git a/src/program.ts b/src/program.ts index f0365ee8..d191e996 100644 --- a/src/program.ts +++ b/src/program.ts @@ -675,6 +675,34 @@ export class Program extends DiagnosticEmitter { classPrototype.fnConcat = prototype.simpleName; break; } + case "-": { + classPrototype.fnSubtract = prototype.simpleName; + break; + } + case "*": { + classPrototype.fnMultiply = prototype.simpleName; + break; + } + case "/": { + classPrototype.fnDivide = prototype.simpleName; + break; + } + case "%": { + classPrototype.fnFractional = prototype.simpleName; + break; + } + case "&": { + classPrototype.fnBitwiseAnd = prototype.simpleName; + break; + } + case "|": { + classPrototype.fnBitwiseOr = prototype.simpleName; + break; + } + case "^": { + classPrototype.fnBitwiseXor = prototype.simpleName; + break; + } case "==": { classPrototype.fnEquals = prototype.simpleName; break; @@ -2833,6 +2861,20 @@ export class ClassPrototype extends Element { fnIndexedSet: string | null = null; /** Overloaded concatenation method, if any. */ fnConcat: string | null = null; + /** Overloaded subtraction method, if any. */ + fnSubtract: string | null = null; + /** Overloaded multiply method, if any. */ + fnMultiply: string | null = null; + /** Overloaded divide method, if any. */ + fnDivide: string | null = null; + /** Overloaded fractional method, if any. */ + fnFractional: string | null = null; + /** Overloaded bitwise and method, if any. */ + fnBitwiseAnd: string | null = null; + /** Overloaded bitwise or method, if any. */ + fnBitwiseOr: string | null = null; + /** Overloaded bitwise xor method, if any. */ + fnBitwiseXor: string | null = null; /** Overloaded equality comparison method, if any. */ fnEquals: string | null = null; diff --git a/tests/compiler/std/operator-overloading.optimized.wat b/tests/compiler/std/operator-overloading.optimized.wat new file mode 100644 index 00000000..f5bec290 --- /dev/null +++ b/tests/compiler/std/operator-overloading.optimized.wat @@ -0,0 +1,848 @@ +(module + (type $iiii (func (param i32 i32 i32) (result i32))) + (type $ii (func (param i32) (result i32))) + (type $iii (func (param i32 i32) (result i32))) + (type $iiiiv (func (param i32 i32 i32 i32))) + (type $v (func)) + (import "env" "abort" (func $abort (param i32 i32 i32 i32))) + (global "$(lib)/allocator/arena/startOffset" (mut i32) (i32.const 0)) + (global "$(lib)/allocator/arena/offset" (mut i32) (i32.const 0)) + (global $std/operator-overloading/a1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/a2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/a (mut i32) (i32.const 0)) + (global $std/operator-overloading/s1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/s2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/s (mut i32) (i32.const 0)) + (global $std/operator-overloading/m1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/m2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/m (mut i32) (i32.const 0)) + (global $std/operator-overloading/d1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/d2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/d (mut i32) (i32.const 0)) + (global $std/operator-overloading/f1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/f2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/f (mut i32) (i32.const 0)) + (global $std/operator-overloading/n1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/n2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/n (mut i32) (i32.const 0)) + (global $std/operator-overloading/o1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/o2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/o (mut i32) (i32.const 0)) + (global $std/operator-overloading/x1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/x2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/x (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq3 (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq4 (mut i32) (i32.const 0)) + (global $std/operator-overloading/eqf (mut i32) (i32.const 0)) + (global $HEAP_BASE i32 (i32.const 64)) + (memory $0 1) + (data (i32.const 4) "\1b\00\00\00s\00t\00d\00/\00o\00p\00e\00r\00a\00t\00o\00r\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s") + (export "memory" (memory $0)) + (start $start) + (func "$(lib)/allocator/arena/allocate_memory" (; 1 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (if + (i32.eqz + (get_local $0) + ) + (return + (i32.const 0) + ) + ) + (if + (i32.gt_u + (tee_local $2 + (i32.and + (i32.add + (i32.add + (tee_local $1 + (get_global "$(lib)/allocator/arena/offset") + ) + (get_local $0) + ) + (i32.const 7) + ) + (i32.const -8) + ) + ) + (i32.shl + (tee_local $0 + (current_memory) + ) + (i32.const 16) + ) + ) + (if + (i32.lt_s + (grow_memory + (select + (get_local $0) + (tee_local $4 + (tee_local $3 + (i32.shr_u + (i32.and + (i32.add + (i32.sub + (get_local $2) + (get_local $1) + ) + (i32.const 65535) + ) + (i32.const -65536) + ) + (i32.const 16) + ) + ) + ) + (i32.gt_s + (get_local $0) + (get_local $4) + ) + ) + ) + (i32.const 0) + ) + (if + (i32.lt_s + (grow_memory + (get_local $3) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + ) + (set_global "$(lib)/allocator/arena/offset" + (get_local $2) + ) + (get_local $1) + ) + (func $std/operator-overloading/Tester#constructor (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if (result i32) + (get_local $0) + (get_local $0) + (block (result i32) + (i32.store + (tee_local $3 + (call "$(lib)/allocator/arena/allocate_memory" + (i32.const 8) + ) + ) + (get_local $1) + ) + (i32.store offset=4 + (get_local $3) + (get_local $2) + ) + (get_local $3) + ) + ) + ) + (func $std/operator-overloading/Tester.add (; 3 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.add + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.add + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.sub (; 4 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.sub + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.sub + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.mul (; 5 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.mul + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.mul + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.div (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.div_s + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.div_s + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.mod (; 7 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.rem_s + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.rem_s + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.and (; 8 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.and + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.and + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.or (; 9 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.or + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.or + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.xor (; 10 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.xor + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.xor + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.equal (; 11 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (i32.and + (if (result i32) + (tee_local $2 + (i32.eq + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + ) + (i32.eq + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + (get_local $2) + ) + (i32.const 1) + ) + ) + (func $start (; 12 ;) (type $v) + (local $0 i32) + (set_global "$(lib)/allocator/arena/startOffset" + (i32.and + (i32.add + (get_global $HEAP_BASE) + (i32.const 7) + ) + (i32.const -8) + ) + ) + (set_global "$(lib)/allocator/arena/offset" + (get_global "$(lib)/allocator/arena/startOffset") + ) + (set_global $std/operator-overloading/a1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) + ) + (set_global $std/operator-overloading/a2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 2) + (i32.const 3) + ) + ) + (set_global $std/operator-overloading/a + (call $std/operator-overloading/Tester.add + (get_global $std/operator-overloading/a1) + (get_global $std/operator-overloading/a2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/a) + ) + (i32.const 3) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/a) + ) + (i32.const 5) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 57) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/s1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 2) + (i32.const 3) + ) + ) + (set_global $std/operator-overloading/s2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 2) + (i32.const -3) + ) + ) + (set_global $std/operator-overloading/s + (call $std/operator-overloading/Tester.sub + (get_global $std/operator-overloading/s1) + (get_global $std/operator-overloading/s2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eqz + (i32.load + (get_global $std/operator-overloading/s) + ) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/s) + ) + (i32.const 6) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 63) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/m1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 2) + (i32.const 5) + ) + ) + (set_global $std/operator-overloading/m2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 3) + (i32.const 2) + ) + ) + (set_global $std/operator-overloading/m + (call $std/operator-overloading/Tester.mul + (get_global $std/operator-overloading/m1) + (get_global $std/operator-overloading/m2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/m) + ) + (i32.const 6) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/m) + ) + (i32.const 10) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 69) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/d1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 6) + (i32.const 50) + ) + ) + (set_global $std/operator-overloading/d2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 3) + (i32.const 10) + ) + ) + (set_global $std/operator-overloading/d + (call $std/operator-overloading/Tester.div + (get_global $std/operator-overloading/d1) + (get_global $std/operator-overloading/d2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/d) + ) + (i32.const 2) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/d) + ) + (i32.const 5) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 75) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/f1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 10) + (i32.const 10) + ) + ) + (set_global $std/operator-overloading/f2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 6) + (i32.const 10) + ) + ) + (set_global $std/operator-overloading/f + (call $std/operator-overloading/Tester.mod + (get_global $std/operator-overloading/f1) + (get_global $std/operator-overloading/f2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/f) + ) + (i32.const 4) + ) + ) + (i32.eqz + (i32.load offset=4 + (get_global $std/operator-overloading/f) + ) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 81) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/n1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 255) + (i32.const 15) + ) + ) + (set_global $std/operator-overloading/n2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 15) + (i32.const 255) + ) + ) + (set_global $std/operator-overloading/n + (call $std/operator-overloading/Tester.and + (get_global $std/operator-overloading/n1) + (get_global $std/operator-overloading/n2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/n) + ) + (i32.const 15) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/n) + ) + (i32.const 15) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 87) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/o1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 3855) + (i32.const 255) + ) + ) + (set_global $std/operator-overloading/o2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 61680) + (i32.const 0) + ) + ) + (set_global $std/operator-overloading/o + (call $std/operator-overloading/Tester.or + (get_global $std/operator-overloading/o1) + (get_global $std/operator-overloading/o2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/o) + ) + (i32.const 65535) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/o) + ) + (i32.const 255) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 93) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/x1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 255) + (i32.const 255) + ) + ) + (set_global $std/operator-overloading/x2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 65280) + (i32.const 0) + ) + ) + (set_global $std/operator-overloading/x + (call $std/operator-overloading/Tester.xor + (get_global $std/operator-overloading/x1) + (get_global $std/operator-overloading/x2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/x) + ) + (i32.const 65535) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/x) + ) + (i32.const 255) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 99) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/eq1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 1) + (i32.const -2) + ) + ) + (set_global $std/operator-overloading/eq2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 1) + (i32.const -2) + ) + ) + (set_global $std/operator-overloading/eq + (call $std/operator-overloading/Tester.equal + (get_global $std/operator-overloading/eq1) + (get_global $std/operator-overloading/eq2) + ) + ) + (if + (i32.ne + (get_global $std/operator-overloading/eq) + (i32.const 1) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 105) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/eq3 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 1) + (i32.const 0) + ) + ) + (set_global $std/operator-overloading/eq4 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 0) + (i32.const 1) + ) + ) + (set_global $std/operator-overloading/eqf + (call $std/operator-overloading/Tester.equal + (get_global $std/operator-overloading/eq3) + (get_global $std/operator-overloading/eq4) + ) + ) + (if + (get_global $std/operator-overloading/eqf) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 111) + (i32.const 0) + ) + (unreachable) + ) + ) + ) +) diff --git a/tests/compiler/std/operator-overloading.ts b/tests/compiler/std/operator-overloading.ts new file mode 100644 index 00000000..c74c4cbe --- /dev/null +++ b/tests/compiler/std/operator-overloading.ts @@ -0,0 +1,111 @@ +import "allocator/arena"; + +class Tester { + constructor(public x: i32, public y: i32) { + } + + @operator('+') + static add(a: Tester, b: Tester): Tester { + return new Tester(a.x + b.x, a.y + b.y); + } + + @operator('-') + static sub(a: Tester, b: Tester): Tester { + return new Tester(a.x - b.x, a.y - b.y); + } + + @operator('*') + static mul(a: Tester, b: Tester): Tester { + return new Tester(a.x * b.x, a.y * b.y); + } + + @operator('/') + static div(a: Tester, b: Tester): Tester { + return new Tester(a.x / b.x, a.y / b.y); + } + + @operator('%') + static mod(a: Tester, b: Tester): Tester { + return new Tester(a.x % b.x, a.y % b.y); + } + + @operator('|') + static or(a: Tester, b: Tester): Tester { + return new Tester(a.x | b.x, a.y | b.y); + } + + @operator('&') + static and(a: Tester, b: Tester): Tester { + return new Tester(a.x & b.x, a.y & b.y); + } + + @operator('^') + static xor(a: Tester, b: Tester): Tester { + return new Tester(a.x ^ b.x, a.y ^ b.y); + } + + @operator('==') + static equal(a: Tester, b: Tester): bool { + return a.x == b.x && a.y == b.y; + } +} + +// check additional +var a1 = new Tester(1, 2); +var a2 = new Tester(2, 3); +var a = a1 + a2; +assert(a.x == 3 && a.y == 5); + +// check subtraction +var s1 = new Tester(2, 3); +var s2 = new Tester(2,-3); +var s = s1 - s2; +assert(s.x == 0 && s.y == 6); + +// check multiplication +var m1 = new Tester(2, 5); +var m2 = new Tester(3, 2); +var m = m1 * m2; +assert(m.x == 6 && m.y == 10); + +// check division +var d1 = new Tester(6, 50); +var d2 = new Tester(3, 10); +var d = d1 / d2; +assert(d.x == 2 && d.y == 5); + +// check fractional +var f1 = new Tester(10, 10); +var f2 = new Tester(6, 10); +var f = f1 % f2; +assert(f.x == 4 && f.y == 0); + +// check bitwise and +var n1 = new Tester(0xFF, 0x0F); +var n2 = new Tester(0x0F, 0xFF); +var n = n1 & n2; +assert(n.x == 0xF && n.y == 0xF); + +// check bitwise or +var o1 = new Tester(0x0F0F, 0xFF); +var o2 = new Tester(0xF0F0, 0x00); +var o = o1 | o2; +assert(o.x == 0xFFFF && o.y == 0xFF); + +// check bitwise xor +var x1 = new Tester(0x00FF, 0xFF); +var x2 = new Tester(0xFF00, 0x00); +var x = x1 ^ x2; +assert(x.x == 0xFFFF && x.y == 0xFF); + +// check truthfully equal +var eq1 = new Tester(1, -2); +var eq2 = new Tester(1, -2); +var eq = eq1 == eq2; +assert(eq == true); + +// check falsely equal +var eq3 = new Tester(1, 0); +var eq4 = new Tester(0, 1); +var eqf = eq3 == eq4; +assert(eqf == false); diff --git a/tests/compiler/std/operator-overloading.untouched.wat b/tests/compiler/std/operator-overloading.untouched.wat new file mode 100644 index 00000000..6c83a27c --- /dev/null +++ b/tests/compiler/std/operator-overloading.untouched.wat @@ -0,0 +1,910 @@ +(module + (type $i (func (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) + (type $ii (func (param i32) (result i32))) + (type $iii (func (param i32 i32) (result i32))) + (type $iiiiv (func (param i32 i32 i32 i32))) + (type $v (func)) + (import "env" "abort" (func $abort (param i32 i32 i32 i32))) + (global "$(lib)/allocator/common/alignment/BITS" i32 (i32.const 3)) + (global "$(lib)/allocator/common/alignment/SIZE" i32 (i32.const 8)) + (global "$(lib)/allocator/common/alignment/MASK" i32 (i32.const 7)) + (global "$(lib)/allocator/arena/startOffset" (mut i32) (i32.const 0)) + (global "$(lib)/allocator/arena/offset" (mut i32) (i32.const 0)) + (global $std/operator-overloading/a1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/a2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/a (mut i32) (i32.const 0)) + (global $std/operator-overloading/s1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/s2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/s (mut i32) (i32.const 0)) + (global $std/operator-overloading/m1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/m2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/m (mut i32) (i32.const 0)) + (global $std/operator-overloading/d1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/d2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/d (mut i32) (i32.const 0)) + (global $std/operator-overloading/f1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/f2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/f (mut i32) (i32.const 0)) + (global $std/operator-overloading/n1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/n2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/n (mut i32) (i32.const 0)) + (global $std/operator-overloading/o1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/o2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/o (mut i32) (i32.const 0)) + (global $std/operator-overloading/x1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/x2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/x (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq1 (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq2 (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq3 (mut i32) (i32.const 0)) + (global $std/operator-overloading/eq4 (mut i32) (i32.const 0)) + (global $std/operator-overloading/eqf (mut i32) (i32.const 0)) + (global $HEAP_BASE i32 (i32.const 64)) + (memory $0 1) + (data (i32.const 4) "\1b\00\00\00s\00t\00d\00/\00o\00p\00e\00r\00a\00t\00o\00r\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s\00") + (export "memory" (memory $0)) + (start $start) + (func "$(lib)/allocator/arena/allocate_memory" (; 1 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.eqz + (get_local $0) + ) + (return + (i32.const 0) + ) + ) + (set_local $1 + (get_global "$(lib)/allocator/arena/offset") + ) + (set_local $2 + (i32.and + (i32.add + (i32.add + (get_local $1) + (get_local $0) + ) + (i32.const 7) + ) + (i32.xor + (i32.const 7) + (i32.const -1) + ) + ) + ) + (set_local $3 + (current_memory) + ) + (if + (i32.gt_u + (get_local $2) + (i32.shl + (get_local $3) + (i32.const 16) + ) + ) + (block + (set_local $4 + (i32.shr_u + (i32.and + (i32.add + (i32.sub + (get_local $2) + (get_local $1) + ) + (i32.const 65535) + ) + (i32.xor + (i32.const 65535) + (i32.const -1) + ) + ) + (i32.const 16) + ) + ) + (set_local $5 + (select + (tee_local $5 + (get_local $3) + ) + (tee_local $6 + (get_local $4) + ) + (i32.gt_s + (get_local $5) + (get_local $6) + ) + ) + ) + (if + (i32.lt_s + (grow_memory + (get_local $5) + ) + (i32.const 0) + ) + (if + (i32.lt_s + (grow_memory + (get_local $4) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + ) + ) + (set_global "$(lib)/allocator/arena/offset" + (get_local $2) + ) + (return + (get_local $1) + ) + ) + (func $std/operator-overloading/Tester#constructor (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (block + ) + (tee_local $0 + (if (result i32) + (get_local $0) + (get_local $0) + (tee_local $0 + (block (result i32) + (set_local $3 + (call "$(lib)/allocator/arena/allocate_memory" + (i32.const 8) + ) + ) + (i32.store + (get_local $3) + (get_local $1) + ) + (i32.store offset=4 + (get_local $3) + (get_local $2) + ) + (get_local $3) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.add (; 3 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.add + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.add + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.sub (; 4 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.sub + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.sub + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.mul (; 5 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.mul + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.mul + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.div (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.div_s + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.div_s + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.mod (; 7 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.rem_s + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.rem_s + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.and (; 8 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.and + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.and + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.or (; 9 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.or + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.or + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.xor (; 10 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.xor + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + (i32.xor + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + ) + ) + ) + (func $std/operator-overloading/Tester.equal (; 11 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (return + (i32.and + (if (result i32) + (tee_local $2 + (i32.eq + (i32.load + (get_local $0) + ) + (i32.load + (get_local $1) + ) + ) + ) + (i32.eq + (i32.load offset=4 + (get_local $0) + ) + (i32.load offset=4 + (get_local $1) + ) + ) + (get_local $2) + ) + (i32.const 1) + ) + ) + ) + (func $start (; 12 ;) (type $v) + (local $0 i32) + (set_global "$(lib)/allocator/arena/startOffset" + (i32.and + (i32.add + (get_global $HEAP_BASE) + (i32.const 7) + ) + (i32.xor + (i32.const 7) + (i32.const -1) + ) + ) + ) + (set_global "$(lib)/allocator/arena/offset" + (get_global "$(lib)/allocator/arena/startOffset") + ) + (set_global $std/operator-overloading/a1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) + ) + (set_global $std/operator-overloading/a2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 2) + (i32.const 3) + ) + ) + (set_global $std/operator-overloading/a + (call $std/operator-overloading/Tester.add + (get_global $std/operator-overloading/a1) + (get_global $std/operator-overloading/a2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/a) + ) + (i32.const 3) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/a) + ) + (i32.const 5) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 57) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/s1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 2) + (i32.const 3) + ) + ) + (set_global $std/operator-overloading/s2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 2) + (i32.const -3) + ) + ) + (set_global $std/operator-overloading/s + (call $std/operator-overloading/Tester.sub + (get_global $std/operator-overloading/s1) + (get_global $std/operator-overloading/s2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/s) + ) + (i32.const 0) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/s) + ) + (i32.const 6) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 63) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/m1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 2) + (i32.const 5) + ) + ) + (set_global $std/operator-overloading/m2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 3) + (i32.const 2) + ) + ) + (set_global $std/operator-overloading/m + (call $std/operator-overloading/Tester.mul + (get_global $std/operator-overloading/m1) + (get_global $std/operator-overloading/m2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/m) + ) + (i32.const 6) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/m) + ) + (i32.const 10) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 69) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/d1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 6) + (i32.const 50) + ) + ) + (set_global $std/operator-overloading/d2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 3) + (i32.const 10) + ) + ) + (set_global $std/operator-overloading/d + (call $std/operator-overloading/Tester.div + (get_global $std/operator-overloading/d1) + (get_global $std/operator-overloading/d2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/d) + ) + (i32.const 2) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/d) + ) + (i32.const 5) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 75) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/f1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 10) + (i32.const 10) + ) + ) + (set_global $std/operator-overloading/f2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 6) + (i32.const 10) + ) + ) + (set_global $std/operator-overloading/f + (call $std/operator-overloading/Tester.mod + (get_global $std/operator-overloading/f1) + (get_global $std/operator-overloading/f2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/f) + ) + (i32.const 4) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/f) + ) + (i32.const 0) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 81) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/n1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 255) + (i32.const 15) + ) + ) + (set_global $std/operator-overloading/n2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 15) + (i32.const 255) + ) + ) + (set_global $std/operator-overloading/n + (call $std/operator-overloading/Tester.and + (get_global $std/operator-overloading/n1) + (get_global $std/operator-overloading/n2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/n) + ) + (i32.const 15) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/n) + ) + (i32.const 15) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 87) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/o1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 3855) + (i32.const 255) + ) + ) + (set_global $std/operator-overloading/o2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 61680) + (i32.const 0) + ) + ) + (set_global $std/operator-overloading/o + (call $std/operator-overloading/Tester.or + (get_global $std/operator-overloading/o1) + (get_global $std/operator-overloading/o2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/o) + ) + (i32.const 65535) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/o) + ) + (i32.const 255) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 93) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/x1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 255) + (i32.const 255) + ) + ) + (set_global $std/operator-overloading/x2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 65280) + (i32.const 0) + ) + ) + (set_global $std/operator-overloading/x + (call $std/operator-overloading/Tester.xor + (get_global $std/operator-overloading/x1) + (get_global $std/operator-overloading/x2) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (tee_local $0 + (i32.eq + (i32.load + (get_global $std/operator-overloading/x) + ) + (i32.const 65535) + ) + ) + (i32.eq + (i32.load offset=4 + (get_global $std/operator-overloading/x) + ) + (i32.const 255) + ) + (get_local $0) + ) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 99) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/eq1 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 1) + (i32.const -2) + ) + ) + (set_global $std/operator-overloading/eq2 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 1) + (i32.const -2) + ) + ) + (set_global $std/operator-overloading/eq + (call $std/operator-overloading/Tester.equal + (get_global $std/operator-overloading/eq1) + (get_global $std/operator-overloading/eq2) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $std/operator-overloading/eq) + (i32.const 1) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 105) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_global $std/operator-overloading/eq3 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 1) + (i32.const 0) + ) + ) + (set_global $std/operator-overloading/eq4 + (call $std/operator-overloading/Tester#constructor + (i32.const 0) + (i32.const 0) + (i32.const 1) + ) + ) + (set_global $std/operator-overloading/eqf + (call $std/operator-overloading/Tester.equal + (get_global $std/operator-overloading/eq3) + (get_global $std/operator-overloading/eq4) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $std/operator-overloading/eqf) + (i32.const 0) + ) + ) + (block + (call $abort + (i32.const 0) + (i32.const 4) + (i32.const 111) + (i32.const 0) + ) + (unreachable) + ) + ) + ) +)