208 lines
4.5 KiB
JavaScript
208 lines
4.5 KiB
JavaScript
"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();
|