From e743d92f5f6786007b7b7ce64fbf46c7334a5b84 Mon Sep 17 00:00:00 2001 From: Alex Russell Date: Sun, 26 Apr 2015 01:29:45 -0700 Subject: [PATCH] Update the build. --- bin/c.js | 4610 ++++++++++++++++++++++++++++++++++++++++++++++++- package.json | 3 +- util/build.sh | 7 +- 3 files changed, 4609 insertions(+), 11 deletions(-) diff --git a/bin/c.js b/bin/c.js index 93baa85..8897379 100644 --- a/bin/c.js +++ b/bin/c.js @@ -12,16 +12,4608 @@ */ (function() { - - - - Failed to Uglify - -

Failed to Uglify

-

Unexpected token name «of», expected punc «;»

- - +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011-2012, Alex Russell (slightlyoff@chromium.org) +(function(scope){ +"use strict"; + +var inBrowser = (typeof scope["HTMLElement"] != "undefined"); + +var getTagName = function(proto) { + var tn = null; + while (proto && proto != Object.prototype) { + if (proto.tagName) { + tn = proto.tagName; + break; + } + proto = proto.prototype; + } + return tn || "div"; +}; +var epsilon = 1e-8; + +var _t_map = {}; +var walkForMethod = function(ctor, name) { + if (!ctor || !name) return; + + // Check the class-side first, the look at the prototype, then walk up + if (typeof ctor[name] == "function") { + return ctor[name]; + } + var p = ctor.prototype; + if (p && typeof p[name] == "function") { + return p[name]; + } + if (p === Object.prototype || + p === Function.prototype) { + return; + } + + if (typeof ctor.__super__ == "function") { + return walkForMethod(ctor.__super__, name); + } +}; + +// Global +var c = scope.c = function() { + if(c._api) { + return c._api.apply(this, arguments); + } +}; + +// +// Constants +// +c.GEQ = 1; +c.LEQ = 2; + +var inBrowserProtoFlip = (!inBrowser) ? + function(realCtor, parent, rp, props) { return realCtor; } : + function(realCtor, parent, rp, props) { + // If we're in a browser, we want to support "subclassing" HTML elements. + // This needs some magic and we rely on a wrapped constructor hack to make + // it happen. + if (parent && parent.prototype instanceof scope.HTMLElement) { + var intermediateCtor = realCtor; + var tn = getTagName(rp); + var upgrade = function(el) { + el.__proto__ = rp; + intermediateCtor.apply(el, arguments); + if (rp["created"]) { el.created(); } + if (rp["decorate"]) { el.decorate(); } + return el; + }; + c.extend(rp, { upgrade: upgrade }); + + realCtor = function() { + // We hack the constructor to always return an element with it's + // prototype wired to ours. Boo. + return upgrade(scope.document.createElement(tn)); + } + realCtor.prototype = rp; + c.extend(realCtor, { ctor: intermediateCtor }); // HACK!!! + } + return realCtor + }; + +// +// Utility methods +// +c.inherit = function(props) { + var ctor = null; + var parent = null; + + if (props["extends"]) { + parent = props["extends"]; + delete props["extends"]; + } + + if (props["initialize"]) { + ctor = props["initialize"]; + delete props["initialize"]; + } + + var realCtor = ctor || function() { }; + + Object.defineProperty(realCtor, "__super__", { + value: (parent) ? parent : Object, + enumerable: false, + configurable: true, + writable: false, + }); + + if (props["_t"]) { + _t_map[props["_t"]] = realCtor; + } + + // FIXME(slightlyoff): would like to have class-side inheritance! + // It's easy enough to do when we have __proto__, but we don't in IE 9/10. + // = ( + var rp = realCtor.prototype = Object.create( + ((parent) ? parent.prototype : Object.prototype) + ); + c.extend(rp, props); + return inBrowserProtoFlip(realCtor, parent, rp, props); +}; + +c.own = function(obj, cb, context) { + Object.getOwnPropertyNames(obj).forEach(cb, context||scope); + return obj; +}; + +c.extend = function(obj, props) { + c.own(props, function(x) { + var pd = Object.getOwnPropertyDescriptor(props, x); + if ( (typeof pd["get"] == "function") || + (typeof pd["set"] == "function") ) { + Object.defineProperty(obj, x, pd); + } else if (typeof pd["value"] == "function" ||x.charAt(0) === "_") { + pd.writable = true; + pd.configurable = true; + pd.enumerable = false; + Object.defineProperty(obj, x, pd); + } else { + try { + obj[x] = props[x]; + } catch(e) { + // TODO(slightlyoff): squelch, e.g. for tagName? + } + } + }); + return obj; +}; + +c.assert = function(f /*boolean*/, description /*String*/) { + if (!f) { + throw new c.InternalError("Assertion failed: " + description); + } +}; + +var exprFromVarOrValue = function(v) { + if (typeof v == "number" ) { + return c.Expression.fromConstant(v); + } else if(v instanceof c.Variable) { + return c.Expression.fromVariable(v); + } + return v; +}; + +c.plus = function(e1, e2) { + e1 = exprFromVarOrValue(e1); + e2 = exprFromVarOrValue(e2); + return e1.plus(e2); +}; + +c.minus = function(e1, e2) { + e1 = exprFromVarOrValue(e1); + e2 = exprFromVarOrValue(e2); + return e1.minus(e2); +}; + +c.times = function(e1, e2) { + e1 = exprFromVarOrValue(e1); + e2 = exprFromVarOrValue(e2); + return e1.times(e2); +}; + +c.divide = function(e1, e2) { + e1 = exprFromVarOrValue(e1); + e2 = exprFromVarOrValue(e2); + return e1.divide(e2); +}; + +c.approx = function(a, b) { + a = +(a); + b = +(b); + if (a === b) { return true; } + if (a == 0) { + return (Math.abs(b) < epsilon); + } + if (b == 0) { + return (Math.abs(a) < epsilon); + } + return (Math.abs(a - b) < Math.abs(a) * epsilon); +}; + +var count = 1; +c._inc = function() { return count++; }; + +c.parseJSON = function(str) { + return JSON.parse(str, function(k, v) { + if (typeof v != "object" || typeof v["_t"] != "string") { + return v; + } + var type = v["_t"]; + var ctor = _t_map[type]; + if (type && ctor) { + var fromJSON = walkForMethod(ctor, "fromJSON"); + if (fromJSON) { + return fromJSON(v, ctor); + } + } + return v; + }); +}; + +if (typeof define === 'function' && define.amd) { + // Require.js + define(c); +} else if (typeof module === 'object' && module.exports) { + // CommonJS + module.exports = c; +} else { + // Browser without module container + scope.c = c; +} + +})(this); +/** + * Copyright 2012 Alex Russell . + * + * Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 + * + * This is an API compatible re-implementation of the subset of jshashtable + * which Cassowary actually uses. + * + * Features removed: + * + * - multiple values per key + * - error tollerent hashing of any variety + * - overly careful (or lazy) size counting, etc. + * - Crockford's "class" pattern. We use the system from c.js. + * - any attempt at back-compat with broken runtimes. + * + * APIs removed, mostly for lack of use in Cassowary: + * + * - support for custom hashing and equality functions as keys to ctor + * - isEmpty() -> check for !ht.size() + * - putAll() + * - entries() + * - containsKey() + * - containsValue() + * - keys() + * - values() + * + * Additions: + * + * - new "scope" parameter to each() and escapingEach() + */ + +(function(c) { +"use strict"; + +if (typeof Map != "undefined" && + typeof Map.prototype.forEach != "undefined") { + + c.HashTable = c.inherit({ + + initialize: function(ht) { + this.hashCode = c._inc(); + this._store = new Map(); + if (ht instanceof c.HashTable) { + if (Map.length) { + this._store = new Map(ht._store); + } else { // Hacking around Safari 8's limitations + var that = this._store; + ht._store.forEach(function(v, k) { + that.set(k, v); + }); + } + } + }, + + clone: function() { + return new c.HashTable(this); + }, + + get: function(key) { + var r = this._store.get(key.hashCode); + if (r === undefined) { + return null; + } + return r[1]; + }, + + clear: function() { + this._store.clear(); + }, + + get size() { + return this._store.size; + }, + + set: function(key, value) { + // if (!key.hashCode) debugger; + return this._store.set(key.hashCode, [key, value]); + }, + + delete: function(key) { + return this._store.delete(key.hashCode); + }, + + each: function(callback, scope) { + this._store.forEach(function(v, k) { + return callback.call(scope||null, v[0], v[1]); + }, scope); + }, + + escapingEach: function(callback, scope) { + if (!this._store.size) { return; } + + var context; + var keys = []; + var rec; + for(var y of this._store.keys()) { + keys.push(y) + }; + + for(var k in keys) { + rec = this._store.get(keys[k]); + context = callback.call(scope||null, rec[0], rec[1]); + + if (context) { + if (context.retval !== undefined) { + return context; + } + if (context.brk) { + break; + } + } + } + }, + + equals: function(other) { + if (other === this) { + return true; + } + + if (!(other instanceof c.HashTable) || other._size !== this._size) { + return false; + } + + for(var x in this._store.keys()) { + if (other._store.get(x) == undefined) { + return false; + } + } + return true; + }, + + }); + +} else { + // For escapingEach + var defaultContext = {}; + var copyOwn = function(src, dest) { + Object.keys(src).forEach(function(x) { + dest[x] = src[x]; + }); + }; + + + c.HashTable = c.inherit({ + + initialize: function() { + this.size = 0; + this._store = {}; + this._keyStrMap = {}; + this._deleted = 0; + }, + + set: function(key, value) { + var hash = key.hashCode; + + if (typeof this._store[hash] == "undefined") { + // FIXME(slightlyoff): if size gooes above the V8 property limit, + // compact or go to a tree. + this.size++; + } + this._store[hash] = value; + this._keyStrMap[hash] = key; + }, + + get: function(key) { + if(!this.size) { return null; } + + key = key.hashCode; + + var v = this._store[key]; + if (typeof v != "undefined") { + return this._store[key]; + } + return null; + }, + + clear: function() { + this.size = 0; + this._store = {}; + this._keyStrMap = {}; + }, + + _compact: function() { + // console.time("HashTable::_compact()"); + var ns = {}; + copyOwn(this._store, ns); + this._store = ns; + // console.timeEnd("HashTable::_compact()"); + }, + + _compactThreshold: 100, + _perhapsCompact: function() { + // If we have more properties than V8's fast property lookup limit, don't + // bother + if (this._size > 30) return; + if (this._deleted > this._compactThreshold) { + this._compact(); + this._deleted = 0; + } + }, + + delete: function(key) { + key = key.hashCode; + if (!this._store.hasOwnProperty(key)) { + return; + } + this._deleted++; + + // FIXME(slightlyoff): + // I hate this because it causes these objects to go megamorphic = ( + // Sadly, Cassowary is hugely sensitive to iteration order changes, and + // "delete" preserves order when Object.keys() is called later. + delete this._store[key]; + // Note: we don't delete from _keyStrMap because we only get the + // Object.keys() from _store, so it's the only one we need to keep up-to- + // date. + + if (this.size > 0) { + this.size--; + } + }, + + each: function(callback, scope) { + if (!this.size) { return; } + + this._perhapsCompact(); + + var store = this._store; + var keyMap = this._keyStrMap; + for (var x in this._store) { + if (this._store.hasOwnProperty(x)) { + callback.call(scope||null, keyMap[x], store[x]); + } + } + }, + + escapingEach: function(callback, scope) { + if (!this.size) { return; } + + this._perhapsCompact(); + + var that = this; + var store = this._store; + var keyMap = this._keyStrMap; + var context = defaultContext; + var kl = Object.keys(store); + for (var x = 0; x < kl.length; x++) { + (function(v) { + if (that._store.hasOwnProperty(v)) { + context = callback.call(scope||null, keyMap[v], store[v]); + } + })(kl[x]); + + if (context) { + if (context.retval !== undefined) { + return context; + } + if (context.brk) { + break; + } + } + } + }, + + clone: function() { + var n = new c.HashTable(); + if (this.size) { + n.size = this.size; + copyOwn(this._store, n._store); + copyOwn(this._keyStrMap, n._keyStrMap); + } + return n; + }, + + equals: function(other) { + if (other === this) { + return true; + } + + if (!(other instanceof c.HashTable) || other._size !== this._size) { + return false; + } + + var codes = Object.keys(this._store); + for (var i = 0; i < codes.length; i++) { + var code = codes[i]; + if (this._keyStrMap[code] !== other._keyStrMap[code] || + this._store[code] !== other._store[code]) { + return false; + } + } + + return true; + }, + + toString: function(h) { + var answer = ""; + this.each(function(k, v) { answer += k + " => " + v + "\n"; }); + return answer; + }, + + toJSON: function() { + var d = {}; + this.each(function(key, value) { + d[key.toString()] = (value.toJSON) ? value.toJSON : value.toString(); + }); + return { + _t: "c.HashTable", + store: d + }; + }, + + fromJSON: function(o) { + var r = new c.HashTable(); + /* + if (o.data) { + r.size = o.data.length; + r.storage = o.data; + } + */ + return r; + }, + }); +} + +})(this["c"]||module.parent.exports||{}); +/** + * Copyright 2011, Alex Russell + * + * Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 + * + * API compatible re-implementation of jshashset.js, including only what + * Cassowary needs. Built for speed, not comfort. + */ +(function(c) { +"use strict"; + +// FIXME(slightlyoff): now that Set is in v8 and has iteration, migrate + +c.HashSet = c.inherit({ + _t: "c.HashSet", + + initialize: function() { + this.storage = []; + this.size = 0; + this.hashCode = c._inc(); + }, + + add: function(item) { + var s = this.storage, io = s.indexOf(item); + if (s.indexOf(item) == -1) { s[s.length] = item; } + this.size = this.storage.length; + }, + + values: function() { + // FIXME(slightlyoff): is it safe to assume we won't be mutated by our caller? + // if not, return this.storage.slice(0); + return this.storage; + }, + + has: function(item) { + var s = this.storage; + return (s.indexOf(item) != -1); + }, + + delete: function(item) { + var io = this.storage.indexOf(item); + if (io == -1) { return null; } + this.storage.splice(io, 1)[0]; + this.size = this.storage.length; + }, + + clear: function() { + this.storage.length = 0; + }, + + each: function(func, scope) { + if(this.size) + this.storage.forEach(func, scope); + }, + + escapingEach: function(func, scope) { + // FIXME(slightlyoff): actually escape! + if (this.size) + this.storage.forEach(func, scope); + }, + + toString: function() { + var answer = this.size + " {"; + var first = true; + this.each(function(e) { + if (!first) { + answer += ", "; + } else { + first = false; + } + answer += e; + }); + answer += "}\n"; + return answer; + }, + + toJSON: function() { + var d = []; + this.each(function(e) { + d[d.length] = e.toJSON(); + }); + return { + _t: "c.HashSet", + data: d + }; + }, + + fromJSON: function(o) { + var r = new c.HashSet(); + if (o.data) { + r.size = o.data.length; + r.storage = o.data; + } + return r; + }, +}); + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011-2012, Alex Russell (slightlyoff@chromium.org) + +(function(c){ + "use strict"; + + c.Error = c.inherit({ + // extends: Error, + initialize: function(s /*String*/) { if (s) { this._description = s; } }, + _name: "c.Error", + _description: "An error has occured in Cassowary", + set description(v) { this._description = v; }, + get description() { return "(" + this._name + ") " + this._description; }, + get message() { return this.description; }, + toString: function() { return this.description; }, + }); + + var errorType = function(name, error) { + return c.inherit({ + extends: c.Error, + initialize: function() { c.Error.apply(this, arguments); }, + _name: name||"", _description: error||"" + }); + }; + + c.ConstraintNotFound = + errorType("c.ConstraintNotFound", + "Tried to remove a constraint never added to the tableu"); + + c.InternalError = + errorType("c.InternalError"); + + c.NonExpression = + errorType("c.NonExpression", + "The resulting expression would be non"); + + c.NotEnoughStays = + errorType("c.NotEnoughStays", + "There are not enough stays to give specific values to every variable"); + + c.RequiredFailure = + errorType("c.RequiredFailure", "A required constraint cannot be satisfied"); + + c.TooDifficult = + errorType("c.TooDifficult", "The constraints are too difficult to solve"); + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011-2012, Alex Russell (slightlyoff@chromium.org) + +(function(c) { +"use strict"; + +var multiplier = 1000; + +c.SymbolicWeight = c.inherit({ + _t: "c.SymbolicWeight", + initialize: function(/*w1, w2, w3*/) { + this.value = 0; + var factor = 1; + for (var i = arguments.length - 1; i >= 0; --i) { + this.value += arguments[i] * factor; + factor *= multiplier; + } + }, + + toJSON: function() { + return { + _t: this._t, + value: this.value + }; + }, +}); + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011, Alex Russell (slightlyoff@chromium.org) + +// FILE: EDU.Washington.grad.gjb.cassowary +// package EDU.Washington.grad.gjb.cassowary; + +(function(c) { + +c.Strength = c.inherit({ + initialize: function(name /*String*/, symbolicWeight, w2, w3) { + this.name = name; + if (symbolicWeight instanceof c.SymbolicWeight) { + this.symbolicWeight = symbolicWeight; + } else { + this.symbolicWeight = new c.SymbolicWeight(symbolicWeight, w2, w3); + } + }, + + get required() { + return (this === c.Strength.required); + }, + + toString: function() { + return this.name + (!this.required ? (":" + this.symbolicWeight) : ""); + }, +}); + +/* public static final */ +c.Strength.required = new c.Strength("", 1000, 1000, 1000); +/* public static final */ +c.Strength.strong = new c.Strength("strong", 1, 0, 0); +/* public static final */ +c.Strength.medium = new c.Strength("medium", 0, 1, 0); +/* public static final */ +c.Strength.weak = new c.Strength("weak", 0, 0, 1); + +})(this["c"]||((typeof module != "undefined") ? module.parent.exports.c : {})); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011-2012, Alex Russell (slightlyoff@chromium.org) + +(function(c) { +"use strict"; + +c.AbstractVariable = c.inherit({ + isDummy: false, + isExternal: false, + isPivotable: false, + isRestricted: false, + + _init: function(args, varNamePrefix) { + // Common mixin initialization. + this.hashCode = c._inc(); + this.name = (varNamePrefix||"") + this.hashCode; + if (args) { + if (typeof args.name != "undefined") { + this.name = args.name; + } + if (typeof args.value != "undefined") { + this.value = args.value; + } + if (typeof args.prefix != "undefined") { + this._prefix = args.prefix; + } + } + }, + + _prefix: "", + name: "", + value: 0, + + valueOf: function() { return this.value; }, + + toJSON: function() { + var o = {}; + if (this._t) { + o._t = this._t; + } + if (this.name) { + o.name = this.name; + } + if (typeof this.value != "undefined") { + o.value = this.value; + } + if (this._prefix) { + o._prefix = this._prefix; + } + if (this._t) { + o._t = this._t; + } + return o; + }, + + fromJSON: function(o, Ctor) { + var r = new Ctor(); + c.extend(r, o); + return r; + }, + + toString: function() { + return this._prefix + "[" + this.name + ":" + this.value + "]"; + }, + +}); + +c.Variable = c.inherit({ + _t: "c.Variable", + extends: c.AbstractVariable, + initialize: function(args) { + this._init(args, "v"); + var vm = c.Variable._map; + if (vm) { vm[this.name] = this; } + }, + isExternal: true, +}); + +/* static */ +// c.Variable._map = []; + +c.DummyVariable = c.inherit({ + _t: "c.DummyVariable", + extends: c.AbstractVariable, + initialize: function(args) { + this._init(args, "d"); + }, + isDummy: true, + isRestricted: true, + value: "dummy", +}); + +c.ObjectiveVariable = c.inherit({ + _t: "c.ObjectiveVariable", + extends: c.AbstractVariable, + initialize: function(args) { + this._init(args, "o"); + }, + value: "obj", +}); + +c.SlackVariable = c.inherit({ + _t: "c.SlackVariable", + extends: c.AbstractVariable, + initialize: function(args) { + this._init(args, "s"); + }, + isPivotable: true, + isRestricted: true, + value: "slack", +}); + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011, Alex Russell (slightlyoff@chromium.org) + +(function(c) { +"use strict"; +c.Point = c.inherit({ + initialize: function(x, y, suffix) { + if (x instanceof c.Variable) { + this._x = x; + } else { + var xArgs = { value: x }; + if (suffix) { + xArgs.name = "x" + suffix; + } + this._x = new c.Variable(xArgs); + } + if (y instanceof c.Variable) { + this._y = y; + } else { + var yArgs = { value: y }; + if (suffix) { + yArgs.name = "y" + suffix; + } + this._y = new c.Variable(yArgs); + } + }, + + get x() { return this._x; }, + set x(xVar) { + if (xVar instanceof c.Variable) { + this._x = xVar; + } else { + this._x.value = xVar; + } + }, + + get y() { return this._y; }, + set y(yVar) { + if (yVar instanceof c.Variable) { + this._y = yVar; + } else { + this._y.value = yVar; + } + }, + + toString: function() { + return "(" + this.x + ", " + this.y + ")"; + }, +}); + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011, Alex Russell (slightlyoff@chromium.org) + +// FILE: EDU.Washington.grad.gjb.cassowary +// package EDU.Washington.grad.gjb.cassowary; + +(function(c) { +"use strict"; + +var checkNumber = function(value, otherwise){ + // if(isNaN(value)) { debugger; } + return (typeof value === "number") ? value : otherwise; +}; + +c.Expression = c.inherit({ + + initialize: function(cvar /*c.AbstractVariable*/, + value /*double*/, + constant /*double*/) { + this.constant = checkNumber(constant, 0); + this.terms = new c.HashTable(); + this.externalVariables = new c.HashSet(); + Object.defineProperty(this, "solver", { + enumerable: false, + configurable: true, + writable: true, + value: null + }); + if (cvar instanceof c.AbstractVariable) { + value = checkNumber(value, 1); + this.setVariable(cvar, value); + } else if (typeof cvar == "number") { + if (!isNaN(cvar)) { + this.constant = cvar; + } else { + console.trace(); + } + } + }, + + initializeFromHash: function(constant /*ClDouble*/, terms /*c.Hashtable*/) { + this.constant = constant; + this.terms = terms.clone(); + return this; + }, + + multiplyMe: function(x /*double*/) { + this.constant *= x; + var t = this.terms; + t.each(function(clv, coeff) { t.set(clv, coeff * x); }); + return this; + }, + + clone: function() { + var e = c.Expression.empty(); + e.initializeFromHash(this.constant, this.terms); + e.solver = this.solver; + return e; + }, + + times: function(x) { + if (typeof x == 'number') { + return (this.clone()).multiplyMe(x); + } else { + if (this.isConstant) { + return x.times(this.constant); + } else if (x.isConstant) { + return this.times(x.constant); + } else { + throw new c.NonExpression(); + } + } + }, + + plus: function(expr /*c.Expression*/) { + if (expr instanceof c.Expression) { + return this.clone().addExpression(expr, 1); + } else if (expr instanceof c.Variable) { + return this.clone().addVariable(expr, 1); + } + }, + + minus: function(expr /*c.Expression*/) { + if (expr instanceof c.Expression) { + return this.clone().addExpression(expr, -1); + } else if (expr instanceof c.Variable) { + return this.clone().addVariable(expr, -1); + } + }, + + divide: function(x) { + if (typeof x == 'number') { + if (c.approx(x, 0)) { + throw new c.NonExpression(); + } + return this.times(1 / x); + } else if (x instanceof c.Expression) { + if (!x.isConstant) { + throw new c.NonExpression(); + } + return this.times(1 / x.constant); + } + }, + + addExpression: function(expr /*c.Expression*/, + n /*double*/, + subject /*c.AbstractVariable*/) { + if (expr instanceof c.AbstractVariable) { + expr = c.Expression.fromVariable(expr); + } + n = checkNumber(n, 1); + this.constant += (n * expr.constant); + expr.terms.each(function(clv, coeff) { + /* + if (clv.isExternal) { + console.log("clv:", clv, "coeff:", coeff, "subject:", subject); + } + */ + this.addVariable(clv, coeff * n, subject); + this._updateIfExternal(clv); + }, this); + return this; + }, + + addVariable: function(v /*c.AbstractVariable*/, cd /*double*/, subject) { + if (cd == null) { cd = 1; } + + var coeff = this.terms.get(v); + if (coeff) { + var newCoefficient = coeff + cd; + if (newCoefficient == 0 || c.approx(newCoefficient, 0)) { + if (this.solver) { + this.solver.noteRemovedVariable(v, subject); + } + this.terms.delete(v); + } else { + this.setVariable(v, newCoefficient); + } + } else { + if (!c.approx(cd, 0)) { + this.setVariable(v, cd); + if (this.solver) { + this.solver.noteAddedVariable(v, subject); + } + } + } + return this; + }, + + _updateIfExternal: function(v) { + if (v.isExternal) { + this.externalVariables.add(v); + if (this.solver) { + this.solver._noteUpdatedExternal(v); + } + } + }, + + setVariable: function(v /*c.AbstractVariable*/, c /*double*/) { + this.terms.set(v, c); + this._updateIfExternal(v); + return this; + }, + + anyPivotableVariable: function() { + if (this.isConstant) { + throw new c.InternalError("anyPivotableVariable called on a constant"); + } + + var rv = this.terms.escapingEach(function(clv, c) { + if (clv.isPivotable) return { retval: clv }; + }); + + if (rv && rv.retval !== undefined) { + return rv.retval; + } + + return null; + }, + + substituteOut: function(outvar /*c.AbstractVariable*/, + expr /*c.Expression*/, + subject /*c.AbstractVariable*/) { + + var solver = this.solver; + if (!solver) { + throw new c.InternalError("Expressions::substituteOut called without a solver"); + } + + var setVariable = this.setVariable.bind(this); + var terms = this.terms; + var multiplier = terms.get(outvar); + terms.delete(outvar); + this.constant += (multiplier * expr.constant); + /* + console.log("substituteOut:", + "\n\tsolver:", typeof this.solver, + "\n\toutvar:", outvar, + "\n\texpr:", expr.toString(), + "\n\tmultiplier:", multiplier, + "\n\tterms:", terms); + */ + expr.terms.each(function(clv, coeff) { + var oldCoefficient = terms.get(clv); + if (oldCoefficient) { + var newCoefficient = oldCoefficient + multiplier * coeff; + if (c.approx(newCoefficient, 0)) { + solver.noteRemovedVariable(clv, subject); + terms.delete(clv); + } else { + setVariable(clv, newCoefficient); + } + } else { + setVariable(clv, multiplier * coeff); + if (solver) { + solver.noteAddedVariable(clv, subject); + } + } + }); + }, + + changeSubject: function(old_subject /*c.AbstractVariable*/, + new_subject /*c.AbstractVariable*/) { + this.setVariable(old_subject, this.newSubject(new_subject)); + }, + + newSubject: function(subject /*c.AbstractVariable*/) { + var reciprocal = 1 / this.terms.get(subject); + this.terms.delete(subject); + this.multiplyMe(-reciprocal); + return reciprocal; + }, + + // Return the coefficient corresponding to variable var, i.e., + // the 'ci' corresponding to the 'vi' that var is: + // v1*c1 + v2*c2 + .. + vn*cn + c + coefficientFor: function(clv /*c.AbstractVariable*/) { + return this.terms.get(clv) || 0; + }, + + get isConstant() { + return this.terms.size == 0; + }, + + toString: function() { + var bstr = ''; // answer + var needsplus = false; + if (!c.approx(this.constant, 0) || this.isConstant) { + bstr += this.constant; + if (this.isConstant) { + return bstr; + } else { + needsplus = true; + } + } + this.terms.each( function(clv, coeff) { + if (needsplus) { + bstr += " + "; + } + bstr += coeff + "*" + clv; + needsplus = true; + }); + return bstr; + }, + + equals: function(other) { + if (other === this) { + return true; + } + + return other instanceof c.Expression && + other.constant === this.constant && + other.terms.equals(this.terms); + }, + + Plus: function(e1 /*c.Expression*/, e2 /*c.Expression*/) { + return e1.plus(e2); + }, + + Minus: function(e1 /*c.Expression*/, e2 /*c.Expression*/) { + return e1.minus(e2); + }, + + Times: function(e1 /*c.Expression*/, e2 /*c.Expression*/) { + return e1.times(e2); + }, + + Divide: function(e1 /*c.Expression*/, e2 /*c.Expression*/) { + return e1.divide(e2); + }, +}); + +c.Expression.empty = function(solver) { + var e = new c.Expression(undefined, 1, 0); + e.solver = solver; + return e; +}; + +c.Expression.fromConstant = function(cons, solver) { + var e = new c.Expression(cons); + e.solver = solver; + return e; +}; + +c.Expression.fromValue = function(v, solver) { + v = +(v); + var e = new c.Expression(undefined, v, 0); + e.solver = solver; + return e; +}; + +c.Expression.fromVariable = function(v, solver) { + var e = new c.Expression(v, 1, 0); + e.solver = solver; + return e; +} + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011-2012, Alex Russell (slightlyoff@chromium.org) + +(function(c) { +"use strict"; + +c.AbstractConstraint = c.inherit({ + initialize: function(strength /*c.Strength*/, weight /*double*/) { + this.hashCode = c._inc(); + this.strength = strength || c.Strength.required; + this.weight = weight || 1; + }, + + isEdit: false, + isInequality: false, + isStay: false, + get required() { return (this.strength === c.Strength.required); }, + + toString: function() { + // this is abstract -- it intentionally leaves the parens unbalanced for + // the subclasses to complete (e.g., with ' = 0', etc. + return this.strength + " {" + this.weight + "} (" + this.expression +")"; + }, +}); + +var ts = c.AbstractConstraint.prototype.toString; + +var EditOrStayCtor = function(cv /*c.Variable*/, strength /*c.Strength*/, weight /*double*/) { + c.AbstractConstraint.call(this, strength || c.Strength.strong, weight); + this.variable = cv; + this.expression = new c.Expression(cv, -1, cv.value); +}; + +c.EditConstraint = c.inherit({ + extends: c.AbstractConstraint, + initialize: function() { EditOrStayCtor.apply(this, arguments); }, + isEdit: true, + toString: function() { return "edit:" + ts.call(this); }, +}); + +c.StayConstraint = c.inherit({ + extends: c.AbstractConstraint, + initialize: function() { EditOrStayCtor.apply(this, arguments); }, + isStay: true, + toString: function() { return "stay:" + ts.call(this); }, +}); + +var lc = +c.Constraint = c.inherit({ + extends: c.AbstractConstraint, + initialize: function(cle /*c.Expression*/, + strength /*c.Strength*/, + weight /*double*/) { + c.AbstractConstraint.call(this, strength, weight); + this.expression = cle; + }, +}); + +c.Inequality = c.inherit({ + extends: c.Constraint, + + _cloneOrNewCle: function(cle) { + // FIXME(D4): move somewhere else? + if (cle.clone) { + return cle.clone(); + } else { + return new c.Expression(cle); + } + }, + + initialize: function(a1, a2, a3, a4, a5) { + // FIXME(slightlyoff): what a disgusting mess. Should at least add docs. + // console.log("c.Inequality.initialize(", a1, a2, a3, a4, a5, ")"); + + var a1IsExp = a1 instanceof c.Expression, + a3IsExp = a3 instanceof c.Expression, + a1IsVar = a1 instanceof c.AbstractVariable, + a3IsVar = a3 instanceof c.AbstractVariable, + a1IsNum = typeof(a1) == 'number', + a3IsNum = typeof(a3) == 'number'; + + // (cle || number), op, cv + if ((a1IsExp || a1IsNum) && a3IsVar) { + var cle = a1, op = a2, cv = a3, strength = a4, weight = a5; + lc.call(this, this._cloneOrNewCle(cle), strength, weight); + if (op == c.LEQ) { + this.expression.multiplyMe(-1); + this.expression.addVariable(cv); + } else if (op == c.GEQ) { + this.expression.addVariable(cv, -1); + } else { + throw new c.InternalError("Invalid operator in c.Inequality constructor"); + } + // cv, op, (cle || number) + } else if (a1IsVar && (a3IsExp || a3IsNum)) { + var cle = a3, op = a2, cv = a1, strength = a4, weight = a5; + lc.call(this, this._cloneOrNewCle(cle), strength, weight); + if (op == c.GEQ) { + this.expression.multiplyMe(-1); + this.expression.addVariable(cv); + } else if (op == c.LEQ) { + this.expression.addVariable(cv, -1); + } else { + throw new c.InternalError("Invalid operator in c.Inequality constructor"); + } + // cle, op, num + } else if (a1IsExp && a3IsNum) { + var cle1 = a1, op = a2, cle2 = a3, strength = a4, weight = a5; + lc.call(this, this._cloneOrNewCle(cle1), strength, weight); + if (op == c.LEQ) { + this.expression.multiplyMe(-1); + this.expression.addExpression(this._cloneOrNewCle(cle2)); + } else if (op == c.GEQ) { + this.expression.addExpression(this._cloneOrNewCle(cle2), -1); + } else { + throw new c.InternalError("Invalid operator in c.Inequality constructor"); + } + return this + // num, op, cle + } else if (a1IsNum && a3IsExp) { + var cle1 = a3, op = a2, cle2 = a1, strength = a4, weight = a5; + lc.call(this, this._cloneOrNewCle(cle1), strength, weight); + if (op == c.GEQ) { + this.expression.multiplyMe(-1); + this.expression.addExpression(this._cloneOrNewCle(cle2)); + } else if (op == c.LEQ) { + this.expression.addExpression(this._cloneOrNewCle(cle2), -1); + } else { + throw new c.InternalError("Invalid operator in c.Inequality constructor"); + } + return this + // cle op cle + } else if (a1IsExp && a3IsExp) { + var cle1 = a1, op = a2, cle2 = a3, strength = a4, weight = a5; + lc.call(this, this._cloneOrNewCle(cle2), strength, weight); + if (op == c.GEQ) { + this.expression.multiplyMe(-1); + this.expression.addExpression(this._cloneOrNewCle(cle1)); + } else if (op == c.LEQ) { + this.expression.addExpression(this._cloneOrNewCle(cle1), -1); + } else { + throw new c.InternalError("Invalid operator in c.Inequality constructor"); + } + // cle + } else if (a1IsExp) { + return lc.call(this, a1, a2, a3); + // >= + } else if (a2 == c.GEQ) { + lc.call(this, new c.Expression(a3), a4, a5); + this.expression.multiplyMe(-1); + this.expression.addVariable(a1); + // <= + } else if (a2 == c.LEQ) { + lc.call(this, new c.Expression(a3), a4, a5); + this.expression.addVariable(a1,-1); + // error + } else { + throw new c.InternalError("Invalid operator in c.Inequality constructor"); + } + }, + + isInequality: true, + + toString: function() { + // return "c.Inequality: " + this.hashCode; + return lc.prototype.toString.call(this) + " >= 0) id: " + this.hashCode; + }, +}); + +c.Equation = c.inherit({ + extends: c.Constraint, + initialize: function(a1, a2, a3, a4) { + // FIXME(slightlyoff): this is just a huge mess. + if (a1 instanceof c.Expression && !a2 || a2 instanceof c.Strength) { + lc.call(this, a1, a2, a3); + } else if ((a1 instanceof c.AbstractVariable) && + (a2 instanceof c.Expression)) { + + var cv = a1, cle = a2, strength = a3, weight = a4; + lc.call(this, cle.clone(), strength, weight); + this.expression.addVariable(cv, -1); + + } else if ((a1 instanceof c.AbstractVariable) && + (typeof(a2) == 'number')) { + + var cv = a1, val = a2, strength = a3, weight = a4; + lc.call(this, new c.Expression(val), strength, weight); + this.expression.addVariable(cv, -1); + + } else if ((a1 instanceof c.Expression) && + (a2 instanceof c.AbstractVariable)) { + + var cle = a1, cv = a2, strength = a3, weight = a4; + lc.call(this, cle.clone(), strength, weight); + this.expression.addVariable(cv, -1); + + } else if (((a1 instanceof c.Expression) || (a1 instanceof c.AbstractVariable) || + (typeof(a1) == 'number')) && + ((a2 instanceof c.Expression) || (a2 instanceof c.AbstractVariable) || + (typeof(a2) == 'number'))) { + + if (a1 instanceof c.Expression) { + a1 = a1.clone(); + } else { + a1 = new c.Expression(a1); + } + + if (a2 instanceof c.Expression) { + a2 = a2.clone(); + } else { + a2 = new c.Expression(a2); + } + lc.call(this, a1, a3, a4); + this.expression.addExpression(a2, -1); + + } else { + throw "Bad initializer to c.Equation"; + } + c.assert(this.strength instanceof c.Strength, "_strength not set"); + }, + + toString: function() { + return lc.prototype.toString.call(this) + " = 0)"; + }, +}); + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011, Alex Russell (slightlyoff@chromium.org) + +(function(c) { +"use strict"; + +c.EditInfo = c.inherit({ + initialize: function(cn /*c.Constraint*/, + eplus /*c.SlackVariable*/, + eminus /*c.SlackVariable*/, + prevEditConstant /*double*/, + i /*int*/) { + this.constraint = cn; + this.editPlus = eplus; + this.editMinus = eminus; + this.prevEditConstant = prevEditConstant; + this.index = i; + }, + toString: function() { + return ""; + } +}); + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011, Alex Russell (slightlyoff@chromium.org) + +(function(c) { +"use strict"; + +c.Tableau = c.inherit({ + initialize: function() { + // columns is a mapping from variables which occur in expressions to the + // set of basic variables whose expressions contain them + // i.e., it's a mapping from variables in expressions (a column) to the + // set of rows that contain them + this.columns = new c.HashTable(); // values are sets + + // _rows maps basic variables to the expressions for that row in the tableau + this.rows = new c.HashTable(); // values are c.Expressions + + // the collection of basic variables that have infeasible rows + // (used when reoptimizing) + this._infeasibleRows = new c.HashSet(); + + // the set of rows where the basic variable is external this was added to + // the C++ version to reduce time in setExternalVariables() + this._externalRows = new c.HashTable(); + }, + + // Variable v has been removed from an Expression. If the Expression is in a + // tableau the corresponding basic variable is subject (or if subject is nil + // then it's in the objective function). Update the column cross-indices. + noteRemovedVariable: function(v /*c.AbstractVariable*/, + subject /*c.AbstractVariable*/) { + var column = this.columns.get(v); + if (subject && column) { + column.delete(subject); + } + }, + + noteAddedVariable: function(v /*c.AbstractVariable*/, subject /*c.AbstractVariable*/) { + if (subject) { + this.insertColVar(v, subject); + } + }, + + getInternalInfo: function() { + return "Tableau Information:\n" + + "Rows: " + this.rows.size + + " (= " + (this.rows.size - 1) + " constraints)" + + "\nColumns: " + this.columns.size + + "\nInfeasible Rows: " + this._infeasibleRows.size + + "\nExternal basic variables: " + this._externalRows.size; + }, + + toString: function() { + var str = "Tableau:\n"; + this.rows.each(function(clv, expr) { + str += clv + " <==> " + expr + "\n"; + }); + str += "\nColumns:\n"; + str += this.columns; + str += "\nInfeasible rows: "; + str += this._infeasibleRows; + str += "External basic variables: "; + str += this._externalRows; + return str; + }, + + /* + toJSON: function() { + // Creates an object representation of the Tableau. + }, + */ + + // Convenience function to insert a variable into + // the set of rows stored at columns[param_var], + // creating a new set if needed + insertColVar: function(param_var /*c.Variable*/, + rowvar /*c.Variable*/) { + var rowset = /* Set */ this.columns.get(param_var); + if (!rowset) { + rowset = new c.HashSet(); + this.columns.set(param_var, rowset); + } + rowset.add(rowvar); + }, + + addRow: function(aVar /*c.AbstractVariable*/, + expr /*c.Expression*/) { + this.rows.set(aVar, expr); + expr.terms.each(function(clv, coeff) { + this.insertColVar(clv, aVar); + }, this); + if (aVar.isExternal) { + // console.log("addRow(): aVar is external:", aVar.name, aVar.hashCode); + this._externalRows.set(aVar, expr); + this._updatedExternals.add(aVar); + } + }, + + removeColumn: function(aVar /*c.AbstractVariable*/) { + var rows = /* Set */ this.columns.get(aVar); + if (rows) { + this.columns.delete(aVar); + rows.each(function(clv) { + var expr = /* c.Expression */this.rows.get(clv); + expr.terms.delete(aVar); + }, this); + /* + } else { + // console.log("Could not find var", aVar, "in columns"); + */ + } + if (aVar.isExternal) { + this._externalRows.delete(aVar); + } + }, + + removeRow: function(aVar /*c.AbstractVariable*/) { + var expr = /* c.Expression */this.rows.get(aVar); + c.assert(expr != null); + expr.terms.each(function(clv, coeff) { + var varset = this.columns.get(clv); + if (varset != null) { + varset.delete(aVar); + } + }, this); + this._infeasibleRows.delete(aVar); + if (aVar.isExternal) { + this._externalRows.delete(aVar); + } + this.rows.delete(aVar); + return expr; + }, + + substituteOut: function(oldVar /*c.AbstractVariable*/, + expr /*c.Expression*/) { + var varset = this.columns.get(oldVar); + varset.each(function(v) { + var row = this.rows.get(v); + row.substituteOut(oldVar, expr, v, this); + if (v.isExternal) { + this._updatedExternals.add(v); + } + if (v.isRestricted && row.constant < 0) { + this._infeasibleRows.add(v); + } + }, this); + + if (oldVar.isExternal) { + this._externalRows.set(oldVar, expr); + } + + this.columns.delete(oldVar); + }, + + columnsHasKey: function(subject /*c.AbstractVariable*/) { + return !!this.columns.get(subject); + }, +}); + +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011, Alex Russell (slightlyoff@chromium.org) + +(function(c) { +var t = c.Tableau; +var tp = t.prototype; +var epsilon = 1e-8; +var weak = c.Strength.weak; + +var _newExpressionInternalReturn = { + eplus: null, + eminus: null, + prevEConstant: null +}; + +c.SimplexSolver = c.inherit({ + extends: c.Tableau, + initialize: function(){ + + c.Tableau.call(this); + this._stayMinusErrorVars = []; + this._stayPlusErrorVars = []; + + this._errorVars = new c.HashTable(); // cn -> Set of cv + + this._markerVars = new c.HashTable(); // cn -> Set of cv + + // this._resolve_pair = [0, 0]; + this._objective = new c.ObjectiveVariable({ name: "Z" }); + + this._editVarMap = new c.HashTable(); // cv -> c.EditInfo + this._editVarList = []; + + this._slackCounter = 0; + this._artificialCounter = 0; + this._dummyCounter = 0; + this.autoSolve = true; + this._needsSolving = false; + + this._optimizeCount = 0; + + this.rows.set(this._objective, c.Expression.empty(this)); + this._editVariableStack = [0]; // Stack + this._updatedExternals = new c.HashSet(); + }, + + _noteUpdatedExternal: function(v, expr) { + this._updatedExternals.add(v); + }, + + add: function(/*c.Constraint, ...*/) { + for (var x = 0; x < arguments.length; x++) { + this.addConstraint(arguments[x]); + } + return this; + }, + + addEditVar: function(v /*c.Variable*/, strength /*c.Strength*/, weight /*double*/) { + var cn = new c.EditConstraint(v, strength||c.Strength.strong, weight); + this.addEditConstraint(cn); + return this; + }, + + addEditConstraint: function(cn) { + var ir = _newExpressionInternalReturn; + this.addConstraint(cn); + this._addEditConstraint(cn, ir.eplus, ir.eminus, ir.prevEConstant); + return this; + }, + + _addEditConstraint: function(cn, cvEplus, cvEminus, prevEConstant) { + var i = this._editVarMap.size; + var ei = new c.EditInfo(cn, cvEplus, cvEminus, prevEConstant, i); + this._editVarMap.set(cn.variable, ei); + this._editVarList[i] = { v: cn.variable, info: ei }; + }, + + addConstraint: function(cn /*c.Constraint*/) { + if (cn instanceof c.Constraint) { + // FIXME(slightlyoff): this sucks. They might not all be updated. + var self = this; + cn.expression.externalVariables.each( + // FIXME(slightlyoff): required? + function(v) { self._noteUpdatedExternal(v); } + ); + } + var expr = this.newExpression(cn); + expr.solver = this; + + if (!this.tryAddingDirectly(expr)) { + this.addWithArtificialVariable(expr); + } + + this._needsSolving = true; + if (this.autoSolve) { + this.optimize(this._objective); + this._setExternalVariables(); + } + return this; + }, + + addConstraintNoException: function(cn /*c.Constraint*/) { + // FIXME(slightlyoff): change this to enable chaining + try { + this.addConstraint(cn); + return true; + } catch (e /*c.RequiredFailure*/){ + console.error(e); + return false; + } + }, + + beginEdit: function() { + // FIXME(slightlyoff): we shouldn't throw here. Log instead + c.assert(this._editVarMap.size > 0, "_editVarMap.size > 0"); + this._infeasibleRows.clear(); + this._resetStayConstants(); + this._editVariableStack[this._editVariableStack.length] = this._editVarMap.size; + return this; + }, + + endEdit: function() { + // FIXME(slightlyoff): we shouldn't throw here. Log instead + c.assert(this._editVarMap.size > 0, "_editVarMap.size > 0"); + this.resolve(); + this._editVariableStack.pop(); + this.removeEditVarsTo( + this._editVariableStack[this._editVariableStack.length - 1] + ); + return this; + }, + + removeAllEditVars: function() { + return this.removeEditVarsTo(0); + }, + + removeEditVarsTo: function(n /*int*/) { + try { + var evll = this._editVarList.length; + // only remove the variable if it's not in the set of variable + // from a previous nested outer edit + // e.g., if I do: + // Edit x,y + // Edit w,h,x,y + // EndEdit + // The end edit needs to only get rid of the edits on w,h + // not the ones on x,y + for(var x = n; x < evll; x++) { + if (this._editVarList[x]) { + this.removeConstraint( + this._editVarMap.get(this._editVarList[x].v).constraint + ); + } + } + this._editVarList.length = n; + c.assert(this._editVarMap.size == n, "_editVarMap.size == n"); + return this; + } catch (e /*ConstraintNotFound*/){ + throw new c.InternalError("Constraint not found in removeEditVarsTo"); + } + }, + + // Add weak stays to the x and y parts of each point. These have + // increasing weights so that the solver will try to satisfy the x + // and y stays on the same point, rather than the x stay on one and + // the y stay on another. + addPointStays: function(points /*[{ x: .., y: ..}, ...]*/) { + points.forEach(function(p, idx) { + this.addStay(p.x, weak, Math.pow(2, idx)); + this.addStay(p.y, weak, Math.pow(2, idx)); + }, this); + return this; + }, + + addStay: function(v /*c.Variable*/, strength /*c.Strength*/, weight /*double*/) { + var cn = new c.StayConstraint(v, + strength || weak, + weight || 1); + return this.addConstraint(cn); + }, + + + setConstant: function(cn, constant) { + this._setConstant(cn, constant); + this.resolve(); + }, + + /* + void simplex_solver::set_constant_(const constraint& c, double constant) + { + auto found = constraints_.find(c); + if (found == constraints_.end()) + throw constraint_not_found(); + + auto& evs = found->second; + auto delta = -(constant - evs.prev_constant); + evs.prev_constant = constant; + + if (evs.marker.is_slack() || c.is_required()) { + if (c.oper().type() == relation::geq) + delta = -delta; + + for (auto& r : rows_) { + auto& expr = r.second; + expr.add(expr.coefficient(evs.marker) * delta); + if (!r.first.is_external() && expr.constant() < 0.0) + infeasible_rows_.emplace_back(r.first); + } + } else { + // Check if the error variables are basic. + auto row_it = rows_.find(evs.marker); + if (row_it != rows_.end()) { + if (row_it->second.add(-delta) < 0.0) + infeasible_rows_.emplace_back(row_it->first); + + return; + } + + row_it = rows_.find(evs.other); + if (row_it != rows_.end()) { + if (row_it->second.add(delta) < 0.0) + infeasible_rows_.emplace_back(row_it->first); + + return; + } + + // Neither is basic. So they must both be nonbasic, and will both + // occur in exactly the same expressions. Find all the expressions + // in which they occur by finding the column for the minusErrorVar + // (it doesn't matter whether we look for that one or for + // plusErrorVar). Fix the constants in these expressions. + for (auto& r : rows_) { + auto& expr = r.second; + expr.add(expr.coefficient(evs.other) * delta); + if (!r.first.is_external() && expr.constant() < 0.0) + infeasible_rows_.emplace_back(r.first); + } + } + } + */ + + // FIXME(slightlyoff): add a removeStay + + removeConstraint: function(cn /*c.Constraint*/) { + // console.log("removeConstraint('", cn, "')"); + this._needsSolving = true; + this._resetStayConstants(); + var zRow = this.rows.get(this._objective); + var eVars = /* Set */this._errorVars.get(cn); + if (eVars != null) { + eVars.each(function(cv) { + var expr = this.rows.get(cv); + if (expr == null) { + zRow.addVariable(cv, + -cn.weight * cn.strength.symbolicWeight.value, + this._objective, + this); + } else { + zRow.addExpression(expr, + -cn.weight * cn.strength.symbolicWeight.value, + this._objective, + this); + } + }, this); + } + var marker = this._markerVars.get(cn); + this._markerVars.delete(cn); + if (marker == null) { + throw new c.InternalError("Constraint not found in removeConstraintInternal"); + } + if (this.rows.get(marker) == null) { + var col = this.columns.get(marker); + // console.log("col is:", col, "from marker:", marker); + var exitVar = null; + var minRatio = 0; + col.each(function(v) { + if (v.isRestricted) { + var expr = this.rows.get(v); + var coeff = expr.coefficientFor(marker); + if (coeff < 0) { + var r = -expr.constant / coeff; + if ( + exitVar == null || + r < minRatio || + (c.approx(r, minRatio) && v.hashCode < exitVar.hashCode) + ) { + minRatio = r; + exitVar = v; + } + } + } + }, this); + if (exitVar == null) { + col.each(function(v) { + if (v.isRestricted) { + var expr = this.rows.get(v); + var coeff = expr.coefficientFor(marker); + var r = expr.constant / coeff; + if (exitVar == null || r < minRatio) { + minRatio = r; + exitVar = v; + } + } + }, this); + } + if (exitVar == null) { + if (col.size == 0) { + this.removeColumn(marker); + } else { + col.escapingEach(function(v) { + if (v != this._objective) { + exitVar = v; + return { brk: true }; + } + }, this); + } + } + if (exitVar != null) { + this.pivot(marker, exitVar); + } + } + if (this.rows.get(marker) != null) { + var expr = this.removeRow(marker); + } + + if (eVars != null) { + eVars.each(function(v) { + if (v != marker) { this.removeColumn(v); } + }, this); + } + + if (cn.isStay) { + if (eVars != null) { + for (var i = 0; i < this._stayPlusErrorVars.length; i++) { + eVars.delete(this._stayPlusErrorVars[i]); + eVars.delete(this._stayMinusErrorVars[i]); + } + } + } else if (cn.isEdit) { + // c.assert(eVars != null, "eVars != null"); + var cei = this._editVarMap.get(cn.variable); + this.removeColumn(cei.editMinus); + this._editVarMap.delete(cn.variable); + } + + if (eVars != null) { + this._errorVars.delete(eVars); + } + + if (this.autoSolve) { + this.optimize(this._objective); + this._setExternalVariables(); + } + + return this; + }, + + reset: function() { + throw new c.InternalError("reset not implemented"); + }, + + resolveArray: function(newEditConstants) { + var l = newEditConstants.length + this._editVarMap.each(function(v, cei) { + var i = cei.index; + if (i < l) + this.suggestValue(v, newEditConstants[i]); + }, this); + this.resolve(); + }, + + resolvePair: function(x /*double*/, y /*double*/) { + this.suggestValue(this._editVarList[0].v, x); + this.suggestValue(this._editVarList[1].v, y); + this.resolve(); + }, + + resolve: function() { + this.dualOptimize(); + this._setExternalVariables(); + this._infeasibleRows.clear(); + this._resetStayConstants(); + }, + + suggestValue: function(v /*c.Variable*/, x /*double*/) { + var cei = this._editVarMap.get(v); + if (!cei) { + throw new c.Error("suggestValue for variable " + v + ", but var is not an edit variable"); + } + var delta = x - cei.prevEditConstant; + cei.prevEditConstant = x; + this.deltaEditConstant(delta, cei.editPlus, cei.editMinus); + return this; + }, + + solve: function() { + if (this._needsSolving) { + this.optimize(this._objective); + this._setExternalVariables(); + } + return this; + }, + + setEditedValue: function(v /*c.Variable*/, n /*double*/) { + if (!(this.columnsHasKey(v) || (this.rows.get(v) != null))) { + v.value = n; + return this; + } + + if (!c.approx(n, v.value)) { + this.addEditVar(v); + this.beginEdit(); + + try { + this.suggestValue(v, n); + } catch (e) { + throw new c.InternalError("Error in setEditedValue"); + } + + this.endEdit(); + } + return this; + }, + + addVar: function(v /*c.Variable*/) { + if (!(this.columnsHasKey(v) || (this.rows.get(v) != null))) { + try { + this.addStay(v); + } catch (e /*c.RequiredFailure*/){ + throw new c.InternalError("Error in addVar -- required failure is impossible"); + } + } + return this; + }, + + getInternalInfo: function() { + var retstr = tp.getInternalInfo.call(this); + retstr += "\nSolver info:\n"; + retstr += "Stay Error Variables: "; + retstr += this._stayPlusErrorVars.length + this._stayMinusErrorVars.length; + retstr += " (" + this._stayPlusErrorVars.length + " +, "; + retstr += this._stayMinusErrorVars.length + " -)\n"; + retstr += "Edit Variables: " + this._editVarMap.size; + retstr += "\n"; + return retstr; + }, + + getDebugInfo: function() { + return this.toString() + this.getInternalInfo() + "\n"; + }, + + toString: function() { + var bstr = tp.getInternalInfo.call(this); + bstr += "\n_stayPlusErrorVars: "; + bstr += '[' + this._stayPlusErrorVars + ']'; + bstr += "\n_stayMinusErrorVars: "; + bstr += '[' + this._stayMinusErrorVars + ']'; + bstr += "\n"; + bstr += "_editVarMap:\n" + this._editVarMap; + bstr += "\n"; + return bstr; + }, + + addWithArtificialVariable: function(expr /*c.Expression*/) { + var av = new c.SlackVariable({ + value: ++this._artificialCounter, + prefix: "a" + }); + var az = new c.ObjectiveVariable({ name: "az" }); + var azRow = /* c.Expression */expr.clone(); + this.addRow(az, azRow); + this.addRow(av, expr); + this.optimize(az); + var azTableauRow = this.rows.get(az); + if (!c.approx(azTableauRow.constant, 0)) { + this.removeRow(az); + this.removeColumn(av); + throw new c.RequiredFailure(); + } + var e = this.rows.get(av); + if (e != null) { + if (e.isConstant) { + this.removeRow(av); + this.removeRow(az); + return; + } + var entryVar = e.anyPivotableVariable(); + this.pivot(entryVar, av); + } + c.assert(this.rows.get(av) == null, "rowExpression(av) == null"); + this.removeColumn(av); + this.removeRow(az); + }, + + tryAddingDirectly: function(expr /*c.Expression*/) { + var subject = this.chooseSubject(expr); + if (subject == null) { + return false; + } + expr.newSubject(subject); + if (this.columnsHasKey(subject)) { + this.substituteOut(subject, expr); + } + this.addRow(subject, expr); + return true; + }, + + chooseSubject: function(expr /*c.Expression*/) { + var subject = null; + var foundUnrestricted = false; + var foundNewRestricted = false; + var terms = expr.terms; + var rv = terms.escapingEach(function(v, c) { + if (foundUnrestricted) { + if (!v.isRestricted) { + if (!this.columnsHasKey(v)) { + return { retval: v }; + } + } + } else { + if (v.isRestricted) { + if (!foundNewRestricted && !v.isDummy && c < 0) { + var col = this.columns.get(v); + if (col == null || + (col.size == 1 && this.columnsHasKey(this._objective)) + ) { + subject = v; + foundNewRestricted = true; + } + } + } else { + subject = v; + foundUnrestricted = true; + } + } + }, this); + if (rv && rv.retval !== undefined) { + return rv.retval; + } + + if (subject != null) { + return subject; + } + + var coeff = 0; + + // subject is nil. + // Make one last check -- if all of the variables in expr are dummy + // variables, then we can pick a dummy variable as the subject + var rv = terms.escapingEach(function(v,c) { + if (!v.isDummy) { + return {retval:null}; + } + if (!this.columnsHasKey(v)) { + subject = v; + coeff = c; + } + }, this); + if (rv && rv.retval !== undefined) return rv.retval; + + if (!c.approx(expr.constant, 0)) { + throw new c.RequiredFailure(); + } + if (coeff > 0) { + expr.multiplyMe(-1); + } + return subject; + }, + + deltaEditConstant: function(delta /*double*/, + plusErrorVar /*c.AbstractVariable*/, + minusErrorVar /*c.AbstractVariable*/) { + var exprPlus = this.rows.get(plusErrorVar); + if (exprPlus != null) { + exprPlus.constant += delta; + if (exprPlus.constant < 0) { + this._infeasibleRows.add(plusErrorVar); + } + return; + } + var exprMinus = this.rows.get(minusErrorVar); + if (exprMinus != null) { + exprMinus.constant += -delta; + if (exprMinus.constant < 0) { + this._infeasibleRows.add(minusErrorVar); + } + return; + } + var columnVars = this.columns.get(minusErrorVar); + if (!columnVars) { + console.log("columnVars is null -- tableau is:\n" + this); + } + columnVars.each(function(basicVar) { + var expr = this.rows.get(basicVar); + var c = expr.coefficientFor(minusErrorVar); + expr.constant += (c * delta); + if (basicVar.isExternal) { + this._noteUpdatedExternal(basicVar); + } + if (basicVar.isRestricted && expr.constant < 0) { + this._infeasibleRows.add(basicVar); + } + }, this); + }, + + // We have set new values for the constants in the edit constraints. + // Re-Optimize using the dual simplex algorithm. + dualOptimize: function() { + var zRow = this.rows.get(this._objective); + // need to handle infeasible rows + while (this._infeasibleRows.size) { + var exitVar = this._infeasibleRows.values()[0]; + this._infeasibleRows.delete(exitVar); + var entryVar = null; + var expr = this.rows.get(exitVar); + // exitVar might have become basic after some other pivoting + // so allow for the case of its not being there any longer + if (expr) { + if (expr.constant < 0) { + var ratio = Number.MAX_VALUE; + var r; + var terms = expr.terms; + terms.each(function(v, cd) { + if (cd > 0 && v.isPivotable) { + var zc = zRow.coefficientFor(v); + r = zc / cd; + if (r < ratio || + (c.approx(r, ratio) && v.hashCode < entryVar.hashCode) + ) { + entryVar = v; + ratio = r; + } + } + }); + if (ratio == Number.MAX_VALUE) { + throw new c.InternalError("ratio == nil (MAX_VALUE) in dualOptimize"); + } + this.pivot(entryVar, exitVar); + } + } + } + }, + + // Make a new linear Expression representing the constraint cn, + // replacing any basic variables with their defining expressions. + // Normalize if necessary so that the Constant is non-negative. If + // the constraint is non-required give its error variables an + // appropriate weight in the objective function. + newExpression: function(cn /*c.Constraint*/) { + var ir = _newExpressionInternalReturn; + ir.eplus = null; + ir.eminus = null; + ir.prevEConstant = null; + + var cnExpr = cn.expression; + var expr = c.Expression.fromConstant(cnExpr.constant, this); + var slackVar = new c.SlackVariable(); + var dummyVar = new c.DummyVariable(); + var eminus = new c.SlackVariable(); + var eplus = new c.SlackVariable(); + var cnTerms = cnExpr.terms; + + // FIXME(slightlyoff): slow!! + cnTerms.each(function(v, c) { + var e = this.rows.get(v); + if (!e) { + expr.addVariable(v, c); + } else { + expr.addExpression(e, c); + } + }, this); + + if (cn.isInequality) { + // cn is an inequality, so Add a slack variable. The original constraint + // is expr>=0, so that the resulting equality is expr-slackVar=0. If cn is + // also non-required Add a negative error variable, giving: + // + // expr - slackVar = -errorVar + // + // in other words: + // + // expr - slackVar + errorVar = 0 + // + // Since both of these variables are newly created we can just Add + // them to the Expression (they can't be basic). + ++this._slackCounter; + slackVar = new c.SlackVariable({ + value: this._slackCounter, + prefix: "s" + }); + expr.setVariable(slackVar, -1); + + this._markerVars.set(cn, slackVar); + if (!cn.required) { + ++this._slackCounter; + eminus = new c.SlackVariable({ + value: this._slackCounter, + prefix: "em" + }); + expr.setVariable(eminus, 1); + var zRow = this.rows.get(this._objective); + zRow.setVariable(eminus, cn.strength.symbolicWeight.value * cn.weight); + this.insertErrorVar(cn, eminus); + this.noteAddedVariable(eminus, this._objective); + } + } else { + if (cn.required) { + // Add a dummy variable to the Expression to serve as a marker for this + // constraint. The dummy variable is never allowed to enter the basis + // when pivoting. + ++this._dummyCounter; + dummyVar = new c.DummyVariable({ + value: this._dummyCounter, + prefix: "d" + }); + ir.eplus = dummyVar; + ir.eminus = dummyVar; + ir.prevEConstant = cnExpr.constant; + expr.setVariable(dummyVar, 1); + this._markerVars.set(cn, dummyVar); + } else { + // cn is a non-required equality. Add a positive and a negative error + // variable, making the resulting constraint + // expr = eplus - eminus + // in other words: + // expr - eplus + eminus = 0 + ++this._slackCounter; + eplus = new c.SlackVariable({ + value: this._slackCounter, + prefix: "ep" + }); + eminus = new c.SlackVariable({ + value: this._slackCounter, + prefix: "em" + }); + expr.setVariable(eplus, -1); + expr.setVariable(eminus, 1); + this._markerVars.set(cn, eplus); + var zRow = this.rows.get(this._objective); + var swCoeff = cn.strength.symbolicWeight.value * cn.weight; + + zRow.setVariable(eplus, swCoeff); + this.noteAddedVariable(eplus, this._objective); + zRow.setVariable(eminus, swCoeff); + this.noteAddedVariable(eminus, this._objective); + + this.insertErrorVar(cn, eminus); + this.insertErrorVar(cn, eplus); + + if (cn.isStay) { + this._stayPlusErrorVars[this._stayPlusErrorVars.length] = eplus; + this._stayMinusErrorVars[this._stayMinusErrorVars.length] = eminus; + } else if (cn.isEdit) { + ir.eplus = eplus; + ir.eminus = eminus; + ir.prevEConstant = cnExpr.constant; + } + } + } + // the Constant in the Expression should be non-negative. If necessary + // normalize the Expression by multiplying by -1 + if (expr.constant < 0) expr.multiplyMe(-1); + return expr; + }, + + // Minimize the value of the objective. (The tableau should already be + // feasible.) + optimize: function(zVar /*c.ObjectiveVariable*/) { + this._optimizeCount++; + + var zRow = this.rows.get(zVar); + c.assert(zRow != null, "zRow != null"); + var entryVar = null; + var exitVar = null; + var objectiveCoeff, terms; + + while (true) { + objectiveCoeff = 0; + terms = zRow.terms; + + // Find the most negative coefficient in the objective function (ignoring + // the non-pivotable dummy variables). If all coefficients are positive + // we're done + terms.escapingEach(function(v, c) { + if (v.isPivotable && c < objectiveCoeff) { + objectiveCoeff = c; + entryVar = v; + // Break on success + return { brk: 1 }; + } + }, this); + + if (objectiveCoeff >= -epsilon) { + return; + } + + // choose which variable to move out of the basis + // Only consider pivotable basic variables + // (i.e. restricted, non-dummy variables) + var minRatio = Number.MAX_VALUE; + var columnVars = this.columns.get(entryVar); + var r = 0; + + columnVars.each(function(v) { + if (v.isPivotable) { + var expr = this.rows.get(v); + var coeff = expr.coefficientFor(entryVar); + // only consider negative coefficients + if (coeff < 0) { + r = -expr.constant / coeff; + // Bland's anti-cycling rule: + // if multiple variables are about the same, + // always pick the lowest via some total + // ordering -- I use their addresses in memory + // if (r < minRatio || + // (c.approx(r, minRatio) && + // v.get_pclv() < exitVar.get_pclv())) + if (r < minRatio || + (c.approx(r, minRatio) && + v.hashCode < exitVar.hashCode) + ) { + minRatio = r; + exitVar = v; + } + } + } + }, this); + + // If minRatio is still nil at this point, it means that the + // objective function is unbounded, i.e. it can become + // arbitrarily negative. This should never happen in this + // application. + if (minRatio == Number.MAX_VALUE) { + throw new c.InternalError("Objective function is unbounded in optimize"); + } + + // console.time("SimplexSolver::optimize pivot()"); + this.pivot(entryVar, exitVar); + // console.timeEnd("SimplexSolver::optimize pivot()"); + } + }, + + // Do a Pivot. Move entryVar into the basis (i.e. make it a basic variable), + // and move exitVar out of the basis (i.e., make it a parametric variable) + pivot: function(entryVar /*c.AbstractVariable*/, exitVar /*c.AbstractVariable*/) { + var time = false; + time && console.time(" SimplexSolver::pivot"); + + // the entryVar might be non-pivotable if we're doing a RemoveConstraint -- + // otherwise it should be a pivotable variable -- enforced at call sites, + // hopefully + if (entryVar == null) { + console.warn("pivot: entryVar == null"); + } + + if (exitVar == null) { + console.warn("pivot: exitVar == null"); + } + // console.log("SimplexSolver::pivot(", entryVar, exitVar, ")") + + // expr is the Expression for the exit variable (about to leave the basis) -- + // so that the old tableau includes the equation: + // exitVar = expr + time && console.time(" removeRow"); + var expr = this.removeRow(exitVar); + time && console.timeEnd(" removeRow"); + + // Compute an Expression for the entry variable. Since expr has + // been deleted from the tableau we can destructively modify it to + // build this Expression. + time && console.time(" changeSubject"); + expr.changeSubject(exitVar, entryVar); + time && console.timeEnd(" changeSubject"); + + time && console.time(" substituteOut"); + this.substituteOut(entryVar, expr); + time && console.timeEnd(" substituteOut"); + + time && console.time(" addRow") + this.addRow(entryVar, expr); + time && console.timeEnd(" addRow") + + time && console.timeEnd(" SimplexSolver::pivot"); + }, + + // Each of the non-required stays will be represented by an equation + // of the form + // v = c + eplus - eminus + // where v is the variable with the stay, c is the previous value of + // v, and eplus and eminus are slack variables that hold the error + // in satisfying the stay constraint. We are about to change + // something, and we want to fix the constants in the equations + // representing the stays. If both eplus and eminus are nonbasic + // they have value 0 in the current solution, meaning the previous + // stay was exactly satisfied. In this case nothing needs to be + // changed. Otherwise one of them is basic, and the other must + // occur only in the Expression for that basic error variable. + // Reset the Constant in this Expression to 0. + _resetStayConstants: function() { + var spev = this._stayPlusErrorVars; + var l = spev.length; + for (var i = 0; i < l; i++) { + var expr = this.rows.get(spev[i]); + if (expr === null) { + expr = this.rows.get(this._stayMinusErrorVars[i]); + } + if (expr != null) { + expr.constant = 0; + } + } + }, + + _setExternalVariables: function() { + var changes = []; + this._updatedExternals.each(function(v) { + // console.log("got updated", v.name, v.hashCode); + var iv = v.value; + // var expr = this._externalRows.get(v); + var expr = this._externalRows.get(v); + if (!expr) { + v.value = 0; + return; + } + v.value = expr.constant; + if (iv !== v.value) { + // console.log(v.name, iv, "-->", v.value, iv === v.value); + changes.push({ + type: "update", + name: v.name, + variable: v, + oldValue: iv + }); + } + }, this); + + this._updatedExternals.clear(); + this._needsSolving = false; + this._informCallbacks(changes); + if (changes.length) { + this.onsolved(changes); + } + // console.log(" --"); + }, + + onsolved: function() { + // Lifecycle stub. Here for dirty, dirty monkey patching. + }, + + _informCallbacks: function(changes) { + if(!this._callbacks) return; + + this._callbacks.forEach(function(fn) { + fn(changes); + }); + }, + + _addCallback: function(fn) { + var a = (this._callbacks || (this._callbacks = [])); + a[a.length] = fn; + }, + + insertErrorVar: function(cn /*c.Constraint*/, aVar /*c.AbstractVariable*/) { + var constraintSet = /* Set */this._errorVars.get(cn); + if (!constraintSet) { + constraintSet = new c.HashSet(); + this._errorVars.set(cn, constraintSet); + } + constraintSet.add(aVar); + }, +}); +})(this["c"]||module.parent.exports||{}); +// Copyright (C) 1998-2000 Greg J. Badros +// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0 +// +// Parts Copyright (C) 2011, Alex Russell (slightlyoff@chromium.org) + +(function(c) { +"use strict"; + +c.Timer = c.inherit({ + initialize: function() { + this.isRunning = false; + this._elapsedMs = 0; + }, + + start: function() { + this.isRunning = true; + this._startReading = new Date(); + return this; + }, + + stop: function() { + this.isRunning = false; + this._elapsedMs += (new Date()) - this._startReading; + return this; + }, + + reset: function() { + this.isRunning = false; + this._elapsedMs = 0; + return this; + }, + + elapsedTime : function() { + if (!this.isRunning) { + return this._elapsedMs / 1000; + } else { + return (this._elapsedMs + (new Date() - this._startReading)) / 1000; + } + }, +}); + +})(this["c"]||module.parent.exports||{}); +this.c.parser = (function(){ + /* + * Generated by PEG.js 0.7.0. + * + * http://pegjs.majda.cz/ + */ + + function quote(s) { + /* + * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a + * string literal except for the closing quote character, backslash, + * carriage return, line separator, paragraph separator, and line feed. + * Any character may appear in the form of an escape sequence. + * + * For portability, we also escape escape all control and non-ASCII + * characters. Note that "\0" and "\v" escape sequences are not used + * because JSHint does not like the first and IE the second. + */ + return '"' + s + .replace(/\\/g, '\\\\') // backslash + .replace(/"/g, '\\"') // closing quote character + .replace(/\x08/g, '\\b') // backspace + .replace(/\t/g, '\\t') // horizontal tab + .replace(/\n/g, '\\n') // line feed + .replace(/\f/g, '\\f') // form feed + .replace(/\r/g, '\\r') // carriage return + .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape) + + '"'; + } + + var result = { + /* + * Parses the input with a generated parser. If the parsing is successfull, + * returns a value explicitly or implicitly specified by the grammar from + * which the parser was generated (see |PEG.buildParser|). If the parsing is + * unsuccessful, throws |PEG.parser.SyntaxError| describing the error. + */ + parse: function(input, startRule) { + var parseFunctions = { + "start": parse_start, + "Statement": parse_Statement, + "SourceCharacter": parse_SourceCharacter, + "IdentifierStart": parse_IdentifierStart, + "IdentifierPart": parse_IdentifierPart, + "WhiteSpace": parse_WhiteSpace, + "LineTerminator": parse_LineTerminator, + "LineTerminatorSequence": parse_LineTerminatorSequence, + "EOS": parse_EOS, + "EOF": parse_EOF, + "Comment": parse_Comment, + "MultiLineComment": parse_MultiLineComment, + "MultiLineCommentNoLineTerminator": parse_MultiLineCommentNoLineTerminator, + "SingleLineComment": parse_SingleLineComment, + "_": parse__, + "__": parse___, + "Literal": parse_Literal, + "Integer": parse_Integer, + "Real": parse_Real, + "SignedInteger": parse_SignedInteger, + "Identifier": parse_Identifier, + "IdentifierName": parse_IdentifierName, + "PrimaryExpression": parse_PrimaryExpression, + "UnaryExpression": parse_UnaryExpression, + "UnaryOperator": parse_UnaryOperator, + "MultiplicativeExpression": parse_MultiplicativeExpression, + "MultiplicativeOperator": parse_MultiplicativeOperator, + "AdditiveExpression": parse_AdditiveExpression, + "AdditiveOperator": parse_AdditiveOperator, + "InequalityExpression": parse_InequalityExpression, + "InequalityOperator": parse_InequalityOperator, + "LinearExpression": parse_LinearExpression + }; + + if (startRule !== undefined) { + if (parseFunctions[startRule] === undefined) { + throw new Error("Invalid rule name: " + quote(startRule) + "."); + } + } else { + startRule = "start"; + } + + var pos = 0; + var reportFailures = 0; + var rightmostFailuresPos = 0; + var rightmostFailuresExpected = []; + + function padLeft(input, padding, length) { + var result = input; + + var padLength = length - input.length; + for (var i = 0; i < padLength; i++) { + result = padding + result; + } + + return result; + } + + function escape(ch) { + var charCode = ch.charCodeAt(0); + var escapeChar; + var length; + + if (charCode <= 0xFF) { + escapeChar = 'x'; + length = 2; + } else { + escapeChar = 'u'; + length = 4; + } + + return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length); + } + + function matchFailed(failure) { + if (pos < rightmostFailuresPos) { + return; + } + + if (pos > rightmostFailuresPos) { + rightmostFailuresPos = pos; + rightmostFailuresExpected = []; + } + + rightmostFailuresExpected.push(failure); + } + + function parse_start() { + var result0, result1, result2; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse___(); + if (result0 !== null) { + result1 = []; + result2 = parse_Statement(); + while (result2 !== null) { + result1.push(result2); + result2 = parse_Statement(); + } + if (result1 !== null) { + result2 = parse___(); + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, statements) { return statements; })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_Statement() { + var result0, result1; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse_LinearExpression(); + if (result0 !== null) { + result1 = parse_EOS(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, expression) { return expression; })(pos0, result0[0]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_SourceCharacter() { + var result0; + + if (input.length > pos) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + return result0; + } + + function parse_IdentifierStart() { + var result0; + + if (/^[a-zA-Z]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z]"); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 36) { + result0 = "$"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"$\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 95) { + result0 = "_"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"_\""); + } + } + } + } + return result0; + } + + function parse_IdentifierPart() { + var result0; + + result0 = parse_IdentifierStart(); + if (result0 === null) { + if (/^[0-9]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + return result0; + } + + function parse_WhiteSpace() { + var result0; + + reportFailures++; + if (/^[\t\x0B\f \xA0\uFEFF]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[\\t\\x0B\\f \\xA0\\uFEFF]"); + } + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("whitespace"); + } + return result0; + } + + function parse_LineTerminator() { + var result0; + + if (/^[\n\r\u2028\u2029]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[\\n\\r\\u2028\\u2029]"); + } + } + return result0; + } + + function parse_LineTerminatorSequence() { + var result0; + + reportFailures++; + if (input.charCodeAt(pos) === 10) { + result0 = "\n"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\n\""); + } + } + if (result0 === null) { + if (input.substr(pos, 2) === "\r\n") { + result0 = "\r\n"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\r\\n\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 13) { + result0 = "\r"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\r\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 8232) { + result0 = "\u2028"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\u2028\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 8233) { + result0 = "\u2029"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\u2029\""); + } + } + } + } + } + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("end of line"); + } + return result0; + } + + function parse_EOS() { + var result0, result1; + var pos0; + + pos0 = pos; + result0 = parse___(); + if (result0 !== null) { + if (input.charCodeAt(pos) === 59) { + result1 = ";"; + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\";\""); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + result0 = parse__(); + if (result0 !== null) { + result1 = parse_LineTerminatorSequence(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + result0 = parse___(); + if (result0 !== null) { + result1 = parse_EOF(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + } + } + return result0; + } + + function parse_EOF() { + var result0; + var pos0; + + pos0 = pos; + reportFailures++; + if (input.length > pos) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + reportFailures--; + if (result0 === null) { + result0 = ""; + } else { + result0 = null; + pos = pos0; + } + return result0; + } + + function parse_Comment() { + var result0; + + reportFailures++; + result0 = parse_MultiLineComment(); + if (result0 === null) { + result0 = parse_SingleLineComment(); + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("comment"); + } + return result0; + } + + function parse_MultiLineComment() { + var result0, result1, result2, result3; + var pos0, pos1, pos2; + + pos0 = pos; + if (input.substr(pos, 2) === "/*") { + result0 = "/*"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"/*\""); + } + } + if (result0 !== null) { + result1 = []; + pos1 = pos; + pos2 = pos; + reportFailures++; + if (input.substr(pos, 2) === "*/") { + result2 = "*/"; + pos += 2; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = pos2; + } + if (result2 !== null) { + result3 = parse_SourceCharacter(); + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = pos1; + } + } else { + result2 = null; + pos = pos1; + } + while (result2 !== null) { + result1.push(result2); + pos1 = pos; + pos2 = pos; + reportFailures++; + if (input.substr(pos, 2) === "*/") { + result2 = "*/"; + pos += 2; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = pos2; + } + if (result2 !== null) { + result3 = parse_SourceCharacter(); + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = pos1; + } + } else { + result2 = null; + pos = pos1; + } + } + if (result1 !== null) { + if (input.substr(pos, 2) === "*/") { + result2 = "*/"; + pos += 2; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + return result0; + } + + function parse_MultiLineCommentNoLineTerminator() { + var result0, result1, result2, result3; + var pos0, pos1, pos2; + + pos0 = pos; + if (input.substr(pos, 2) === "/*") { + result0 = "/*"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"/*\""); + } + } + if (result0 !== null) { + result1 = []; + pos1 = pos; + pos2 = pos; + reportFailures++; + if (input.substr(pos, 2) === "*/") { + result2 = "*/"; + pos += 2; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + if (result2 === null) { + result2 = parse_LineTerminator(); + } + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = pos2; + } + if (result2 !== null) { + result3 = parse_SourceCharacter(); + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = pos1; + } + } else { + result2 = null; + pos = pos1; + } + while (result2 !== null) { + result1.push(result2); + pos1 = pos; + pos2 = pos; + reportFailures++; + if (input.substr(pos, 2) === "*/") { + result2 = "*/"; + pos += 2; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + if (result2 === null) { + result2 = parse_LineTerminator(); + } + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = pos2; + } + if (result2 !== null) { + result3 = parse_SourceCharacter(); + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = pos1; + } + } else { + result2 = null; + pos = pos1; + } + } + if (result1 !== null) { + if (input.substr(pos, 2) === "*/") { + result2 = "*/"; + pos += 2; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + return result0; + } + + function parse_SingleLineComment() { + var result0, result1, result2, result3; + var pos0, pos1, pos2; + + pos0 = pos; + if (input.substr(pos, 2) === "//") { + result0 = "//"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"//\""); + } + } + if (result0 !== null) { + result1 = []; + pos1 = pos; + pos2 = pos; + reportFailures++; + result2 = parse_LineTerminator(); + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = pos2; + } + if (result2 !== null) { + result3 = parse_SourceCharacter(); + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = pos1; + } + } else { + result2 = null; + pos = pos1; + } + while (result2 !== null) { + result1.push(result2); + pos1 = pos; + pos2 = pos; + reportFailures++; + result2 = parse_LineTerminator(); + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = pos2; + } + if (result2 !== null) { + result3 = parse_SourceCharacter(); + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = pos1; + } + } else { + result2 = null; + pos = pos1; + } + } + if (result1 !== null) { + result2 = parse_LineTerminator(); + if (result2 === null) { + result2 = parse_EOF(); + } + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + return result0; + } + + function parse__() { + var result0, result1; + + result0 = []; + result1 = parse_WhiteSpace(); + if (result1 === null) { + result1 = parse_MultiLineCommentNoLineTerminator(); + if (result1 === null) { + result1 = parse_SingleLineComment(); + } + } + while (result1 !== null) { + result0.push(result1); + result1 = parse_WhiteSpace(); + if (result1 === null) { + result1 = parse_MultiLineCommentNoLineTerminator(); + if (result1 === null) { + result1 = parse_SingleLineComment(); + } + } + } + return result0; + } + + function parse___() { + var result0, result1; + + result0 = []; + result1 = parse_WhiteSpace(); + if (result1 === null) { + result1 = parse_LineTerminatorSequence(); + if (result1 === null) { + result1 = parse_Comment(); + } + } + while (result1 !== null) { + result0.push(result1); + result1 = parse_WhiteSpace(); + if (result1 === null) { + result1 = parse_LineTerminatorSequence(); + if (result1 === null) { + result1 = parse_Comment(); + } + } + } + return result0; + } + + function parse_Literal() { + var result0; + var pos0; + + pos0 = pos; + result0 = parse_Real(); + if (result0 === null) { + result0 = parse_Integer(); + } + if (result0 !== null) { + result0 = (function(offset, val) { + return { + type: "NumericLiteral", + value: val + } + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_Integer() { + var result0, result1; + var pos0; + + pos0 = pos; + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result0 = null; + } + if (result0 !== null) { + result0 = (function(offset, digits) { + return parseInt(digits.join("")); + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_Real() { + var result0, result1, result2; + var pos0, pos1; + + pos0 = pos; + pos1 = pos; + result0 = parse_Integer(); + if (result0 !== null) { + if (input.charCodeAt(pos) === 46) { + result1 = "."; + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\".\""); + } + } + if (result1 !== null) { + result2 = parse_Integer(); + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, digits) { + return parseFloat(digits.join("")); + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_SignedInteger() { + var result0, result1, result2; + var pos0; + + pos0 = pos; + if (/^[\-+]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[\\-+]"); + } + } + result0 = result0 !== null ? result0 : ""; + if (result0 !== null) { + if (/^[0-9]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result2 !== null) { + result1 = []; + while (result2 !== null) { + result1.push(result2); + if (/^[0-9]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result1 = null; + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + return result0; + } + + function parse_Identifier() { + var result0; + var pos0; + + reportFailures++; + pos0 = pos; + result0 = parse_IdentifierName(); + if (result0 !== null) { + result0 = (function(offset, name) { return name; })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("identifier"); + } + return result0; + } + + function parse_IdentifierName() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_IdentifierStart(); + if (result0 !== null) { + result1 = []; + result2 = parse_IdentifierPart(); + while (result2 !== null) { + result1.push(result2); + result2 = parse_IdentifierPart(); + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, start, parts) { + return start + parts.join(""); + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("identifier"); + } + return result0; + } + + function parse_PrimaryExpression() { + var result0, result1, result2, result3, result4; + var pos0, pos1; + + pos0 = pos; + result0 = parse_Identifier(); + if (result0 !== null) { + result0 = (function(offset, name) { return { type: "Variable", name: name }; })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + result0 = parse_Literal(); + if (result0 === null) { + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 40) { + result0 = "("; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"(\""); + } + } + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + result2 = parse_LinearExpression(); + if (result2 !== null) { + result3 = parse___(); + if (result3 !== null) { + if (input.charCodeAt(pos) === 41) { + result4 = ")"; + pos++; + } else { + result4 = null; + if (reportFailures === 0) { + matchFailed("\")\""); + } + } + if (result4 !== null) { + result0 = [result0, result1, result2, result3, result4]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, expression) { return expression; })(pos0, result0[2]); + } + if (result0 === null) { + pos = pos0; + } + } + } + return result0; + } + + function parse_UnaryExpression() { + var result0, result1, result2; + var pos0, pos1; + + result0 = parse_PrimaryExpression(); + if (result0 === null) { + pos0 = pos; + pos1 = pos; + result0 = parse_UnaryOperator(); + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + result2 = parse_UnaryExpression(); + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, operator, expression) { + return { + type: "UnaryExpression", + operator: operator, + expression: expression + }; + })(pos0, result0[0], result0[2]); + } + if (result0 === null) { + pos = pos0; + } + } + return result0; + } + + function parse_UnaryOperator() { + var result0; + + if (input.charCodeAt(pos) === 43) { + result0 = "+"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 45) { + result0 = "-"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 33) { + result0 = "!"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"!\""); + } + } + } + } + return result0; + } + + function parse_MultiplicativeExpression() { + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = pos; + pos1 = pos; + result0 = parse_UnaryExpression(); + if (result0 !== null) { + result1 = []; + pos2 = pos; + result2 = parse___(); + if (result2 !== null) { + result3 = parse_MultiplicativeOperator(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_UnaryExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + while (result2 !== null) { + result1.push(result2); + pos2 = pos; + result2 = parse___(); + if (result2 !== null) { + result3 = parse_MultiplicativeOperator(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_UnaryExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, head, tail) { + var result = head; + for (var i = 0; i < tail.length; i++) { + result = { + type: "MultiplicativeExpression", + operator: tail[i][1], + left: result, + right: tail[i][3] + }; + } + return result; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_MultiplicativeOperator() { + var result0; + + if (input.charCodeAt(pos) === 42) { + result0 = "*"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"*\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 47) { + result0 = "/"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"/\""); + } + } + } + return result0; + } + + function parse_AdditiveExpression() { + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = pos; + pos1 = pos; + result0 = parse_MultiplicativeExpression(); + if (result0 !== null) { + result1 = []; + pos2 = pos; + result2 = parse___(); + if (result2 !== null) { + result3 = parse_AdditiveOperator(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_MultiplicativeExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + while (result2 !== null) { + result1.push(result2); + pos2 = pos; + result2 = parse___(); + if (result2 !== null) { + result3 = parse_AdditiveOperator(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_MultiplicativeExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, head, tail) { + var result = head; + for (var i = 0; i < tail.length; i++) { + result = { + type: "AdditiveExpression", + operator: tail[i][1], + left: result, + right: tail[i][3] + }; + } + return result; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_AdditiveOperator() { + var result0; + + if (input.charCodeAt(pos) === 43) { + result0 = "+"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 45) { + result0 = "-"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } + } + return result0; + } + + function parse_InequalityExpression() { + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = pos; + pos1 = pos; + result0 = parse_AdditiveExpression(); + if (result0 !== null) { + result1 = []; + pos2 = pos; + result2 = parse___(); + if (result2 !== null) { + result3 = parse_InequalityOperator(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_AdditiveExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + while (result2 !== null) { + result1.push(result2); + pos2 = pos; + result2 = parse___(); + if (result2 !== null) { + result3 = parse_InequalityOperator(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_AdditiveExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, head, tail) { + var result = head; + for (var i = 0; i < tail.length; i++) { + result = { + type: "Inequality", + operator: tail[i][1], + left: result, + right: tail[i][3] + }; + } + return result; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + function parse_InequalityOperator() { + var result0; + + if (input.substr(pos, 2) === "<=") { + result0 = "<="; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"<=\""); + } + } + if (result0 === null) { + if (input.substr(pos, 2) === ">=") { + result0 = ">="; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\">=\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 60) { + result0 = "<"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"<\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos) === 62) { + result0 = ">"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\">\""); + } + } + } + } + } + return result0; + } + + function parse_LinearExpression() { + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = pos; + pos1 = pos; + result0 = parse_InequalityExpression(); + if (result0 !== null) { + result1 = []; + pos2 = pos; + result2 = parse___(); + if (result2 !== null) { + if (input.substr(pos, 2) === "==") { + result3 = "=="; + pos += 2; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\"==\""); + } + } + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_InequalityExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + while (result2 !== null) { + result1.push(result2); + pos2 = pos; + result2 = parse___(); + if (result2 !== null) { + if (input.substr(pos, 2) === "==") { + result3 = "=="; + pos += 2; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\"==\""); + } + } + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_InequalityExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, head, tail) { + var result = head; + for (var i = 0; i < tail.length; i++) { + result = { + type: "Equality", + operator: tail[i][1], + left: result, + right: tail[i][3] + }; + } + return result; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + return result0; + } + + + function cleanupExpected(expected) { + expected.sort(); + + var lastExpected = null; + var cleanExpected = []; + for (var i = 0; i < expected.length; i++) { + if (expected[i] !== lastExpected) { + cleanExpected.push(expected[i]); + lastExpected = expected[i]; + } + } + return cleanExpected; + } + + function computeErrorPosition() { + /* + * The first idea was to use |String.split| to break the input up to the + * error position along newlines and derive the line and column from + * there. However IE's |split| implementation is so broken that it was + * enough to prevent it. + */ + + var line = 1; + var column = 1; + var seenCR = false; + + for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) { + var ch = input.charAt(i); + if (ch === "\n") { + if (!seenCR) { line++; } + column = 1; + seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + line++; + column = 1; + seenCR = true; + } else { + column++; + seenCR = false; + } + } + + return { line: line, column: column }; + } + + + var result = parseFunctions[startRule](); + + /* + * The parser is now in one of the following three states: + * + * 1. The parser successfully parsed the whole input. + * + * - |result !== null| + * - |pos === input.length| + * - |rightmostFailuresExpected| may or may not contain something + * + * 2. The parser successfully parsed only a part of the input. + * + * - |result !== null| + * - |pos < input.length| + * - |rightmostFailuresExpected| may or may not contain something + * + * 3. The parser did not successfully parse any part of the input. + * + * - |result === null| + * - |pos === 0| + * - |rightmostFailuresExpected| contains at least one failure + * + * All code following this comment (including called functions) must + * handle these states. + */ + if (result === null || pos !== input.length) { + var offset = Math.max(pos, rightmostFailuresPos); + var found = offset < input.length ? input.charAt(offset) : null; + var errorPosition = computeErrorPosition(); + + throw new this.SyntaxError( + cleanupExpected(rightmostFailuresExpected), + found, + offset, + errorPosition.line, + errorPosition.column + ); + } + + return result; + }, + + /* Returns the parser source code. */ + toSource: function() { return this._source; } + }; + + /* Thrown when a parser encounters a syntax error. */ + + result.SyntaxError = function(expected, found, offset, line, column) { + function buildMessage(expected, found) { + var expectedHumanized, foundHumanized; + + switch (expected.length) { + case 0: + expectedHumanized = "end of input"; + break; + case 1: + expectedHumanized = expected[0]; + break; + default: + expectedHumanized = expected.slice(0, expected.length - 1).join(", ") + + " or " + + expected[expected.length - 1]; + } + + foundHumanized = found ? quote(found) : "end of input"; + + return "Expected " + expectedHumanized + " but " + foundHumanized + " found."; + } + + this.name = "SyntaxError"; + this.expected = expected; + this.found = found; + this.message = buildMessage(expected, found); + this.offset = offset; + this.line = line; + this.column = column; + }; + + result.SyntaxError.prototype = Error.prototype; + + return result; +})(); +// Copyright (C) 2013, Alex Russell +// Use of this source code is governed by +// http://www.apache.org/licenses/LICENSE-2.0 + +(function(c){ +"use strict"; + +var solver = new c.SimplexSolver(); +var vars = {}; +var exprs = {}; + +var weak = c.Strength.weak; +var medium = c.Strength.medium; +var strong = c.Strength.strong; +var required = c.Strength.required; + +var _c = function(expr) { + if (exprs[expr]) { + return exprs[expr]; + } + switch(expr.type) { + case "Inequality": + var op = (expr.operator == "<=") ? c.LEQ : c.GEQ; + var i = new c.Inequality(_c(expr.left), op, _c(expr.right), weak); + solver.addConstraint(i); + return i; + case "Equality": + var i = new c.Equation(_c(expr.left), _c(expr.right), weak); + solver.addConstraint(i); + return i; + case "MultiplicativeExpression": + var i = c.times(_c(expr.left), _c(expr.right)); + solver.addConstraint(i); + return i; + case "AdditiveExpression": + if (expr.operator == "+") { + return c.plus(_c(expr.left), _c(expr.right)); + } else { + return c.minus(_c(expr.left), _c(expr.right)); + } + case "NumericLiteral": + return new c.Expression(expr.value); + case "Variable": + // console.log(expr); + if(!vars[expr.name]) { + vars[expr.name] = new c.Variable({ name: expr.name }); + } + return vars[expr.name]; + case "UnaryExpression": + console.log("UnaryExpression...WTF?"); + break; + } +}; + +var compile = function(expressions) { + return expressions.map(_c); +}; + +// Global API entrypoint +c._api = function() { + var args = Array.prototype.slice.call(arguments); + if (args.length == 1) { + if(typeof args[0] == "string") { + // Parse and execute it + var r = c.parser.parse(args[0]); + return compile(r); + } else if(typeof args[0] == "function") { + solver._addCallback(args[0]); + } + } +}; + +})(this["c"]||module.parent.exports||{}); }).call( (typeof module != "undefined") ? (module.compiled = true && module) : this diff --git a/package.json b/package.json index 8820aa3..abfe986 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ }, "dependencies": { }, "devDependencies": { - "pegjs" : "*", + "pegjs": "*", + "uglify-js": "*", "intern": "2.2.2" }, "engines" : { "node" : ">=0.8.x" } diff --git a/util/build.sh b/util/build.sh index 075b62f..80b4533 100755 --- a/util/build.sh +++ b/util/build.sh @@ -4,7 +4,12 @@ # # Copyright (C) 2012, Alex Russell (slightlyoff@chromium.org) -COMMAND='python post.py' + +# Unglify currently doesn't understand `for(.. of ..)`, so we punt +DEBUG=1 + +# COMMAND='python post.py' +COMMAND='uglifyjs --screw-ie8 -- ' # To invoke in debug mode, run with a debug env variable like: # $> DEBUG=1 ./build.sh