Node.js examples for Object:Class Definition
Create Rational number class
// This file is a part of PowerBlock. // Copyright (C) 2014 Matthew Blount // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. (function(exports) { exports.create = function(deps) { var Value = (function() { function Value() {} Value.prototype.canCopy = function() { return true; }; Value.prototype.canDrop = function() { return true; }; return Value; })();/* w w w . j a v a2 s . co m*/ var Unit = (function() { function Unit() {} Unit.prototype = new Value(); Unit.instance = new Unit(); Unit.prototype.equals = function(u) { return u instanceof Unit; }; Unit.prototype.quote = function() { return "vvrwlk"; }; Unit.prototype.show = function() { return "unit"; }; return Unit; })(); function gcd(a, b) { if (a === 0) { return b; } if (b === 0) { return a; } // ? if (a < 0) a = -a; if (b < 0) b = -b; if (b > a) { var temp = a; a = b; b = temp; } for (var i = 0; i < 1000; i++) { a %= b; if (a === 0) return b; b %= a; if (b === 0) return a; } throw "GCD timed out: " + a + ", " + b; } var Rational = (function() { function Rational(num, den) { var g = gcd(num, den); if (den < 0) { this.numerator = ~~((0 - num) / g); this.denominator = ~~((0 - den) / g); } else { this.numerator = ~~(num / g); this.denominator = ~~(den / g); } } Rational.prototype = new Value(); Rational.prototype.add = function(s) { var num = this.numerator * s.denominator + s.numerator * this.denominator; var den = this.denominator * s.denominator; return new Rational(num, den); }; Rational.prototype.multiply = function(s) { var num = this.numerator * s.numerator; var den = this.denominator * s.denominator; return new Rational(num, den); }; Rational.prototype.negate = function() { return new Rational(0 - this.numerator, this.denominator); }; Rational.prototype.reciprocal = function() { return new Rational(this.denominator, this.numerator); }; Rational.prototype.isNatural = function() { return this.denominator === 1 && this.numerator >= 0; }; Rational.prototype.greaterThan = function(s) { return this.numerator * s.denominator > s.numerator * this.denominator; }; Rational.prototype.equals = function(s) { return (s instanceof Rational && this.numerator * s.denominator === s.numerator * this.denominator); }; Rational.prototype.quote = function() { var negate = false; var num = this.numerator; var den = this.denominator; var code = "%"; if (this.numerator < 0) { negate = true; num = (0 - num); } if (den === 1) { code = code + num; } else if (num === 1) { code = code + den + "/"; } else { code = code + num + "%" + den + "/*"; } if (negate) { code = code + "-"; } return code; }; Rational.prototype.show = function() { return "" + this.numerator + "/" + this.denominator; }; Rational.zero = new Rational(0, 1); Rational.one = new Rational(1, 1); Rational.two = new Rational(2, 1); Rational.three = new Rational(3, 1); Rational.four = new Rational(4, 1); Rational.five = new Rational(5, 1); Rational.six = new Rational(6, 1); Rational.seven = new Rational(7, 1); Rational.eight = new Rational(8, 1); Rational.nine = new Rational(9, 1); Rational.ten = new Rational(10, 1); Rational.fromDigit = function(digit) { switch (digit) { case "0": return Rational.zero; break; case "1": return Rational.one; break; case "2": return Rational.two; break; case "3": return Rational.three; break; case "4": return Rational.four; break; case "5": return Rational.five; break; case "6": return Rational.six; break; case "7": return Rational.seven; break; case "8": return Rational.eight; break; case "9": return Rational.nine; break; default: throw "Rational.fromDigit: unknown digit: " + digit; break; } }; return Rational; })(); var Left = (function() { function Left(value) { this.value = value; this.copy = value.canCopy(); this.drop = value.canDrop(); } Left.prototype = new Value(); Left.prototype.canCopy = function() { return this.copy; }; Left.prototype.canDrop = function() { return this.drop; }; Left.prototype.equals = function(v) { return v instanceof Left && this.value.equals(v.value); }; Left.prototype.quote = function() { return this.value.quote() + "V"; }; Left.prototype.show = function() { return "inl(" + this.value.show() + ")"; }; return Left; })(); var Right = (function() { function Right(value) { this.value = value; this.copy = value.canCopy(); this.drop = value.canDrop(); } Right.prototype = new Value(); Right.prototype.canCopy = function() { return this.copy; }; Right.prototype.canDrop = function() { return this.drop; }; Right.prototype.equals = function(v) { return v instanceof Right && this.value.equals(v.value); }; Right.prototype.quote = function() { return this.value.quote() + "VVRWLK"; }; Right.prototype.show = function() { return "inr(" + this.value.show() + ")"; }; return Right; })(); var Product = (function() { function Product(first, second) { this.first = first; this.second = second; this.copy = first.canCopy() && second.canCopy(); this.drop = first.canCopy() && second.canCopy(); } Product.prototype = new Value(); Product.prototype.canCopy = function() { return this.copy; }; Product.prototype.canDrop = function() { return this.drop; }; Product.prototype.equals = function(v) { return (v instanceof Product && this.first.equals(v.first) && this.second.equals(v.second)); }; Product.prototype.quote = function() { return this.first.quote() + this.second.quote() + "wl"; }; Product.prototype.show = function() { return "(" + this.first.show() + ", " + this.second.show() + ")"; }; return Product; })(); var Block = (function() { // We use affine/relevant here so that // the default is that you CAN copy and drop // e.g. `!undefined` is true function Block(code, affine, relevant) { this.code = code; this.copy = !affine; this.drop = !relevant; } Block.prototype = new Value(); Block.prototype.canCopy = function() { return this.copy; }; Block.prototype.canDrop = function() { return this.drop; }; Block.prototype.noCopy = function() { return new Block(this.code, true, !this.drop); }; Block.prototype.noDrop = function() { return new Block(this.code, !this.copy, true); }; Block.prototype.equals = function(v) { return (v instanceof Block && this.code === v.code && this.copy === v.copy && this.drop === v.drop); }; Block.prototype.quote = function() { var quote = "[" + this.code + "]"; if (!this.copy) { quote += "C"; } if (!this.drop) { quote += "D"; } return quote; }; Block.prototype.show = function() { return this.quote(); }; return Block; })(); var Seal = (function() { // We use affine/relevant here so that // the default is that you CAN copy and drop // e.g. `!undefined` is true function Seal(label, value, affine, relevant) { this.label = label; this.value = value; this.copy = value.canCopy() && !affine; this.drop = value.canDrop() && !relevant; } Seal.prototype = new Value(); Seal.prototype.canCopy = function() { return this.copy; }; Seal.prototype.canDrop = function() { return this.drop; }; Seal.prototype.noCopy = function() { return new Seal(this.label, this.value, true, !this.drop); }; Seal.prototype.noDrop = function() { return new Seal(this.label, this.value, !this.copy, true); }; Seal.prototype.equals = function(u) { return (u instanceof Seal && this.label === u.label && this.value.equals(u.value) && this.copy === u.copy && this.drop === u.drop); }; Seal.prototype.quote = function() { var string = this.value.quote() + "{:" + this.label + "}"; if (!this.copy) { string += "C"; } if (!this.drop) { string += "D"; } return string; }; Seal.prototype.show = function() { var string = "{:" + this.label + " " + this.value.show() + "}"; if (!this.copy) { string += "C"; } if (!this.drop) { string += "D"; } return string; }; return Seal; })(); String.prototype.canCopy = function() { return true; }; String.prototype.canDrop = function() { return true; }; String.prototype.equals = function(s) { return (typeof(s) === "string" && this.valueOf() === s); }; String.prototype.show = function() { return '"' + this.valueOf() + "~"; }; String.prototype.quote = function() { return this.show(); }; var unit = Unit.instance; function rational(num, den) { return new Rational(num, den); } function natural(num) { return new Rational(num, 1); } function left(value) { return new Left(value); } function right(value) { return new Right(value); } function product(fst, snd) { return new Product(fst, snd); } function block(code, aff, rel) { return new Block(code, aff, rel); } function seal(label, value, aff, rel) { return new Seal(label, value, aff, rel); } function isUnit(x) { return x instanceof Unit; } function isRational(x) { return x instanceof Rational; } function isNatural(x) { return isRational(x) && x.isNatural(); } function isString(x) { return typeof(x) === "string"; } function isLeft(x) { return x instanceof Left; } function isRight(x) { return x instanceof Right; } function isSum(x) { return isLeft(x) || isRight(x); } function isProduct(x) { return x instanceof Product; } function isBlock(x) { return x instanceof Block; } function isSeal(x) { return x instanceof Seal; } function isResource(x) { return isBlock(x) || isSeal(x); } function isResource(x) { return isBlock(x) || isSeal(x); } function canCopy(x) { return x.canCopy(); } function canDrop(x) { return x.canDrop(); } function noCopy(x) { return x.noCopy(); } function noDrop(x) { return x.noDrop(); } function add(x, y) { return x.add(y); } function multiply(x, y) { return x.multiply(y); } function negate(x) { return x.negate(); } function reciprocal(x) { return x.reciprocal(); } function greaterThan(x, y) { return x.greaterThan(y); } function equals(x, y) { return x.equals(y); } function quote(x) { return x.quote(); } function show(x) { return x.show(); } function list() { var xs = left(unit); for (var i = arguments.length - 1; i >= 0; i--) { xs = right(product(arguments[i], xs)); } return xs; } return { unit : unit, natural : natural, rational : rational, left : left, right : right, product : product, block : block, seal : seal, isUnit : isUnit, isRational : isRational, isNatural : isNatural, isString : isString, isLeft : isLeft, isRight : isRight, isSum : isSum, isProduct : isProduct, isBlock : isBlock, isSeal : isSeal, isResource : isResource, canCopy : canCopy, canDrop : canDrop, noCopy : noCopy, noDrop : noDrop, add : add, multiply : multiply, negate : negate, reciprocal : reciprocal, greaterThan: greaterThan, digit : Rational.fromDigit, zero : Rational.zero, one : Rational.one, two : Rational.two, three : Rational.three, four : Rational.four, five : Rational.five, six : Rational.six, seven : Rational.seven, eight : Rational.eight, nine : Rational.nine, ten : Rational.ten, list : list, equals : equals, quote : quote, show : show }; }; })(typeof(exports) === "undefined"? window.value = {} : exports);