| "use strict"; |
| |
| function assert(actual, expected, message) { |
| if (arguments.length == 1) |
| expected = true; |
| |
| if (actual === expected) |
| return; |
| |
| if (actual !== null && expected !== null |
| && typeof actual == 'object' && typeof expected == 'object' |
| && actual.toString() === expected.toString()) |
| return; |
| |
| throw Error("assertion failed: got |" + actual + "|" + |
| ", expected |" + expected + "|" + |
| (message ? " (" + message + ")" : "")); |
| } |
| |
| /* operators overloading with Operators.create() */ |
| function test_operators_create() { |
| class Vec2 |
| { |
| constructor(x, y) { |
| this.x = x; |
| this.y = y; |
| } |
| static mul_scalar(p1, a) { |
| var r = new Vec2(); |
| r.x = p1.x * a; |
| r.y = p1.y * a; |
| return r; |
| } |
| toString() { |
| return "Vec2(" + this.x + "," + this.y + ")"; |
| } |
| } |
| |
| Vec2.prototype[Symbol.operatorSet] = Operators.create( |
| { |
| "+"(p1, p2) { |
| var r = new Vec2(); |
| r.x = p1.x + p2.x; |
| r.y = p1.y + p2.y; |
| return r; |
| }, |
| "-"(p1, p2) { |
| var r = new Vec2(); |
| r.x = p1.x - p2.x; |
| r.y = p1.y - p2.y; |
| return r; |
| }, |
| "=="(a, b) { |
| return a.x == b.x && a.y == b.y; |
| }, |
| "<"(a, b) { |
| var r; |
| /* lexicographic order */ |
| if (a.x == b.x) |
| r = (a.y < b.y); |
| else |
| r = (a.x < b.x); |
| return r; |
| }, |
| "++"(a) { |
| var r = new Vec2(); |
| r.x = a.x + 1; |
| r.y = a.y + 1; |
| return r; |
| } |
| }, |
| { |
| left: Number, |
| "*"(a, b) { |
| return Vec2.mul_scalar(b, a); |
| } |
| }, |
| { |
| right: Number, |
| "*"(a, b) { |
| return Vec2.mul_scalar(a, b); |
| } |
| }); |
| |
| var a = new Vec2(1, 2); |
| var b = new Vec2(3, 4); |
| var r; |
| |
| r = a * 2 + 3 * b; |
| assert(r.x === 11 && r.y === 16); |
| assert(a == a, true); |
| assert(a == b, false); |
| assert(a != a, false); |
| assert(a < b, true); |
| assert(a <= b, true); |
| assert(b < a, false); |
| assert(b <= a, false); |
| assert(a <= a, true); |
| assert(a >= a, true); |
| a++; |
| assert(a.x === 2 && a.y === 3); |
| r = ++a; |
| assert(a.x === 3 && a.y === 4); |
| assert(r === a); |
| } |
| |
| /* operators overloading thru inheritance */ |
| function test_operators() |
| { |
| var Vec2; |
| |
| function mul_scalar(p1, a) { |
| var r = new Vec2(); |
| r.x = p1.x * a; |
| r.y = p1.y * a; |
| return r; |
| } |
| |
| var vec2_ops = Operators({ |
| "+"(p1, p2) { |
| var r = new Vec2(); |
| r.x = p1.x + p2.x; |
| r.y = p1.y + p2.y; |
| return r; |
| }, |
| "-"(p1, p2) { |
| var r = new Vec2(); |
| r.x = p1.x - p2.x; |
| r.y = p1.y - p2.y; |
| return r; |
| }, |
| "=="(a, b) { |
| return a.x == b.x && a.y == b.y; |
| }, |
| "<"(a, b) { |
| var r; |
| /* lexicographic order */ |
| if (a.x == b.x) |
| r = (a.y < b.y); |
| else |
| r = (a.x < b.x); |
| return r; |
| }, |
| "++"(a) { |
| var r = new Vec2(); |
| r.x = a.x + 1; |
| r.y = a.y + 1; |
| return r; |
| } |
| }, |
| { |
| left: Number, |
| "*"(a, b) { |
| return mul_scalar(b, a); |
| } |
| }, |
| { |
| right: Number, |
| "*"(a, b) { |
| return mul_scalar(a, b); |
| } |
| }); |
| |
| Vec2 = class Vec2 extends vec2_ops |
| { |
| constructor(x, y) { |
| super(); |
| this.x = x; |
| this.y = y; |
| } |
| toString() { |
| return "Vec2(" + this.x + "," + this.y + ")"; |
| } |
| } |
| |
| var a = new Vec2(1, 2); |
| var b = new Vec2(3, 4); |
| var r; |
| |
| r = a * 2 + 3 * b; |
| assert(r.x === 11 && r.y === 16); |
| assert(a == a, true); |
| assert(a == b, false); |
| assert(a != a, false); |
| assert(a < b, true); |
| assert(a <= b, true); |
| assert(b < a, false); |
| assert(b <= a, false); |
| assert(a <= a, true); |
| assert(a >= a, true); |
| a++; |
| assert(a.x === 2 && a.y === 3); |
| r = ++a; |
| assert(a.x === 3 && a.y === 4); |
| assert(r === a); |
| } |
| |
| function test_default_op() |
| { |
| assert(Object(1) + 2, 3); |
| assert(Object(1) + true, 2); |
| assert(-Object(1), -1); |
| } |
| |
| test_operators_create(); |
| test_operators(); |
| test_default_op(); |