Просмотр исходного кода

Resolved merge issues. Removed mixed tabs and spaces, changed some parse calls, and removed fixedArity calls in favor of assigning to nargs.

Brennan Chesley 12 лет назад
Родитель
Сommit
ac73f00e50
41 измененных файлов с 1378 добавлено и 1382 удалено
  1. 16 16
      lib/pipeline/expressions/AddExpression.js
  2. 13 14
      lib/pipeline/expressions/AllElementsTrueExpression.js
  3. 41 41
      lib/pipeline/expressions/AndExpression.js
  4. 15 16
      lib/pipeline/expressions/AnyElementTrueExpression.js
  5. 33 33
      lib/pipeline/expressions/CoerceToBoolExpression.js
  6. 54 55
      lib/pipeline/expressions/CompareExpression.js
  7. 3 3
      lib/pipeline/expressions/ConcatExpression.js
  8. 41 41
      lib/pipeline/expressions/CondExpression.js
  9. 15 15
      lib/pipeline/expressions/ConstantExpression.js
  10. 13 13
      lib/pipeline/expressions/DayOfMonthExpression.js
  11. 5 5
      lib/pipeline/expressions/DayOfWeekExpression.js
  12. 12 13
      lib/pipeline/expressions/DayOfYearExpression.js
  13. 17 17
      lib/pipeline/expressions/DivideExpression.js
  14. 134 134
      lib/pipeline/expressions/Expression.js
  15. 33 33
      lib/pipeline/expressions/FieldPathExpression.js
  16. 140 140
      lib/pipeline/expressions/FieldRangeExpression.js
  17. 13 13
      lib/pipeline/expressions/HourExpression.js
  18. 15 15
      lib/pipeline/expressions/IfNullExpression.js
  19. 16 16
      lib/pipeline/expressions/MillisecondExpression.js
  20. 15 15
      lib/pipeline/expressions/MinuteExpression.js
  21. 18 18
      lib/pipeline/expressions/ModExpression.js
  22. 14 14
      lib/pipeline/expressions/MonthExpression.js
  23. 17 17
      lib/pipeline/expressions/MultiplyExpression.js
  24. 4 4
      lib/pipeline/expressions/NaryExpression.js
  25. 16 16
      lib/pipeline/expressions/NotExpression.js
  26. 36 36
      lib/pipeline/expressions/OrExpression.js
  27. 16 16
      lib/pipeline/expressions/SecondExpression.js
  28. 23 23
      lib/pipeline/expressions/SetDifferenceExpression.js
  29. 18 18
      lib/pipeline/expressions/SetEqualsExpression.js
  30. 19 19
      lib/pipeline/expressions/SetIntersectionExpression.js
  31. 50 50
      lib/pipeline/expressions/SetIsSubsetExpression.js
  32. 24 24
      lib/pipeline/expressions/SetUnionExpression.js
  33. 6 6
      lib/pipeline/expressions/SizeExpression.js
  34. 21 21
      lib/pipeline/expressions/StrcasecmpExpression.js
  35. 22 22
      lib/pipeline/expressions/SubstrExpression.js
  36. 18 18
      lib/pipeline/expressions/SubtractExpression.js
  37. 17 17
      lib/pipeline/expressions/ToLowerExpression.js
  38. 17 17
      lib/pipeline/expressions/ToUpperExpression.js
  39. 22 22
      lib/pipeline/expressions/WeekExpression.js
  40. 48 48
      test/lib/pipeline/expressions/AllElementsTrueExpression.js
  41. 308 308
      test/lib/pipeline/expressions/CompareExpression.js

+ 16 - 16
lib/pipeline/expressions/AddExpression.js

@@ -1,24 +1,24 @@
 "use strict";
 "use strict";
 
 
-/** 
- * Create an expression that finds the sum of n operands. 
+/**
+ * Create an expression that finds the sum of n operands.
  * @class AddExpression
  * @class AddExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
 var AddExpression = module.exports = function AddExpression(){
 var AddExpression = module.exports = function AddExpression(){
-	if (arguments.length !== 0) throw new Error("zero args expected");
-	base.call(this);
+        if (arguments.length !== 0) throw new Error("zero args expected");
+        base.call(this);
 }, klass = AddExpression, NaryExpression = require("./NaryExpression"), base = NaryExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = AddExpression, NaryExpression = require("./NaryExpression"), base = NaryExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-	Expression = require("./Expression");
+        Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$add";
+        return "$add";
 };
 };
 
 
 /**
 /**
@@ -26,17 +26,17 @@ proto.getOpName = function getOpName(){
  * @method @evaluate
  * @method @evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-	var total = 0;
-	for (var i = 0, n = this.operands.length; i < n; ++i) {
-		var value = this.operands[i].evaluateInternal(vars);
-		if (value instanceof Date) throw new Error("$add does not support dates; code 16415");
-		if (typeof value == "string") throw new Error("$add does not support strings; code 16416");
-		total += Value.coerceToDouble(value);
-	}
-	if (typeof total != "number") throw new Error("$add resulted in a non-numeric type; code 16417");
-	return total;
+        var total = 0;
+        for (var i = 0, n = this.operands.length; i < n; ++i) {
+                var value = this.operands[i].evaluateInternal(vars);
+                if (value instanceof Date) throw new Error("$add does not support dates; code 16415");
+                if (typeof value == "string") throw new Error("$add does not support strings; code 16416");
+                total += Value.coerceToDouble(value);
+        }
+        if (typeof total != "number") throw new Error("$add resulted in a non-numeric type; code 16417");
+        return total;
 };
 };
 
 
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$add",klass.parse(AddExpression));
+Expression.registerExpression("$add",base.parse(AddExpression));

+ 13 - 14
lib/pipeline/expressions/AllElementsTrueExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * Create an expression that returns true exists in all elements.
  * Create an expression that returns true exists in all elements.
  * @class AllElementsTrueExpression
  * @class AllElementsTrueExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
@@ -8,22 +8,21 @@
  * @constructor
  * @constructor
  **/
  **/
 var AllElementsTrueExpression = module.exports = function AllElementsTrueExpression() {
 var AllElementsTrueExpression = module.exports = function AllElementsTrueExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one arg expected");
-		base.call(this);
+    this.nargs = 1;
+    base.call(this);
 }, klass = AllElementsTrueExpression,
 }, klass = AllElementsTrueExpression,
-		NaryExpression = require("./NaryExpression"),
-		base = NaryExpression,
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    NaryExpression = require("./NaryExpression"),
+    base = NaryExpression,
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		CoerceToBoolExpression = require("./CoerceToBoolExpression"),
-		Expression = require("./Expression");
+    CoerceToBoolExpression = require("./CoerceToBoolExpression"),
+    Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
@@ -47,4 +46,4 @@ proto.evaluateInternal = function evaluateInternal(vars) {
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$allElementsTrue", AllElementsTrueExpression.parse);
+Expression.registerExpression("$allElementsTrue", base.parse(AllElementsTrueExpression));

+ 41 - 41
lib/pipeline/expressions/AndExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * Create an expression that finds the conjunction of n operands. The
  * Create an expression that finds the conjunction of n operands. The
  * conjunction uses short-circuit logic; the expressions are evaluated in the
  * conjunction uses short-circuit logic; the expressions are evaluated in the
  * order they were added to the conjunction, and the evaluation stops and
  * order they were added to the conjunction, and the evaluation stops and
@@ -12,25 +12,25 @@
  * @constructor
  * @constructor
  **/
  **/
 var AndExpression = module.exports = function AndExpression() {
 var AndExpression = module.exports = function AndExpression() {
-		if (arguments.length !== 0) throw new Error("zero args expected");
-		base.call(this);
+                if (arguments.length !== 0) throw new Error("zero args expected");
+                base.call(this);
 }, klass = AndExpression,
 }, klass = AndExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+                base = require("./NaryExpression"),
+                proto = klass.prototype = Object.create(base.prototype, {
+                                constructor: {
+                                                value: klass
+                                }
+                });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		ConstantExpression = require("./ConstantExpression"),
-		CoerceToBoolExpression = require("./CoerceToBoolExpression"),
-		Expression = require("./Expression");
+                ConstantExpression = require("./ConstantExpression"),
+                CoerceToBoolExpression = require("./CoerceToBoolExpression"),
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$and";
+                return "$and";
 };
 };
 
 
 /**
 /**
@@ -38,43 +38,43 @@ proto.getOpName = function getOpName() {
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		for (var i = 0, n = this.operands.length; i < n; ++i) {
-				var value = this.operands[i].evaluateInternal(vars);
-				if (!Value.coerceToBool()) return false;
-		}
-		return true;
+                for (var i = 0, n = this.operands.length; i < n; ++i) {
+                                var value = this.operands[i].evaluateInternal(vars);
+                                if (!Value.coerceToBool()) return false;
+                }
+                return true;
 };
 };
 
 
 proto.optimize = function optimize() {
 proto.optimize = function optimize() {
-		var expr = base.prototype.optimize.call(this); //optimize the conjunction as much as possible
+                var expr = base.prototype.optimize.call(this); //optimize the conjunction as much as possible
 
 
-		// if the result isn't a conjunction, we can't do anything
-		if (!(expr instanceof AndExpression)) return expr;
-		var andExpr = expr;
+                // if the result isn't a conjunction, we can't do anything
+                if (!(expr instanceof AndExpression)) return expr;
+                var andExpr = expr;
 
 
-		// Check the last argument on the result; if it's not constant (as promised by ExpressionNary::optimize(),) then there's nothing we can do.
-		var n = andExpr.operands.length;
-		// ExpressionNary::optimize() generates an ExpressionConstant for {$and:[]}.
-		if (!n) throw new Error("requires operands!");
-		var lastExpr = andExpr.operands[n - 1];
-		if (!(lastExpr instanceof ConstantExpression)) return expr;
+                // Check the last argument on the result; if it's not constant (as promised by ExpressionNary::optimize(),) then there's nothing we can do.
+                var n = andExpr.operands.length;
+                // ExpressionNary::optimize() generates an ExpressionConstant for {$and:[]}.
+                if (!n) throw new Error("requires operands!");
+                var lastExpr = andExpr.operands[n - 1];
+                if (!(lastExpr instanceof ConstantExpression)) return expr;
 
 
-		// Evaluate and coerce the last argument to a boolean.  If it's false, then we can replace this entire expression.
-		var last = Value.coerceToBool(lastExpr.evaluate());
-		if (!last) return new ConstantExpression(false);
+                // Evaluate and coerce the last argument to a boolean.  If it's false, then we can replace this entire expression.
+                var last = Value.coerceToBool(lastExpr.evaluate());
+                if (!last) return new ConstantExpression(false);
 
 
-		// If we got here, the final operand was true, so we don't need it anymore.
-		// If there was only one other operand, we don't need the conjunction either.
-		// Note we still need to keep the promise that the result will be a boolean.
-		if (n == 2) return new CoerceToBoolExpression(andExpr.operands[0]);
+                // If we got here, the final operand was true, so we don't need it anymore.
+                // If there was only one other operand, we don't need the conjunction either.
+                // Note we still need to keep the promise that the result will be a boolean.
+                if (n == 2) return new CoerceToBoolExpression(andExpr.operands[0]);
 
 
-		//Remove the final "true" value, and return the new expression.
-		//CW TODO: Note that because of any implicit conversions, we may need to apply an implicit boolean conversion.
-		andExpr.operands.length = n - 1; //truncate the array
-		return expr;
+                //Remove the final "true" value, and return the new expression.
+                //CW TODO: Note that because of any implicit conversions, we may need to apply an implicit boolean conversion.
+                andExpr.operands.length = n - 1; //truncate the array
+                return expr;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$and", klass.parse(AndExpression));
+Expression.registerExpression("$and", base.parse(AndExpression));
 
 
-//TODO:	proto.toMatcherBson
+//TODO: proto.toMatcherBson

+ 15 - 16
lib/pipeline/expressions/AnyElementTrueExpression.js

@@ -1,25 +1,24 @@
 "use strict";
 "use strict";
 
 
-/** 
- * Create an expression that returns true exists in any element. 
+/**
+ * Create an expression that returns true exists in any element.
  * @class AnyElementTrueExpression
  * @class AnyElementTrueExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
 var AnyElementTrueExpression = module.exports = function AnyElementTrueExpression(){
 var AnyElementTrueExpression = module.exports = function AnyElementTrueExpression(){
-	this.fixedArity(1);
-	if (arguments.length !== 1) throw new Error("one args expected");
-	base.call(this);
+    this.nargs = (1);
+    base.call(this);
 }, klass = AnyElementTrueExpression, NaryExpression = require("./NaryExpression"), base = NaryExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = AnyElementTrueExpression, NaryExpression = require("./NaryExpression"), base = NaryExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-	Expression = require("./Expression");
+        Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$anyElementTrue";
+        return "$anyElementTrue";
 };
 };
 
 
 /**
 /**
@@ -28,16 +27,16 @@ proto.getOpName = function getOpName(){
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
 
 
-	if (!vars instanceof Array) throw new Error("$anyElementTrue requires an array");
+        if (!vars instanceof Array) throw new Error("$anyElementTrue requires an array");
 
 
-	var total = 0;
-	for (var i = 0, n = vars.length; i < n; ++i) {
-		var value = vars[i].evaluateInternal([i]);
-		if ( value.coerceToBool() )
-			return true;
-	}
-	return false;
+        var total = 0;
+        for (var i = 0, n = vars.length; i < n; ++i) {
+                var value = vars[i].evaluateInternal([i]);
+                if ( value.coerceToBool() )
+                        return true;
+        }
+        return false;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$anyElementTrue",klass.parse(AnyElementTrueExpression));
+Expression.registerExpression("$anyElementTrue",base.parse(AnyElementTrueExpression));

+ 33 - 33
lib/pipeline/expressions/CoerceToBoolExpression.js

@@ -1,62 +1,62 @@
 "use strict";
 "use strict";
 
 
-/** 
- * internal expression for coercing things to booleans 
+/**
+ * internal expression for coercing things to booleans
  * @class CoerceToBoolExpression
  * @class CoerceToBoolExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
 var CoerceToBoolExpression = module.exports = function CoerceToBoolExpression(expression){
 var CoerceToBoolExpression = module.exports = function CoerceToBoolExpression(expression){
-	if (arguments.length !== 1) throw new Error("args expected: expression");
-	this.expression = expression;
-	base.call(this);
+        if (arguments.length !== 1) throw new Error("args expected: expression");
+        this.expression = expression;
+        base.call(this);
 }, klass = CoerceToBoolExpression, base = require("./Expression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = CoerceToBoolExpression, base = require("./Expression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-	AndExpression = require("./AndExpression"),
-	OrExpression = require("./OrExpression"),
-	NotExpression = require("./NotExpression"),
-	Expression = require("./Expression");
+        AndExpression = require("./AndExpression"),
+        OrExpression = require("./OrExpression"),
+        NotExpression = require("./NotExpression"),
+        Expression = require("./Expression");
 
 
 proto.optimize = function optimize() {
 proto.optimize = function optimize() {
-	this.expression = this.expression.optimize();	// optimize the operand
-
-	// if the operand already produces a boolean, then we don't need this
-	// LATER - Expression to support a "typeof" query?
-	var expr = this.expression;
-	if(expr instanceof AndExpression ||
-			expr instanceof OrExpression ||
-			expr instanceof NotExpression ||
-			expr instanceof CoerceToBoolExpression)
-		return expr;
-	return this;
+        this.expression = this.expression.optimize();   // optimize the operand
+
+        // if the operand already produces a boolean, then we don't need this
+        // LATER - Expression to support a "typeof" query?
+        var expr = this.expression;
+        if(expr instanceof AndExpression ||
+                        expr instanceof OrExpression ||
+                        expr instanceof NotExpression ||
+                        expr instanceof CoerceToBoolExpression)
+                return expr;
+        return this;
 };
 };
 
 
 proto.addDependencies = function addDependencies(deps, path) {
 proto.addDependencies = function addDependencies(deps, path) {
-	return this.expression.addDependencies(deps);
+        return this.expression.addDependencies(deps);
 };
 };
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.evaluateInternal = function evaluateInternal(vars){
 proto.evaluateInternal = function evaluateInternal(vars){
-	var result = this.expression.evaluateInternal(vars);
-	return Value.coerceToBool(result);
+        var result = this.expression.evaluateInternal(vars);
+        return Value.coerceToBool(result);
 };
 };
 
 
 proto.serialize = function serialize(explain) {
 proto.serialize = function serialize(explain) {
-	if ( explain ) {
-		return {$coerceToBool:[this.expression.toJSON()]};
-	}
-	else {
-		return {$and:[this.expression.toJSON()]};
-	}
+        if ( explain ) {
+                return {$coerceToBool:[this.expression.toJSON()]};
+        }
+        else {
+                return {$and:[this.expression.toJSON()]};
+        }
 };
 };
 
 
 proto.toJSON = function toJSON() {
 proto.toJSON = function toJSON() {
-	// Serializing as an $and expression which will become a CoerceToBool
-	return {$and:[this.expression.toJSON()]};
+        // Serializing as an $and expression which will become a CoerceToBool
+        return {$and:[this.expression.toJSON()]};
 };
 };
 
 
-//TODO:	proto.addToBsonObj   --- may be required for $project to work
-//TODO:	proto.addToBsonArray
+//TODO: proto.addToBsonObj   --- may be required for $project to work
+//TODO: proto.addToBsonArray

+ 54 - 55
lib/pipeline/expressions/CompareExpression.js

@@ -8,17 +8,16 @@
  * @constructor
  * @constructor
  **/
  **/
 var CompareExpression = module.exports = function CompareExpression(cmpOp) {
 var CompareExpression = module.exports = function CompareExpression(cmpOp) {
-		this.fixedVarity(2);
-		if (arguments.length !== 2) throw new Error("two args expected: cmpOp");
-		this.cmpOp = cmpOp;
-		base.call(this);
+    this.nargs = 2;
+    this.cmpOp = cmpOp;
+    base.call(this);
 }, klass = CompareExpression,
 }, klass = CompareExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value");
 var Value = require("../Value");
@@ -32,24 +31,24 @@ var NaryExpression = require("./NaryExpression");
 /**
 /**
  * Lookup table for truth value returns
  * Lookup table for truth value returns
  *
  *
- * @param truthValues	truth value for -1, 0, 1
- * @param reverse		reverse comparison operator
- * @param name			string name
+ * @param truthValues   truth value for -1, 0, 1
+ * @param reverse               reverse comparison operator
+ * @param name                  string name
  **/
  **/
 var CmpLookup = (function() { // emulating a struct
 var CmpLookup = (function() { // emulating a struct
-		// CONSTRUCTOR
-		var klass = function CmpLookup(truthValues, reverse, name) {
-				if (arguments.length !== 3) throw new Error("args expected: truthValues, reverse, name");
-				this.truthValues = truthValues;
-				this.reverse = reverse;
-				this.name = name;
-		}, base = Object,
-				proto = klass.prototype = Object.create(base.prototype, {
-						constructor: {
-								value: klass
-						}
-				});
-		return klass;
+                // CONSTRUCTOR
+                var klass = function CmpLookup(truthValues, reverse, name) {
+                                if (arguments.length !== 3) throw new Error("args expected: truthValues, reverse, name");
+                                this.truthValues = truthValues;
+                                this.reverse = reverse;
+                                this.name = name;
+                }, base = Object,
+                                proto = klass.prototype = Object.create(base.prototype, {
+                                                constructor: {
+                                                                value: klass
+                                                }
+                                });
+                return klass;
 })();
 })();
 
 
 // verify we need this below
 // verify we need this below
@@ -59,37 +58,37 @@ var CmpLookup = (function() { // emulating a struct
  * @private
  * @private
  **/
  **/
 var cmpLookupMap = [ //NOTE: converted from this Array to a Dict/Object below using CmpLookup#name as the key
 var cmpLookupMap = [ //NOTE: converted from this Array to a Dict/Object below using CmpLookup#name as the key
-		//              -1      0      1      reverse             name     (taking advantage of the fact that our 'enums' are strings below)
-		new CmpLookup([false, true, false], CompareExpression.EQ, CompareExpression.EQ),
-		new CmpLookup([true, false, true], CompareExpression.NE, CompareExpression.NE),
-		new CmpLookup([false, false, true], CompareExpression.LT, CompareExpression.GT),
-		new CmpLookup([false, true, true], CompareExpression.LTE, CompareExpression.GTE),
-		new CmpLookup([true, false, false], CompareExpression.GT, CompareExpression.LT),
-		new CmpLookup([true, true, false], CompareExpression.GTE, CompareExpression.LTE),
-		new CmpLookup([false, false, false], CompareExpression.CMP, CompareExpression.CMP)
+    //              -1      0      1      reverse             name     (taking advantage of the fact that our 'enums' are strings below)
+    new CmpLookup([false, true, false], CompareExpression.EQ, CompareExpression.EQ),
+    new CmpLookup([true, false, true], CompareExpression.NE, CompareExpression.NE),
+    new CmpLookup([false, false, true], CompareExpression.LT, CompareExpression.GT),
+    new CmpLookup([false, true, true], CompareExpression.LTE, CompareExpression.GTE),
+    new CmpLookup([true, false, false], CompareExpression.GT, CompareExpression.LT),
+    new CmpLookup([true, true, false], CompareExpression.GTE, CompareExpression.LTE),
+    new CmpLookup([false, false, false], CompareExpression.CMP, CompareExpression.CMP)
 ].reduce(function(r, o) {
 ].reduce(function(r, o) {
-		r[o.name] = o;
-		return r;
+                r[o.name] = o;
+                return r;
 }, {});
 }, {});
 
 
 
 
 klass.parse = function parse(bsonExpr, vps, op) {
 klass.parse = function parse(bsonExpr, vps, op) {
-		var expr = new CompareExpression(op);
-		var args = NaryExpression.parseArguments(bsonExpr, vps);
-		expr.validateArguments(args);
-		expr.vpOperand = args;
-		return expr;
+    var expr = new CompareExpression(op);
+    var args = NaryExpression.parseArguments(bsonExpr, vps);
+    expr.validateArguments(args);
+    expr.vpOperand = args;
+    return expr;
 
 
 };
 };
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		//debugger;
-		var left = this.operands[0].evaluateInternal(vars),
-				right = this.operands[1].evaluateInternal(vars),
-				cmp = Expression.signum(Value.compare(left, right));
-		if (this.cmpOp == Expression.CmpOp.CMP) return cmp;
-		return cmpLookupMap[this.cmpOp].truthValues[cmp + 1] || false;
+                //debugger;
+    var left = this.operands[0].evaluateInternal(vars),
+        right = this.operands[1].evaluateInternal(vars),
+        cmp = Expression.signum(Value.compare(left, right));
+    if (this.cmpOp == Expression.CmpOp.CMP) return cmp;
+    return cmpLookupMap[this.cmpOp].truthValues[cmp + 1] || false;
 };
 };
 
 
 klass.EQ = "$eq";
 klass.EQ = "$eq";
@@ -101,14 +100,14 @@ klass.LTE = "$lte";
 klass.CMP = "$cmp";
 klass.CMP = "$cmp";
 
 
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return this.cmpOp;
+                return this.cmpOp;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$eq", klass.parse(CompareExpression));
-Expression.registerExpression("$ne", klass.parse(CompareExpression));
-Expression.registerExpression("$gt", klass.parse(CompareExpression));
-Expression.registerExpression("$gte", klass.parse(CompareExpression));
-Expression.registerExpression("$lt", klass.parse(CompareExpression));
-Expression.registerExpression("$lte", klass.parse(CompareExpression));
-Expression.registerExpression("$cmp", klass.parse(CompareExpression));
+Expression.registerExpression("$eq", klass.parse);
+Expression.registerExpression("$ne", klass.parse);
+Expression.registerExpression("$gt", klass.parse);
+Expression.registerExpression("$gte", klass.parse);
+Expression.registerExpression("$lt", klass.parse);
+Expression.registerExpression("$lte", klass.parse);
+Expression.registerExpression("$cmp", klass.parse);

+ 3 - 3
lib/pipeline/expressions/ConcatExpression.js

@@ -10,8 +10,8 @@ var Expression = require("./Expression");
  * @constructor
  * @constructor
  **/
  **/
 var ConcatExpression = module.exports = function ConcatExpression(){
 var ConcatExpression = module.exports = function ConcatExpression(){
-	if (arguments.length !== 0) throw new Error("zero args expected");
-	base.call(this);
+        if (arguments.length !== 0) throw new Error("zero args expected");
+        base.call(this);
 }, klass = ConcatExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = ConcatExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
@@ -20,7 +20,7 @@ var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$concat";
+        return "$concat";
 };
 };
 
 
 /**
 /**

+ 41 - 41
lib/pipeline/expressions/CondExpression.js

@@ -8,71 +8,71 @@
  * @constructor
  * @constructor
  **/
  **/
 var CondExpression = module.exports = function CondExpression(vars) {
 var CondExpression = module.exports = function CondExpression(vars) {
-		this.fixedArity(3);
-		this.pCond = this.evaluateInternal(vars);
-		this.idx = this.pCond.coerceToBool() ? 1 : 2;
+    this.nargs = 3;
+    this.pCond = this.evaluateInternal(vars);
+    this.idx = this.pCond.coerceToBool() ? 1 : 2;
 
 
-		if (arguments.length !== 3) throw new Error("three args expected");
-		base.call(this);
+    if (arguments.length !== 3) throw new Error("three args expected");
+    base.call(this);
 }, klass = CondExpression,
 }, klass = CondExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+    Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$cond";
+    return "$cond";
 };
 };
 
 
-proto.parse = function parse(expr, vps) {
-		this.checkArgLimit(3);
+klass.parse = function parse(expr, vps) {
+    this.checkArgLimit(3);
 
 
-		// if not an object, return;
-		if (typeof(expr) !== Object)
-				return Expression.parse(expr, vps);
+    // if not an object, return;
+    if (typeof(expr) !== Object)
+        return Expression.parse(expr, vps);
 
 
-		// verify 
-		if (Expression.parseOperand(expr) !== "$cond")
-				throw new Error("Invalid expression");
+    // verify
+    if (Expression.parseOperand(expr) !== "$cond")
+        throw new Error("Invalid expression");
 
 
-		var ret = new CondExpression();
+    var ret = new CondExpression();
 
 
-		var ex = Expression.parseObject(expr);
-		var args = Expression.parseOperand(expr, vps);
-		if (args[0] !== "if")
-				throw new Error("Missing 'if' parameter to $cond");
-		if (args[1] !== "then")
-				throw new Error("Missing 'then' parameter to $cond");
-		if (args[2] !== "else")
-				throw new Error("Missing 'else' parameter to $cond");
+    var ex = Expression.parseObject(expr);
+    var args = Expression.parseOperand(expr, vps);
+    if (args[0] !== "if")
+        throw new Error("Missing 'if' parameter to $cond");
+    if (args[1] !== "then")
+        throw new Error("Missing 'then' parameter to $cond");
+    if (args[2] !== "else")
+        throw new Error("Missing 'else' parameter to $cond");
 
 
 
 
-		return ret;
+    return ret;
 };
 };
 
 
-/** 
+/**
  * Use the $cond operator with the following syntax:  { $cond: [ <boolean-expression>, <true-case>, <false-case> ] }
  * Use the $cond operator with the following syntax:  { $cond: [ <boolean-expression>, <true-case>, <false-case> ] }
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var pCond1 = this.operands[0].evaluateInternal(vars);
+                var pCond1 = this.operands[0].evaluateInternal(vars);
 
 
-		this.idx = 0;
-		if (pCond1.coerceToBool()) {
-				this.idx = 1;
-		} else {
-				this.idx = 2;
-		}
+                this.idx = 0;
+                if (pCond1.coerceToBool()) {
+                                this.idx = 1;
+                } else {
+                                this.idx = 2;
+                }
 
 
-		return this.operands[this.idx].evaluateInternal(vars);
+                return this.operands[this.idx].evaluateInternal(vars);
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$cond", klass.parse(CondExpression));
+Expression.registerExpression("$cond", klass.parse);

+ 15 - 15
lib/pipeline/expressions/ConstantExpression.js

@@ -8,19 +8,19 @@
  * @constructor
  * @constructor
  **/
  **/
 var ConstantExpression = module.exports = function ConstantExpression(value){
 var ConstantExpression = module.exports = function ConstantExpression(value){
-	if (arguments.length !== 1) throw new Error("args expected: value");
-	this.value = value;	//TODO: actually make read-only in terms of JS?
-	base.call(this);
+    if (arguments.length !== 1) throw new Error("args expected: value");
+    this.value = value; //TODO: actually make read-only in terms of JS?
+    base.call(this);
 }, klass = ConstantExpression, base = require("./Expression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = ConstantExpression, base = require("./Expression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-	Expression = require("./Expression");
+    Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$const";
+        return "$const";
 };
 };
 
 
 /**
 /**
@@ -28,16 +28,16 @@ proto.getOpName = function getOpName(){
  * @method getValue
  * @method getValue
  * @returns the value
  * @returns the value
  **/
  **/
-proto.getValue = function getValue(){	//TODO: convert this to an instance field rather than a property
-	return this.value;
+proto.getValue = function getValue(){   //TODO: convert this to an instance field rather than a property
+    return this.value;
 };
 };
 
 
 proto.addDependencies = function addDependencies(deps, path) {
 proto.addDependencies = function addDependencies(deps, path) {
-	// nothing to do
+        // nothing to do
 };
 };
 
 
-klass.parse = function parse(){
-	return;
+klass.parse = function parse(expr, vps){
+    return new ConstantExpression(expr);
 };
 };
 
 
 /**
 /**
@@ -45,19 +45,19 @@ klass.parse = function parse(){
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars){
 proto.evaluateInternal = function evaluateInternal(vars){
-	return this.value;
+        return this.value;
 };
 };
 
 
 proto.optimize = function optimize() {
 proto.optimize = function optimize() {
-	return this; // nothing to do
+        return this; // nothing to do
 };
 };
 
 
 proto.serialize = function(rawValue){
 proto.serialize = function(rawValue){
-	return rawValue ? {$const: this.value} : this.value;
+        return rawValue ? {$const: this.value} : this.value;
 };
 };
 
 
-//TODO:	proto.addToBsonObj   --- may be required for $project to work -- my hope is that we can implement toJSON methods all around and use that instead
-//TODO:	proto.addToBsonArray
+//TODO: proto.addToBsonObj   --- may be required for $project to work -- my hope is that we can implement toJSON methods all around and use that instead
+//TODO: proto.addToBsonArray
 
 
 /** Register Expression */
 /** Register Expression */
 Expression.registerExpression("$const",klass.parse(ConstantExpression));
 Expression.registerExpression("$const",klass.parse(ConstantExpression));

+ 13 - 13
lib/pipeline/expressions/DayOfMonthExpression.js

@@ -8,16 +8,16 @@
  * @constructor
  * @constructor
  **/
  **/
 var DayOfMonthExpression = module.exports = function DayOfMonthExpression() {
 var DayOfMonthExpression = module.exports = function DayOfMonthExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one arg expected");
-		base.call(this);
+                this.fixedArity(1);
+                if (arguments.length !== 1) throw new Error("one arg expected");
+                base.call(this);
 }, klass = DayOfMonthExpression,
 }, klass = DayOfMonthExpression,
-		base = require("../Value"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Expression = require("./Expression");
 var Expression = require("./Expression");
@@ -25,7 +25,7 @@ var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$dayOfMonth";
+    return "$dayOfMonth";
 };
 };
 
 
 /**
 /**
@@ -33,9 +33,9 @@ proto.getOpName = function getOpName() {
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var date = this.operands[0].evaluateInternal(vars);
-		return date.getUTCDate();
+    var date = this.operands[0].evaluateInternal(vars);
+    return date.getUTCDate();
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$dayOfMonth", klass.parse(DayOfMonthExpression));
+Expression.registerExpression("$dayOfMonth", base.parse(DayOfMonthExpression));

+ 5 - 5
lib/pipeline/expressions/DayOfWeekExpression.js

@@ -14,11 +14,11 @@ var DayOfWeekExpression = module.exports = function DayOfWeekExpression(){
 }, klass = DayOfWeekExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = DayOfWeekExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
-var	Expression = require("./Expression");
+var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$dayOfWeek";
+    return "$dayOfWeek";
 };
 };
 
 
 /**
 /**
@@ -26,9 +26,9 @@ proto.getOpName = function getOpName(){
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars){
 proto.evaluateInternal = function evaluateInternal(vars){
-	var date = this.operands[0].evaluateInternal(vars);
-	return date.getUTCDay()+1;
+    var date = this.operands[0].evaluateInternal(vars);
+    return date.getUTCDay()+1;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$dayOfWeek",klass.parse(DayOfWeekExpression));
+Expression.registerExpression("$dayOfWeek",base.parse(DayOfWeekExpression));

+ 12 - 13
lib/pipeline/expressions/DayOfYearExpression.js

@@ -8,17 +8,17 @@
  * @constructor
  * @constructor
  **/
  **/
 var DayOfYearExpression = module.exports = function DayOfYearExpression(){
 var DayOfYearExpression = module.exports = function DayOfYearExpression(){
-	this.fixedArity(1);
-	if(arguments.length !== 1) throw new Error("one arg expected");
-	base.call(this);
+        this.nargs = 1;
+        if(arguments.length !== 1) throw new Error("one arg expected");
+        base.call(this);
 }, klass = DayOfYearExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = DayOfYearExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
-var	Expression = require("./Expression");
+var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$dayOfYear";
+    return "$dayOfYear";
 };
 };
 
 
 /**
 /**
@@ -26,18 +26,17 @@ proto.getOpName = function getOpName(){
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars){
 proto.evaluateInternal = function evaluateInternal(vars){
-	//NOTE: the below silliness is to deal with the leap year scenario when we should be returning 366
-	var date = this.operands[0].evaluateInternal(vars);
-	return klass.getDateDayOfYear(date);
+        //NOTE: the below silliness is to deal with the leap year scenario when we should be returning 366
+    var date = this.operands[0].evaluateInternal(vars);
+    return klass.getDateDayOfYear(date);
 };
 };
 
 
 // STATIC METHODS
 // STATIC METHODS
 klass.getDateDayOfYear = function getDateDayOfYear(d){
 klass.getDateDayOfYear = function getDateDayOfYear(d){
-	var y11 = new Date(d.getUTCFullYear(), 0, 1),	// same year, first month, first day; time omitted
-		ymd = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()+1);	// same y,m,d; time omitted, add 1 because days start at 1
-	return Math.ceil((ymd - y11) / 86400000);	//NOTE: 86400000 ms is 1 day
+    var y11 = new Date(d.getUTCFullYear(), 0, 1),       // same year, first month, first day; time omitted
+        ymd = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()+1);  // same y,m,d; time omitted, add 1 because days start at 1
+    return Math.ceil((ymd - y11) / 86400000);   //NOTE: 86400000 ms is 1 day
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$dayOfYear",klass.parse(DayOfYearExpression));
-
+Expression.registerExpression("$dayOfYear",base.parse(DayOfYearExpression));

+ 17 - 17
lib/pipeline/expressions/DivideExpression.js

@@ -1,26 +1,26 @@
 "use strict";
 "use strict";
 
 
-/** 
- * A $divide pipeline expression. 
- * @see evaluateInternal 
+/**
+ * A $divide pipeline expression.
+ * @see evaluateInternal
  * @class DivideExpression
  * @class DivideExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
 var DivideExpression = module.exports = function DivideExpression(){
 var DivideExpression = module.exports = function DivideExpression(){
-	this.fixedArity(2);
-	if (arguments.length !== 2) throw new Error("two args expected");
-	base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 2) throw new Error("two args expected");
+    base.call(this);
 }, klass = DivideExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = DivideExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
-proto.getOpName = function getOpName(){	//TODO: try to move this to a static and/or instance field instead of a getter function
-	return "$divide";
+proto.getOpName = function getOpName(){ //TODO: try to move this to a static and/or instance field instead of a getter function
+        return "$divide";
 };
 };
 
 
 /**
 /**
@@ -28,14 +28,14 @@ proto.getOpName = function getOpName(){	//TODO: try to move this to a static and
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-	var left = this.operands[0].evaluateInternal(vars),
-		right = this.operands[1].evaluateInternal(vars);
-	if (!(left instanceof Date) && (!right instanceof Date)) throw new Error("$divide does not support dates; code 16373");
-	right = Value.coerceToDouble(right);
-	if (right === 0) return undefined;
-	left = Value.coerceToDouble(left);
-	return left / right;
+        var left = this.operands[0].evaluateInternal(vars),
+                right = this.operands[1].evaluateInternal(vars);
+        if (!(left instanceof Date) && (!right instanceof Date)) throw new Error("$divide does not support dates; code 16373");
+        right = Value.coerceToDouble(right);
+        if (right === 0) return undefined;
+        left = Value.coerceToDouble(left);
+        return left / right;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$divide",klass.parse(DivideExpression));
+Expression.registerExpression("$divide",base.parse(DivideExpression));

+ 134 - 134
lib/pipeline/expressions/Expression.js

@@ -5,8 +5,8 @@
  *
  *
  * NOTE: An object expression can take any of the following forms:
  * NOTE: An object expression can take any of the following forms:
  *
  *
- *	f0: {f1: ..., f2: ..., f3: ...}
- *	f0: {$operator:[operand1, operand2, ...]}
+ *      f0: {f1: ..., f2: ..., f3: ...}
+ *      f0: {$operator:[operand1, operand2, ...]}
  *
  *
  * @class Expression
  * @class Expression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
@@ -16,19 +16,19 @@
 
 
 
 
 var Expression = module.exports = function Expression() {
 var Expression = module.exports = function Expression() {
-		if (arguments.length !== 0) throw new Error("zero args expected");
+                if (arguments.length !== 0) throw new Error("zero args expected");
 }, klass = Expression,
 }, klass = Expression,
     base = Object,
     base = Object,
     proto = klass.prototype = Object.create(base.prototype, {
     proto = klass.prototype = Object.create(base.prototype, {
-	constructor: {
+        constructor: {
             value: klass
             value: klass
-	}
+        }
     });
     });
 
 
 
 
 
 
 function fn(){
 function fn(){
-	return;
+        return;
 }
 }
 
 
 
 
@@ -39,145 +39,145 @@ function fn(){
  * @property ObjectCtx
  * @property ObjectCtx
  **/
  **/
 var ObjectCtx = Expression.ObjectCtx = (function() {
 var ObjectCtx = Expression.ObjectCtx = (function() {
-		// CONSTRUCTOR
-		/**
-		 * Utility class for parseObject() below. isDocumentOk indicates that it is OK to use a Document in the current context.
-		 *
-		 * NOTE: deviation from Mongo code: accepts an `Object` of settings rather than a bitmask to help simplify the interface a little bit
-		 *
-		 * @class ObjectCtx
-		 * @namespace mungedb-aggregate.pipeline.expressions.Expression
-		 * @module mungedb-aggregate
-		 * @constructor
-		 * @param opts
-		 *	@param [opts.isDocumentOk]	{Boolean}
-		 *	@param [opts.isTopLevel]	{Boolean}
-		 *	@param [opts.isInclusionOk]	{Boolean}
-		 **/
-		var klass = function ObjectCtx(opts /*= {isDocumentOk:..., isTopLevel:..., isInclusionOk:...}*/ ) {
-				if (!(opts instanceof Object && opts.constructor == Object)) throw new Error("opts is required and must be an Object containing named args");
-				for (var k in opts) { // assign all given opts to self so long as they were part of klass.prototype as undefined properties
-						if (opts.hasOwnProperty(k) && proto.hasOwnProperty(k) && proto[k] === undefined) this[k] = opts[k];
-				}
-		}, base = Object,
-				proto = klass.prototype = Object.create(base.prototype, {
-						constructor: {
-								value: klass
-						}
-				});
+                // CONSTRUCTOR
+                /**
+                 * Utility class for parseObject() below. isDocumentOk indicates that it is OK to use a Document in the current context.
+                 *
+                 * NOTE: deviation from Mongo code: accepts an `Object` of settings rather than a bitmask to help simplify the interface a little bit
+                 *
+                 * @class ObjectCtx
+                 * @namespace mungedb-aggregate.pipeline.expressions.Expression
+                 * @module mungedb-aggregate
+                 * @constructor
+                 * @param opts
+                 *      @param [opts.isDocumentOk]      {Boolean}
+                 *      @param [opts.isTopLevel]        {Boolean}
+                 *      @param [opts.isInclusionOk]     {Boolean}
+                 **/
+                var klass = function ObjectCtx(opts /*= {isDocumentOk:..., isTopLevel:..., isInclusionOk:...}*/ ) {
+                                if (!(opts instanceof Object && opts.constructor == Object)) throw new Error("opts is required and must be an Object containing named args");
+                                for (var k in opts) { // assign all given opts to self so long as they were part of klass.prototype as undefined properties
+                                                if (opts.hasOwnProperty(k) && proto.hasOwnProperty(k) && proto[k] === undefined) this[k] = opts[k];
+                                }
+                }, base = Object,
+                                proto = klass.prototype = Object.create(base.prototype, {
+                                                constructor: {
+                                                                value: klass
+                                                }
+                                });
 
 
-		// PROTOTYPE MEMBERS
-		proto.isDocumentOk =
-				proto.isTopLevel =
-				proto.isInclusionOk = undefined;
+                // PROTOTYPE MEMBERS
+                proto.isDocumentOk =
+                                proto.isTopLevel =
+                                proto.isInclusionOk = undefined;
 
 
-		return klass;
+                return klass;
 })();
 })();
 
 
 proto.removeFieldPrefix = function removeFieldPrefix(prefixedField) {
 proto.removeFieldPrefix = function removeFieldPrefix(prefixedField) {
-		if (prefixedField.indexOf("\0") !== -1) {
-				// field path must not contain embedded null characters - 16419
-		}
-		if (prefixedField[0] !== '$') {
-				// "field path references must be prefixed with a '$'"
-		}
-		return prefixedField.slice(1);
+                if (prefixedField.indexOf("\0") !== -1) {
+                                // field path must not contain embedded null characters - 16419
+                }
+                if (prefixedField[0] !== '$') {
+                                // "field path references must be prefixed with a '$'"
+                }
+                return prefixedField.slice(1);
 };
 };
 var KIND_UNKNOWN = 0,
 var KIND_UNKNOWN = 0,
-		KIND_NOTOPERATOR = 1,
-		KIND_OPERATOR = 2;
+                KIND_NOTOPERATOR = 1,
+                KIND_OPERATOR = 2;
 /**
 /**
  * Parse an Object.  The object could represent a functional expression or a Document expression.
  * Parse an Object.  The object could represent a functional expression or a Document expression.
  *
  *
  * An object expression can take any of the following forms:
  * An object expression can take any of the following forms:
  *
  *
- *	f0: {f1: ..., f2: ..., f3: ...}
- *	f0: {$operator:[operand1, operand2, ...]}
+ *      f0: {f1: ..., f2: ..., f3: ...}
+ *      f0: {$operator:[operand1, operand2, ...]}
  *
  *
  * @static
  * @static
  * @method parseObject
  * @method parseObject
- * @param obj	the element representing the object
- * @param ctx	a MiniCtx representing the options above
+ * @param obj   the element representing the object
+ * @param ctx   a MiniCtx representing the options above
  * @returns the parsed Expression
  * @returns the parsed Expression
  **/
  **/
 klass.parseObject = function parseObject(obj, ctx, vps) {
 klass.parseObject = function parseObject(obj, ctx, vps) {
-		if (!(ctx instanceof ObjectCtx)) throw new Error("ctx must be ObjectCtx");
-		var kind = KIND_UNKNOWN,
-				pExpression, // the result
-				pExpressionObject; // the alt result
-		if (obj === undefined || obj == {}) return new ObjectExpression();
-		var fieldNames = Object.keys(obj);
-		if (fieldNames.length === 0) { //NOTE: Added this for mongo 2.5 port of document sources. Should reconsider when porting the expressions themselves
-				return new ObjectExpression();
-		}
-		for (var fieldCount = 0, n = fieldNames.length; fieldCount < n; ++fieldCount) {
-				var pFieldName = fieldNames[fieldCount];
+                if (!(ctx instanceof ObjectCtx)) throw new Error("ctx must be ObjectCtx");
+                var kind = KIND_UNKNOWN,
+                                pExpression, // the result
+                                pExpressionObject; // the alt result
+                if (obj === undefined || obj == {}) return new ObjectExpression();
+                var fieldNames = Object.keys(obj);
+                if (fieldNames.length === 0) { //NOTE: Added this for mongo 2.5 port of document sources. Should reconsider when porting the expressions themselves
+                                return new ObjectExpression();
+                }
+                for (var fieldCount = 0, n = fieldNames.length; fieldCount < n; ++fieldCount) {
+                                var pFieldName = fieldNames[fieldCount];
 
 
-				if (pFieldName[0] === "$") {
-						if (fieldCount !== 0)
-								throw new Error("the operator must be the only field in a pipeline object (at '" + pFieldName + "'.; code 16410");
+                                if (pFieldName[0] === "$") {
+                                                if (fieldCount !== 0)
+                                                                throw new Error("the operator must be the only field in a pipeline object (at '" + pFieldName + "'.; code 16410");
 
 
-						if (ctx.isTopLevel)
-								throw new Error("$expressions are not allowed at the top-level of $project; code 16404");
-						kind = KIND_OPERATOR; //we've determined this "object" is an operator expression
-						pExpression = Expression.parseExpression(pFieldName, obj[pFieldName], vps);
-				} else {
-						if (kind === KIND_OPERATOR)
-								throw new Error("this object is already an operator expression, and can't be used as a document expression (at '" + pFieldName + "'.; code 15990");
+                                                if (ctx.isTopLevel)
+                                                                throw new Error("$expressions are not allowed at the top-level of $project; code 16404");
+                                                kind = KIND_OPERATOR; //we've determined this "object" is an operator expression
+                                                pExpression = Expression.parseExpression(pFieldName, obj[pFieldName], vps);
+                                } else {
+                                                if (kind === KIND_OPERATOR)
+                                                                throw new Error("this object is already an operator expression, and can't be used as a document expression (at '" + pFieldName + "'.; code 15990");
 
 
-						if (!ctx.isTopLevel && pFieldName.indexOf(".") != -1)
-								throw new Error("dotted field names are only allowed at the top level; code 16405");
-						if (pExpression === undefined) { // if it's our first time, create the document expression
-								if (!ctx.isDocumentOk)
-										throw new Error("document not allowed in this context"); // CW TODO error: document not allowed in this context
-								pExpression = pExpressionObject = new ObjectExpression(); //check for top level?
-								kind = KIND_NOTOPERATOR; //this "object" is not an operator expression
-						}
-						var fieldValue = obj[pFieldName];
-						switch (typeof(fieldValue)) {
-								case "object":
-										// it's a nested document
-										var subCtx = new ObjectCtx({
-												isDocumentOk: ctx.isDocumentOk,
-												isInclusionOk: ctx.isInclusionOk
-										});
-										pExpressionObject.addField(pFieldName, Expression.parseObject(fieldValue, subCtx, vps));
-										break;
-								case "string":
-										// it's a renamed field		// CW TODO could also be a constant
-										var pathExpr = new FieldPathExpression.parse(fieldValue);
-										pExpressionObject.addField(pFieldName, pathExpr);
-										break;
-								case "boolean":
-								case "number":
-										// it's an inclusion specification
-										if (fieldValue) {
-												if (!ctx.isInclusionOk)
-														throw new Error("field inclusion is not allowed inside of $expressions; code 16420");
-												pExpressionObject.includePath(pFieldName);
-										} else {
-												if (!(ctx.isTopLevel && fn == Document.ID_PROPERTY_NAME))
-														throw new Error("The top-level " + Document.ID_PROPERTY_NAME + " field is the only field currently supported for exclusion; code 16406");
-												pExpressionObject.excludeId = true;
-										}
-										break;
-								default:
-										throw new Error("disallowed field type " + (fieldValue ? fieldValue.constructor.name + ":" : "") + typeof(fieldValue) + " in object expression (at '" + pFieldName + "')");
-						}
-				}
-		}
-		return pExpression;
+                                                if (!ctx.isTopLevel && pFieldName.indexOf(".") != -1)
+                                                                throw new Error("dotted field names are only allowed at the top level; code 16405");
+                                                if (pExpression === undefined) { // if it's our first time, create the document expression
+                                                                if (!ctx.isDocumentOk)
+                                                                                throw new Error("document not allowed in this context"); // CW TODO error: document not allowed in this context
+                                                                pExpression = pExpressionObject = new ObjectExpression(); //check for top level?
+                                                                kind = KIND_NOTOPERATOR; //this "object" is not an operator expression
+                                                }
+                                                var fieldValue = obj[pFieldName];
+                                                switch (typeof(fieldValue)) {
+                                                                case "object":
+                                                                                // it's a nested document
+                                                                                var subCtx = new ObjectCtx({
+                                                                                                isDocumentOk: ctx.isDocumentOk,
+                                                                                                isInclusionOk: ctx.isInclusionOk
+                                                                                });
+                                                                                pExpressionObject.addField(pFieldName, Expression.parseObject(fieldValue, subCtx, vps));
+                                                                                break;
+                                                                case "string":
+                                                                                // it's a renamed field         // CW TODO could also be a constant
+                                                                                var pathExpr = new FieldPathExpression.parse(fieldValue);
+                                                                                pExpressionObject.addField(pFieldName, pathExpr);
+                                                                                break;
+                                                                case "boolean":
+                                                                case "number":
+                                                                                // it's an inclusion specification
+                                                                                if (fieldValue) {
+                                                                                                if (!ctx.isInclusionOk)
+                                                                                                                throw new Error("field inclusion is not allowed inside of $expressions; code 16420");
+                                                                                                pExpressionObject.includePath(pFieldName);
+                                                                                } else {
+                                                                                                if (!(ctx.isTopLevel && fn == Document.ID_PROPERTY_NAME))
+                                                                                                                throw new Error("The top-level " + Document.ID_PROPERTY_NAME + " field is the only field currently supported for exclusion; code 16406");
+                                                                                                pExpressionObject.excludeId = true;
+                                                                                }
+                                                                                break;
+                                                                default:
+                                                                                throw new Error("disallowed field type " + (fieldValue ? fieldValue.constructor.name + ":" : "") + typeof(fieldValue) + " in object expression (at '" + pFieldName + "')");
+                                                }
+                                }
+                }
+                return pExpression;
 };
 };
 
 
 
 
 klass.expressionParserMap = {};
 klass.expressionParserMap = {};
 
 
 klass.registerExpression = function registerExpression(key, parserFunc) {
 klass.registerExpression = function registerExpression(key, parserFunc) {
-		if (key in klass.expressionParserMap) {
-				throw new Error("Duplicate expression registrarion for " + key);
-		}
-		klass.expressionParserMap[key] = parserFunc;
-		return 0; // Should
+                if (key in klass.expressionParserMap) {
+                                throw new Error("Duplicate expression registrarion for " + key);
+                }
+                klass.expressionParserMap[key] = parserFunc;
+                return 0; // Should
 };
 };
 
 
 /**
 /**
@@ -185,15 +185,15 @@ klass.registerExpression = function registerExpression(key, parserFunc) {
  *
  *
  * @static
  * @static
  * @method parseExpression
  * @method parseExpression
- * @param opName	the name of the (prefix) operator
- * @param obj	the BSONElement to parse
+ * @param opName        the name of the (prefix) operator
+ * @param obj   the BSONElement to parse
  * @returns the parsed Expression
  * @returns the parsed Expression
  **/
  **/
 klass.parseExpression = function parseExpression(exprKey, exprValue, vps) {
 klass.parseExpression = function parseExpression(exprKey, exprValue, vps) {
-		if (!(exprKey in Expression.expressionParserMap)) {
-				throw new Error("Invalid operator : " + exprKey);
-		}
-		return Expression.expressionParserMap[exprKey](exprValue, vps);
+                if (!(exprKey in Expression.expressionParserMap)) {
+                                throw new Error("Invalid operator : " + exprKey);
+                }
+                return Expression.expressionParserMap[exprKey](exprValue, vps);
 };
 };
 
 
 /**
 /**
@@ -224,9 +224,9 @@ klass.parseOperand = function parseOperand(exprElement, vps) {
  * @returns the field path with the prefix removed
  * @returns the field path with the prefix removed
  **/
  **/
 klass.removeFieldPrefix = function removeFieldPrefix(prefixedField) {
 klass.removeFieldPrefix = function removeFieldPrefix(prefixedField) {
-		if (prefixedField.indexOf("\0") != -1) throw new Error("field path must not contain embedded null characters; code 16419");
-		if (prefixedField[0] !== "$") throw new Error("field path references must be prefixed with a '$' ('" + prefixedField + "'); code 15982");
-		return prefixedField.substr(1);
+                if (prefixedField.indexOf("\0") != -1) throw new Error("field path must not contain embedded null characters; code 16419");
+                if (prefixedField[0] !== "$") throw new Error("field path references must be prefixed with a '$' ('" + prefixedField + "'); code 15982");
+                return prefixedField.substr(1);
 };
 };
 
 
 
 
@@ -238,7 +238,7 @@ klass.removeFieldPrefix = function removeFieldPrefix(prefixedField) {
  * @returns the computed value
  * @returns the computed value
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(obj) {
 proto.evaluateInternal = function evaluateInternal(obj) {
-		throw new Error("WAS NOT IMPLEMENTED BY INHERITOR!");
+                throw new Error("WAS NOT IMPLEMENTED BY INHERITOR!");
 };
 };
 
 
 /**
 /**
@@ -255,7 +255,7 @@ proto.evaluateInternal = function evaluateInternal(obj) {
  * @returns the optimized Expression
  * @returns the optimized Expression
  **/
  **/
 proto.optimize = function optimize() {
 proto.optimize = function optimize() {
-		throw new Error("WAS NOT IMPLEMENTED BY INHERITOR!");
+                throw new Error("WAS NOT IMPLEMENTED BY INHERITOR!");
 };
 };
 
 
 /**
 /**
@@ -265,11 +265,11 @@ proto.optimize = function optimize() {
  * If any other Expression is an ancestor, or in other cases where {a:1} inclusion objects aren't allowed, they get NULL.
  * If any other Expression is an ancestor, or in other cases where {a:1} inclusion objects aren't allowed, they get NULL.
  *
  *
  * @method addDependencies
  * @method addDependencies
- * @param deps	output parameter
- * @param path	path to self if all ancestors are ExpressionObjects.
+ * @param deps  output parameter
+ * @param path  path to self if all ancestors are ExpressionObjects.
  **/
  **/
 proto.addDependencies = function addDependencies(deps, path) {
 proto.addDependencies = function addDependencies(deps, path) {
-		throw new Error("WAS NOT IMPLEMENTED BY INHERITOR!");
+                throw new Error("WAS NOT IMPLEMENTED BY INHERITOR!");
 };
 };
 
 
 /**
 /**
@@ -277,11 +277,11 @@ proto.addDependencies = function addDependencies(deps, path) {
  * @method getIsSimple
  * @method getIsSimple
  **/
  **/
 proto.getIsSimple = function getIsSimple() {
 proto.getIsSimple = function getIsSimple() {
-		return false;
+                return false;
 };
 };
 
 
 proto.toMatcherBson = function toMatcherBson() {
 proto.toMatcherBson = function toMatcherBson() {
-		throw new Error("WAS NOT IMPLEMENTED BY INHERITOR!"); //verify(false && "Expression::toMatcherBson()");
+                throw new Error("WAS NOT IMPLEMENTED BY INHERITOR!"); //verify(false && "Expression::toMatcherBson()");
 };
 };
 
 
 
 

+ 33 - 33
lib/pipeline/expressions/FieldPathExpression.js

@@ -106,36 +106,36 @@ proto.optimize = function optimize() {
  * @returns the field found; could be an array
  * @returns the field found; could be an array
  **/
  **/
 proto._evaluatePath = function _evaluatePath(obj, i, len){
 proto._evaluatePath = function _evaluatePath(obj, i, len){
-	var fieldName = this.path.fields[i],
-		field = obj[fieldName]; // It is possible we won't have an obj (document) and we need to not fail if that is the case
-
-	// if the field doesn't exist, quit with an undefined value
-	if (field === undefined) return undefined;
-
-	// if we've hit the end of the path, stop
-	if (++i >= len) return field;
-
-	// We're diving deeper.  If the value was null, return null
-	if(field === null) return undefined;
-
-	if (field.constructor === Object) {
-		return this._evaluatePath(field, i, len);
-	} else if (Array.isArray(field)) {
-		var results = [];
-		for (var i2 = 0, l2 = field.length; i2 < l2; i2++) {
-			var subObj = field[i2],
-				subObjType = typeof(subObj);
-			if (subObjType === "undefined" || subObj === null) {
-				results.push(subObj);
-			} else if (subObj.constructor === Object) {
-				results.push(this._evaluatePath(subObj, i, len));
-			} else {
-				throw new Error("the element '" + fieldName + "' along the dotted path '" + this.path.getPath() + "' is not an object, and cannot be navigated.; code 16014");
-			}
-		}
-		return results;
-	}
-	return undefined;
+        var fieldName = this.path.fields[i],
+                field = obj[fieldName]; // It is possible we won't have an obj (document) and we need to not fail if that is the case
+
+        // if the field doesn't exist, quit with an undefined value
+        if (field === undefined) return undefined;
+
+        // if we've hit the end of the path, stop
+        if (++i >= len) return field;
+
+        // We're diving deeper.  If the value was null, return null
+        if(field === null) return undefined;
+
+        if (field.constructor === Object) {
+                return this._evaluatePath(field, i, len);
+        } else if (Array.isArray(field)) {
+                var results = [];
+                for (var i2 = 0, l2 = field.length; i2 < l2; i2++) {
+                        var subObj = field[i2],
+                                subObjType = typeof(subObj);
+                        if (subObjType === "undefined" || subObj === null) {
+                                results.push(subObj);
+                        } else if (subObj.constructor === Object) {
+                                results.push(this._evaluatePath(subObj, i, len));
+                        } else {
+                                throw new Error("the element '" + fieldName + "' along the dotted path '" + this.path.getPath() + "' is not an object, and cannot be navigated.; code 16014");
+                        }
+                }
+                return results;
+        }
+        return undefined;
 };
 };
 
 
 proto.evaluatePathArray = function evaluatePathArray(index, input) {
 proto.evaluatePathArray = function evaluatePathArray(index, input) {
@@ -175,11 +175,11 @@ proto.evaluatePath = function(index, input) {
 
 
 
 
 proto.optimize = function(){
 proto.optimize = function(){
-	return this;
+        return this;
 };
 };
 
 
 proto.addDependencies = function addDependencies(deps){
 proto.addDependencies = function addDependencies(deps){
-	if(this.path.fields[0] === "CURRENT" || this.path.fields[0] === "ROOT") {
+        if(this.path.fields[0] === "CURRENT" || this.path.fields[0] === "ROOT") {
             if(this.path.fields.length === 1) {
             if(this.path.fields.length === 1) {
                 deps[""] = 1;
                 deps[""] = 1;
             } else {
             } else {
@@ -190,7 +190,7 @@ proto.addDependencies = function addDependencies(deps){
 
 
 // renamed write to get because there are no streams
 // renamed write to get because there are no streams
 proto.getFieldPath = function getFieldPath(usePrefix){
 proto.getFieldPath = function getFieldPath(usePrefix){
-	return this.path.getPath(usePrefix);
+        return this.path.getPath(usePrefix);
 };
 };
 
 
 proto.serialize = function toJSON(){
 proto.serialize = function toJSON(){

+ 140 - 140
lib/pipeline/expressions/FieldRangeExpression.js

@@ -6,9 +6,9 @@
  * Field ranges are meant to match up with classic Matcher semantics, and therefore are conjunctions.
  * Field ranges are meant to match up with classic Matcher semantics, and therefore are conjunctions.
  *
  *
  * For example, these appear in mongo shell predicates in one of these forms:
  * For example, these appear in mongo shell predicates in one of these forms:
- *	{ a : C } -> (a == C) // degenerate "point" range
- *	{ a : { $lt : C } } -> (a < C) // open range
- *	{ a : { $gt : C1, $lte : C2 } } -> ((a > C1) && (a <= C2)) // closed
+ *      { a : C } -> (a == C) // degenerate "point" range
+ *      { a : { $lt : C } } -> (a < C) // open range
+ *      { a : { $gt : C1, $lte : C2 } } -> ((a > C1) && (a <= C2)) // closed
  *
  *
  * When initially created, a field range only includes one end of the range.  Additional points may be added via intersect().
  * When initially created, a field range only includes one end of the range.  Additional points may be added via intersect().
  *
  *
@@ -25,135 +25,135 @@
  * @returns the newly created field range expression
  * @returns the newly created field range expression
  **/
  **/
 var FieldRangeExpression = module.exports = function FieldRangeExpression(pathExpr, cmpOp, value){
 var FieldRangeExpression = module.exports = function FieldRangeExpression(pathExpr, cmpOp, value){
-	if (arguments.length !== 3) throw new Error("args expected: pathExpr, cmpOp, and value");
-	this.pathExpr = pathExpr;
-	this.range = new Range({cmpOp:cmpOp, value:value});
+        if (arguments.length !== 3) throw new Error("args expected: pathExpr, cmpOp, and value");
+        this.pathExpr = pathExpr;
+        this.range = new Range({cmpOp:cmpOp, value:value});
 }, klass = FieldRangeExpression, Expression = require("./Expression"), base = Expression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = FieldRangeExpression, Expression = require("./Expression"), base = Expression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-	ConstantExpression = require("./ConstantExpression");
+        ConstantExpression = require("./ConstantExpression");
 
 
 // NESTED CLASSES
 // NESTED CLASSES
 var Range = (function(){
 var Range = (function(){
-	/**
-	 * create a new Range; opts is either {cmpOp:..., value:...} or {bottom:..., isBottomOpen:..., top:..., isTopOpen:...}
-	 * @private
-	 **/
-	var klass = function Range(opts){
-		this.isBottomOpen = this.isTopOpen = false;
-		this.bottom = this.top = undefined;
-		if(opts.hasOwnProperty("cmpOp") && opts.hasOwnProperty("value")){
-			switch (opts.cmpOp) {
-				case Expression.CmpOp.EQ:
-					this.bottom = this.top = opts.value;
-					break;
-
-				case Expression.CmpOp.GT:
-					this.isBottomOpen = true;
-					/* falls through */
-				case Expression.CmpOp.GTE:
-					this.isTopOpen = true;
-					this.bottom = opts.value;
-					break;
-
-				case Expression.CmpOp.LT:
-					this.isTopOpen = true;
-					/* falls through */
-				case Expression.CmpOp.LTE:
-					this.isBottomOpen = true;
-					this.top = opts.value;
-					break;
-
-				case Expression.CmpOp.NE:
-				case Expression.CmpOp.CMP:
-					throw new Error("CmpOp not allowed: " + opts.cmpOp);
-
-				default:
-					throw new Error("Unexpected CmpOp: " + opts.cmpOp);
-			}
-		}else{
-			this.bottom = opts.bottom;
-			this.isBottomOpen = opts.isBottomOpen;
-			this.top = opts.top;
-			this.isTopOpen = opts.isTopOpen;
-		}
-	}, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
-
-	// PROTOTYPE MEMBERS
-	proto.intersect = function intersect(range){
-		// Find the max of the bottom end of ranges
-		var maxBottom = range.bottom,
-			maxBottomOpen = range.isBottomOpen;
-		if(this.bottom !== undefined){
-			if(range.bottom === undefined){
-				maxBottom = this.bottom;
-				maxBottomOpen = this.isBottomOpen;
-			}else{
-				if(Value.compare(this.bottom, range.bottom) === 0){
-					maxBottomOpen = this.isBottomOpen || range.isBottomOpen;
-				}else{
-					maxBottom = this.bottom;
-					maxBottomOpen = this.isBottomOpen;
-				}
-			}
-		}
-		// Find the min of the tops of the ranges
-		var minTop = range.top,
-			minTopOpen = range.isTopOpen;
-		if(this.top !== undefined){
-			if(range.top === undefined){
-				minTop = this.top;
-				minTopOpen = this.isTopOpen;
-			}else{
-				if(Value.compare(this.top, range.top) === 0){
-					minTopOpen = this.isTopOpen || range.isTopOpen;
-				}else{
-					minTop = this.top;
-					minTopOpen = this.isTopOpen;
-				}
-			}
-		}
-		if(Value.compare(maxBottom, minTop) <= 0)
-			return new Range({bottom:maxBottom, isBottomOpen:maxBottomOpen, top:minTop, isTopOpen:minTopOpen});
-		return null; // empty intersection
-	};
-
-	proto.contains = function contains(value){
-		var cmp;
-		if(this.bottom !== undefined){
-			cmp = Value.compare(value, this.bottom);
-			if(cmp < 0) return false;
-			if(this.isBottomOpen && cmp === 0) return false;
-		}
-		if(this.top !== undefined){
-			cmp = Value.compare(value, this.top);
-			if(cmp > 0) return false;
-			if(this.isTopOpen && cmp === 0) return false;
-		}
-		return true;
-	};
-
-	return klass;
+        /**
+         * create a new Range; opts is either {cmpOp:..., value:...} or {bottom:..., isBottomOpen:..., top:..., isTopOpen:...}
+         * @private
+         **/
+        var klass = function Range(opts){
+                this.isBottomOpen = this.isTopOpen = false;
+                this.bottom = this.top = undefined;
+                if(opts.hasOwnProperty("cmpOp") && opts.hasOwnProperty("value")){
+                        switch (opts.cmpOp) {
+                                case Expression.CmpOp.EQ:
+                                        this.bottom = this.top = opts.value;
+                                        break;
+
+                                case Expression.CmpOp.GT:
+                                        this.isBottomOpen = true;
+                                        /* falls through */
+                                case Expression.CmpOp.GTE:
+                                        this.isTopOpen = true;
+                                        this.bottom = opts.value;
+                                        break;
+
+                                case Expression.CmpOp.LT:
+                                        this.isTopOpen = true;
+                                        /* falls through */
+                                case Expression.CmpOp.LTE:
+                                        this.isBottomOpen = true;
+                                        this.top = opts.value;
+                                        break;
+
+                                case Expression.CmpOp.NE:
+                                case Expression.CmpOp.CMP:
+                                        throw new Error("CmpOp not allowed: " + opts.cmpOp);
+
+                                default:
+                                        throw new Error("Unexpected CmpOp: " + opts.cmpOp);
+                        }
+                }else{
+                        this.bottom = opts.bottom;
+                        this.isBottomOpen = opts.isBottomOpen;
+                        this.top = opts.top;
+                        this.isTopOpen = opts.isTopOpen;
+                }
+        }, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+
+        // PROTOTYPE MEMBERS
+        proto.intersect = function intersect(range){
+                // Find the max of the bottom end of ranges
+                var maxBottom = range.bottom,
+                        maxBottomOpen = range.isBottomOpen;
+                if(this.bottom !== undefined){
+                        if(range.bottom === undefined){
+                                maxBottom = this.bottom;
+                                maxBottomOpen = this.isBottomOpen;
+                        }else{
+                                if(Value.compare(this.bottom, range.bottom) === 0){
+                                        maxBottomOpen = this.isBottomOpen || range.isBottomOpen;
+                                }else{
+                                        maxBottom = this.bottom;
+                                        maxBottomOpen = this.isBottomOpen;
+                                }
+                        }
+                }
+                // Find the min of the tops of the ranges
+                var minTop = range.top,
+                        minTopOpen = range.isTopOpen;
+                if(this.top !== undefined){
+                        if(range.top === undefined){
+                                minTop = this.top;
+                                minTopOpen = this.isTopOpen;
+                        }else{
+                                if(Value.compare(this.top, range.top) === 0){
+                                        minTopOpen = this.isTopOpen || range.isTopOpen;
+                                }else{
+                                        minTop = this.top;
+                                        minTopOpen = this.isTopOpen;
+                                }
+                        }
+                }
+                if(Value.compare(maxBottom, minTop) <= 0)
+                        return new Range({bottom:maxBottom, isBottomOpen:maxBottomOpen, top:minTop, isTopOpen:minTopOpen});
+                return null; // empty intersection
+        };
+
+        proto.contains = function contains(value){
+                var cmp;
+                if(this.bottom !== undefined){
+                        cmp = Value.compare(value, this.bottom);
+                        if(cmp < 0) return false;
+                        if(this.isBottomOpen && cmp === 0) return false;
+                }
+                if(this.top !== undefined){
+                        cmp = Value.compare(value, this.top);
+                        if(cmp > 0) return false;
+                        if(this.isTopOpen && cmp === 0) return false;
+                }
+                return true;
+        };
+
+        return klass;
 })();
 })();
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.evaluate = function evaluate(obj){
 proto.evaluate = function evaluate(obj){
-	if(this.range === undefined) return false;
-	var value = this.pathExpr.evaluate(obj);
-	if(value instanceof Array)
-		throw new Error('FieldRangeExpression cannot evaluate an array.');
-	return this.range.contains(value);
+        if(this.range === undefined) return false;
+        var value = this.pathExpr.evaluate(obj);
+        if(value instanceof Array)
+                throw new Error('FieldRangeExpression cannot evaluate an array.');
+        return this.range.contains(value);
 };
 };
 
 
 proto.optimize = function optimize(){
 proto.optimize = function optimize(){
-	if(this.range === undefined) return new ConstantExpression(false);
-	if(this.range.bottom === undefined && this.range.top === undefined) return new ConstantExpression(true);
-	return this;
+        if(this.range === undefined) return new ConstantExpression(false);
+        if(this.range.bottom === undefined && this.range.top === undefined) return new ConstantExpression(true);
+        return this;
 };
 };
 
 
 proto.addDependencies = function(deps){
 proto.addDependencies = function(deps){
-	return this.pathExpr.addDependencies(deps);
+        return this.pathExpr.addDependencies(deps);
 };
 };
 
 
 /**
 /**
@@ -171,34 +171,34 @@ proto.addDependencies = function(deps){
  * @param pValue the value to compare against
  * @param pValue the value to compare against
  **/
  **/
 proto.intersect = function intersect(cmpOp, value){
 proto.intersect = function intersect(cmpOp, value){
-	this.range = this.range.intersect(new Range({cmpOp:cmpOp, value:value}));
+        this.range = this.range.intersect(new Range({cmpOp:cmpOp, value:value}));
 };
 };
 
 
 proto.toJSON = function toJSON(){
 proto.toJSON = function toJSON(){
-	if (this.range === undefined) return false; //nothing will satisfy this predicate
-	if (this.range.top === undefined && this.range.bottom === undefined) return true; // any value will satisfy this predicate
-
-	// FIXME Append constant values using the $const operator.  SERVER-6769
-
-	var json = {};
-	if (this.range.top === this.range.bottom) {
-		json[Expression.CmpOp.EQ] = [this.pathExpr.toJSON(), this.range.top];
-	}else{
-		var leftOp = {};
-		if (this.range.bottom !== undefined) {
-			leftOp[this.range.isBottomOpen ? Expression.CmpOp.GT : Expression.CmpOp.GTE] = [this.pathExpr.toJSON(), this.range.bottom];
-			if (this.range.top === undefined) return leftOp;
-		}
-
-		var rightOp = {};
-		if(this.range.top !== undefined){
-			rightOp[this.range.isTopOpen ? Expression.CmpOp.LT : Expression.CmpOp.LTE] = [this.pathExpr.toJSON(), this.range.top];
-			if (this.range.bottom === undefined) return rightOp;
-		}
-
-		json.$and = [leftOp, rightOp];
-	}
-	return json;
+        if (this.range === undefined) return false; //nothing will satisfy this predicate
+        if (this.range.top === undefined && this.range.bottom === undefined) return true; // any value will satisfy this predicate
+
+        // FIXME Append constant values using the $const operator.  SERVER-6769
+
+        var json = {};
+        if (this.range.top === this.range.bottom) {
+                json[Expression.CmpOp.EQ] = [this.pathExpr.toJSON(), this.range.top];
+        }else{
+                var leftOp = {};
+                if (this.range.bottom !== undefined) {
+                        leftOp[this.range.isBottomOpen ? Expression.CmpOp.GT : Expression.CmpOp.GTE] = [this.pathExpr.toJSON(), this.range.bottom];
+                        if (this.range.top === undefined) return leftOp;
+                }
+
+                var rightOp = {};
+                if(this.range.top !== undefined){
+                        rightOp[this.range.isTopOpen ? Expression.CmpOp.LT : Expression.CmpOp.LTE] = [this.pathExpr.toJSON(), this.range.top];
+                        if (this.range.bottom === undefined) return rightOp;
+                }
+
+                json.$and = [leftOp, rightOp];
+        }
+        return json;
 };
 };
 
 
 //TODO: proto.addToBson = ...?
 //TODO: proto.addToBson = ...?

+ 13 - 13
lib/pipeline/expressions/HourExpression.js

@@ -1,36 +1,36 @@
 "use strict";
 "use strict";
 
 
-/** 
- * An $hour pipeline expression. 
- * @see evaluateInternal 
+/**
+ * An $hour pipeline expression.
+ * @see evaluateInternal
  * @class HourExpression
  * @class HourExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
 var HourExpression = module.exports = function HourExpression(){
 var HourExpression = module.exports = function HourExpression(){
-	this.fixedArity(1);
-	if (arguments.length !== 1) throw new Error("one arg expected");
-	base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one arg expected");
+    base.call(this);
 }, klass = HourExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = HourExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$hour";
+    return "$hour";
 };
 };
 
 
 // DEPENDENCIES
 // DEPENDENCIES
-var	Expression = require("./Expression");
+var Expression = require("./Expression");
 
 
-/** 
- * Takes a date and returns the hour between 0 and 23. 
+/**
+ * Takes a date and returns the hour between 0 and 23.
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars){
 proto.evaluateInternal = function evaluateInternal(vars){
-	var date = this.operands[0].evaluateInternal(vars);
-	return date.getUTCHours();
+    var date = this.operands[0].evaluateInternal(vars);
+    return date.getUTCHours();
 };
 };
 
 
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$hour",klass.parse(HourExpression));
+Expression.registerExpression("$hour",base.parse(HourExpression));

+ 15 - 15
lib/pipeline/expressions/IfNullExpression.js

@@ -9,23 +9,23 @@
  * @constructor
  * @constructor
  **/
  **/
 var IfNullExpression = module.exports = function IfNullExpression() {
 var IfNullExpression = module.exports = function IfNullExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 0) throw new Error("zero args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 0) throw new Error("zero args expected");
+    base.call(this);
 }, klass = IfNullExpression,
 }, klass = IfNullExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Expression = require("./Expression");
 var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$ifNull";
+                return "$ifNull";
 };
 };
 
 
 // virtuals from ExpressionNary
 // virtuals from ExpressionNary
@@ -35,11 +35,11 @@ proto.getOpName = function getOpName() {
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var left = this.operands[0].evaluateInternal(vars);
-		if (left !== undefined && left !== null) return left;
-		var right = this.operands[1].evaluateInternal(vars);
-		return right;
+    var left = this.operands[0].evaluateInternal(vars);
+    if (left !== undefined && left !== null) return left;
+    var right = this.operands[1].evaluateInternal(vars);
+    return right;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$ifNull", klass.parse(IfNullExpression));
+Expression.registerExpression("$ifNull", base.parse(IfNullExpression));

+ 16 - 16
lib/pipeline/expressions/MillisecondExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * An $millisecond pipeline expression.
  * An $millisecond pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class MillisecondExpression
  * @class MillisecondExpression
@@ -9,23 +9,23 @@
  * @constructor
  * @constructor
  **/
  **/
 var MillisecondExpression = module.exports = function MillisecondExpression() {
 var MillisecondExpression = module.exports = function MillisecondExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one arg expected");
-		base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one arg expected");
+    base.call(this);
 }, klass = MillisecondExpression,
 }, klass = MillisecondExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Expression = require("./Expression");
 var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$millisecond";
+    return "$millisecond";
 };
 };
 
 
 /**
 /**
@@ -33,11 +33,11 @@ proto.getOpName = function getOpName() {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var date = this.operands[0].evaluateInternal(vars);
-		return date.getUTCMilliseconds(); //TODO: incorrect for last millisecond of leap year, need to fix...
-		// currently leap milliseconds are unsupported in v8
-		// http://code.google.com/p/v8/issues/detail?id=1944
+    var date = this.operands[0].evaluateInternal(vars);
+    return date.getUTCMilliseconds(); //TODO: incorrect for last millisecond of leap year, need to fix...
+    // currently leap milliseconds are unsupported in v8
+    // http://code.google.com/p/v8/issues/detail?id=1944
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$millisecond", klass.parse(MillisecondExpression));
+Expression.registerExpression("$millisecond", base.parse(MillisecondExpression));

+ 15 - 15
lib/pipeline/expressions/MinuteExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * An $minute pipeline expression.
  * An $minute pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class MinuteExpression
  * @class MinuteExpression
@@ -9,33 +9,33 @@
  * @constructor
  * @constructor
  **/
  **/
 var MinuteExpression = module.exports = function MinuteExpression() {
 var MinuteExpression = module.exports = function MinuteExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one arg expected");
-		base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one arg expected");
+    base.call(this);
 }, klass = MinuteExpression,
 }, klass = MinuteExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Expression = require("./Expression");
 var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$minute";
+    return "$minute";
 };
 };
 
 
-/** 
+/**
  * Takes a date and returns the minute between 0 and 59.
  * Takes a date and returns the minute between 0 and 59.
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var date = this.operands[0].evaluateInternal(vars);
-		return date.getUTCMinutes();
+    var date = this.operands[0].evaluateInternal(vars);
+    return date.getUTCMinutes();
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$minute", klass.parse(MinuteExpression));
+Expression.registerExpression("$minute", base.parse(MinuteExpression));

+ 18 - 18
lib/pipeline/expressions/ModExpression.js

@@ -9,24 +9,24 @@
  * @constructor
  * @constructor
  **/
  **/
 var ModExpression = module.exports = function ModExpression() {
 var ModExpression = module.exports = function ModExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 0) throw new Error("zero args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 0) throw new Error("zero args expected");
+    base.call(this);
 }, klass = ModExpression,
 }, klass = ModExpression,
     base = require("./NaryExpression"),
     base = require("./NaryExpression"),
     proto = klass.prototype = Object.create(base.prototype, {
     proto = klass.prototype = Object.create(base.prototype, {
         constructor: {
         constructor: {
             value: klass
             value: klass
-	}
+        }
     });
     });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$mod";
+                return "$mod";
 };
 };
 
 
 /**
 /**
@@ -34,21 +34,21 @@ proto.getOpName = function getOpName() {
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		this.checkArgCount(2);
-		var left = this.operands[0].evaluateInternal(vars),
-				right = this.operands[1].evaluateInternal(vars);
-		if (left instanceof Date || right instanceof Date) throw new Error("$mod does not support dates; code 16374");
+                this.checkArgCount(2);
+                var left = this.operands[0].evaluateInternal(vars),
+                                right = this.operands[1].evaluateInternal(vars);
+                if (left instanceof Date || right instanceof Date) throw new Error("$mod does not support dates; code 16374");
 
 
-		// pass along jstNULLs and Undefineds
-		if (left === undefined || left === null) return left;
-		if (right === undefined || right === null) return right;
+                // pass along jstNULLs and Undefineds
+                if (left === undefined || left === null) return left;
+                if (right === undefined || right === null) return right;
 
 
-		// ensure we aren't modding by 0
-		right = Value.coerceToDouble(right);
-		if (right === 0) return undefined;
+                // ensure we aren't modding by 0
+                right = Value.coerceToDouble(right);
+                if (right === 0) return undefined;
 
 
-		left = Value.coerceToDouble(left);
-		return left % right;
+                left = Value.coerceToDouble(left);
+                return left % right;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */

+ 14 - 14
lib/pipeline/expressions/MonthExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * A $month pipeline expression.
  * A $month pipeline expression.
  * @see evaluate
  * @see evaluate
  * @class MonthExpression
  * @class MonthExpression
@@ -9,23 +9,23 @@
  * @constructor
  * @constructor
  **/
  **/
 var MonthExpression = module.exports = function MonthExpression() {
 var MonthExpression = module.exports = function MonthExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one arg expected");
-		base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one arg expected");
+    base.call(this);
 }, klass = MonthExpression,
 }, klass = MonthExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Expression = require("./Expression");
 var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$month";
+    return "$month";
 };
 };
 
 
 /**
 /**
@@ -33,9 +33,9 @@ proto.getOpName = function getOpName() {
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var date = this.operands[0].evaluateInternal(vars);
-		return date.getUTCMonth();
+    var date = this.operands[0].evaluateInternal(vars);
+    return date.getUTCMonth();
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$month", klass.parse(MonthExpression));
+Expression.registerExpression("$month", base.parse(MonthExpression));

+ 17 - 17
lib/pipeline/expressions/MultiplyExpression.js

@@ -1,16 +1,16 @@
 "use strict";
 "use strict";
 
 
-/** 
- * A $multiply pipeline expression. 
- * @see evaluateInternal 
+/**
+ * A $multiply pipeline expression.
+ * @see evaluateInternal
  * @class MultiplyExpression
  * @class MultiplyExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
 var MultiplyExpression = module.exports = function MultiplyExpression(){
 var MultiplyExpression = module.exports = function MultiplyExpression(){
-	if (arguments.length !== 1) throw new Error("one arg expected");
-	base.call(this);
+    if (arguments.length !== 0) throw new Error("one arg expected");
+    base.call(this);
 }, klass = MultiplyExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = MultiplyExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
@@ -19,23 +19,23 @@ var Value = require("../Value"),
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$multiply";
+        return "$multiply";
 };
 };
 
 
-/** 
- * Takes an array of one or more numbers and multiples them, returning the resulting product. 
+/**
+ * Takes an array of one or more numbers and multiples them, returning the resulting product.
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars){
 proto.evaluateInternal = function evaluateInternal(vars){
-	var product = 1;
-	for(var i = 0, n = this.operands.length; i < n; ++i){
-		var value = this.operands[i].evaluateInternal(vars);
-		if(value instanceof Date) throw new Error("$multiply does not support dates; code 16375");
-		product *= Value.coerceToDouble(value);
-	}
-	if(typeof(product) != "number") throw new Error("$multiply resulted in a non-numeric type; code 16418");
-	return product;
+    var product = 1;
+    for(var i = 0, n = this.operands.length; i < n; ++i){
+        var value = this.operands[i].evaluateInternal(vars);
+        if(value instanceof Date) throw new Error("$multiply does not support dates; code 16375");
+        product *= Value.coerceToDouble(value);
+    }
+    if(typeof(product) != "number") throw new Error("$multiply resulted in a non-numeric type; code 16418");
+    return product;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$multiply", klass.parse(MultiplyExpression));
+Expression.registerExpression("$multiply", base.parse(MultiplyExpression));

+ 4 - 4
lib/pipeline/expressions/NaryExpression.js

@@ -58,7 +58,7 @@ var ConstantExpression = require("./ConstantExpression");
 proto.evaluate = undefined; // evaluate(doc){ ... defined by inheritor ... }
 proto.evaluate = undefined; // evaluate(doc){ ... defined by inheritor ... }
 
 
 proto.getOpName = function getOpName(doc){
 proto.getOpName = function getOpName(doc){
-	throw new Error("NOT IMPLEMENTED BY INHERITOR");
+        throw new Error("NOT IMPLEMENTED BY INHERITOR");
 };
 };
 
 
 proto.optimize = function optimize(){
 proto.optimize = function optimize(){
@@ -101,8 +101,8 @@ proto.optimize = function optimize(){
 };
 };
 
 
 proto.addDependencies = function addDependencies(deps){
 proto.addDependencies = function addDependencies(deps){
-	for(var i = 0, l = this.operands.length; i < l; ++i)
-		this.operands[i].addDependencies(deps);
+        for(var i = 0, l = this.operands.length; i < l; ++i)
+                this.operands[i].addDependencies(deps);
 };
 };
 
 
 /**
 /**
@@ -111,7 +111,7 @@ proto.addDependencies = function addDependencies(deps){
  * @param pExpression the expression to add
  * @param pExpression the expression to add
  **/
  **/
 proto.addOperand = function addOperand(expr) {
 proto.addOperand = function addOperand(expr) {
-	this.operands.push(expr);
+        this.operands.push(expr);
 };
 };
 
 
 proto.serialize = function serialize() {
 proto.serialize = function serialize() {

+ 16 - 16
lib/pipeline/expressions/NotExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * A $not pipeline expression.
  * A $not pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class NotExpression
  * @class NotExpression
@@ -9,34 +9,34 @@
  * @constructor
  * @constructor
  **/
  **/
 var NotExpression = module.exports = function NotExpression() {
 var NotExpression = module.exports = function NotExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one arg expected");
-		base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one arg expected");
+    base.call(this);
 }, klass = NotExpression,
 }, klass = NotExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+    Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$not";
+    return "$not";
 };
 };
 
 
-/** 
+/**
  * Returns the boolean opposite value passed to it. When passed a true value, $not returns false; when passed a false value, $not returns true.
  * Returns the boolean opposite value passed to it. When passed a true value, $not returns false; when passed a false value, $not returns true.
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var op = this.operands[0].evaluateInternal(vars);
-		return !Value.coerceToBool(op);
+    var op = this.operands[0].evaluateInternal(vars);
+    return !Value.coerceToBool(op);
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$not", klass.parse(NotExpression));
+Expression.registerExpression("$not", base.parse(NotExpression));

+ 36 - 36
lib/pipeline/expressions/OrExpression.js

@@ -1,67 +1,67 @@
 "use strict";
 "use strict";
 
 
-/** 
- * An $or pipeline expression. 
- * @see evaluateInternal 
+/**
+ * An $or pipeline expression.
+ * @see evaluateInternal
  * @class OrExpression
  * @class OrExpression
  * @namespace mungedb-aggregate.pipeline.expressions
  * @namespace mungedb-aggregate.pipeline.expressions
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
 var OrExpression = module.exports = function OrExpression(){
 var OrExpression = module.exports = function OrExpression(){
-	if (arguments.length !== 0) throw new Error("zero args expected");
-	base.call(this);
+        if (arguments.length !== 0) throw new Error("zero args expected");
+        base.call(this);
 }, klass = OrExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 }, klass = OrExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-	ConstantExpression = require("./ConstantExpression"),
-	CoerceToBoolExpression = require("./CoerceToBoolExpression"),
-	Expression = require("./Expression");
+        ConstantExpression = require("./ConstantExpression"),
+        CoerceToBoolExpression = require("./CoerceToBoolExpression"),
+        Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$or";
+        return "$or";
 };
 };
 
 
-/** 
- * Takes an array of one or more values and returns true if any of the values in the array are true. Otherwise $or returns false. 
+/**
+ * Takes an array of one or more values and returns true if any of the values in the array are true. Otherwise $or returns false.
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars){
 proto.evaluateInternal = function evaluateInternal(vars){
-	for(var i = 0, n = this.operands.length; i < n; ++i){
-		var value = this.operands[i].evaluateInternal(vars);
-		if (Value.coerceToBool(value)) return true;
-	}
-	return false;
+        for(var i = 0, n = this.operands.length; i < n; ++i){
+                var value = this.operands[i].evaluateInternal(vars);
+                if (Value.coerceToBool(value)) return true;
+        }
+        return false;
 };
 };
 
 
 proto.optimize = function optimize() {
 proto.optimize = function optimize() {
-	var pE = base.prototype.optimize.call(this); // optimize the disjunction as much as possible
+        var pE = base.prototype.optimize.call(this); // optimize the disjunction as much as possible
 
 
-	if (!(pE instanceof OrExpression)) return pE; // if the result isn't a disjunction, we can't do anything
-	var pOr = pE;
+        if (!(pE instanceof OrExpression)) return pE; // if the result isn't a disjunction, we can't do anything
+        var pOr = pE;
 
 
-	// Check the last argument on the result; if it's not const (as promised
-	// by ExpressionNary::optimize(),) then there's nothing we can do.
-	var n = pOr.operands.length;
-	// ExpressionNary::optimize() generates an ExpressionConstant for {$or:[]}.
-	if (!n) throw new Error("OrExpression must have operands!");
-	var pLast = pOr.operands[n - 1];
-	if (!(pLast instanceof ConstantExpression)) return pE;
+        // Check the last argument on the result; if it's not const (as promised
+        // by ExpressionNary::optimize(),) then there's nothing we can do.
+        var n = pOr.operands.length;
+        // ExpressionNary::optimize() generates an ExpressionConstant for {$or:[]}.
+        if (!n) throw new Error("OrExpression must have operands!");
+        var pLast = pOr.operands[n - 1];
+        if (!(pLast instanceof ConstantExpression)) return pE;
 
 
-	// Evaluate and coerce the last argument to a boolean.  If it's true, then we can replace this entire expression.
-	var last = Value.coerceToBool();
-	if (last) return new ConstantExpression(true);
+        // Evaluate and coerce the last argument to a boolean.  If it's true, then we can replace this entire expression.
+        var last = Value.coerceToBool();
+        if (last) return new ConstantExpression(true);
 
 
-	// If we got here, the final operand was false, so we don't need it anymore.
-	// If there was only one other operand, we don't need the conjunction either.  Note we still need to keep the promise that the result will be a boolean.
-	if (n == 2) return new CoerceToBoolExpression(pOr.operands[0]);
+        // If we got here, the final operand was false, so we don't need it anymore.
+        // If there was only one other operand, we don't need the conjunction either.  Note we still need to keep the promise that the result will be a boolean.
+        if (n == 2) return new CoerceToBoolExpression(pOr.operands[0]);
 
 
-	// Remove the final "false" value, and return the new expression.
-	pOr.operands.length = n - 1;
-	return pE;
+        // Remove the final "false" value, and return the new expression.
+        pOr.operands.length = n - 1;
+        return pE;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$or", klass.parse(OrExpression));
+Expression.registerExpression("$or", base.parse(OrExpression));

+ 16 - 16
lib/pipeline/expressions/SecondExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * An $second pipeline expression.
  * An $second pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class SecondExpression
  * @class SecondExpression
@@ -9,23 +9,23 @@
  * @constructor
  * @constructor
  **/
  **/
 var SecondExpression = module.exports = function SecondExpression() {
 var SecondExpression = module.exports = function SecondExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one arg expected");
-		base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one arg expected");
+    base.call(this);
 }, klass = SecondExpression,
 }, klass = SecondExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Expression = require("./Expression");
 var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$second";
+                return "$second";
 };
 };
 
 
 /**
 /**
@@ -33,11 +33,11 @@ proto.getOpName = function getOpName() {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var date = this.operands[0].evaluateInternal(vars);
-		return date.getUTCSeconds(); //TODO: incorrect for last second of leap year, need to fix...
-		// currently leap seconds are unsupported in v8
-		// http://code.google.com/p/v8/issues/detail?id=1944
+                var date = this.operands[0].evaluateInternal(vars);
+                return date.getUTCSeconds(); //TODO: incorrect for last second of leap year, need to fix...
+                // currently leap seconds are unsupported in v8
+                // http://code.google.com/p/v8/issues/detail?id=1944
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$second", klass.parse(SecondExpression));
+Expression.registerExpression("$second", base.parse(SecondExpression));

+ 23 - 23
lib/pipeline/expressions/SetDifferenceExpression.js

@@ -9,24 +9,24 @@
  * @constructor
  * @constructor
  **/
  **/
 var SetDifferenceExpression = module.exports = function SetDifferenceExpression() {
 var SetDifferenceExpression = module.exports = function SetDifferenceExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 2) throw new Error("two args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 2) throw new Error("two args expected");
+    base.call(this);
 }, klass = SetDifferenceExpression,
 }, klass = SetDifferenceExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$setdifference";
+                return "$setdifference";
 };
 };
 
 
 /**
 /**
@@ -34,20 +34,20 @@ proto.getOpName = function getOpName() {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var array1 = this.operands[0].evaluateInternal(vars),
-				array2 = this.operands[1].evaluateInternal(vars);
-		if (array1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an array");
-		if (array2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an array");
+                var array1 = this.operands[0].evaluateInternal(vars),
+                                array2 = this.operands[1].evaluateInternal(vars);
+                if (array1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an array");
+                if (array2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an array");
 
 
-		var returnVec = [];
+                var returnVec = [];
 
 
-		array1.forEach(function(key) {
-				if (-1 === array2.indexOf(key)) {
-						returnVec.push(key);
-				}
-		}, this);
-		return returnVec;
+                array1.forEach(function(key) {
+                                if (-1 === array2.indexOf(key)) {
+                                                returnVec.push(key);
+                                }
+                }, this);
+                return returnVec;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$setdifference", klass.parse(SetDifferenceExpression));
+Expression.registerExpression("$setdifference", base.parse(SetDifferenceExpression));

+ 18 - 18
lib/pipeline/expressions/SetEqualsExpression.js

@@ -9,24 +9,24 @@
  * @constructor
  * @constructor
  **/
  **/
 var SetEqualsExpression = module.exports = function SetEqualsExpression() {
 var SetEqualsExpression = module.exports = function SetEqualsExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 2) throw new Error("two args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 2) throw new Error("two args expected");
+    base.call(this);
 }, klass = SetEqualsExpression,
 }, klass = SetEqualsExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$setequals";
+                return "$setequals";
 };
 };
 
 
 /**
 /**
@@ -34,13 +34,13 @@ proto.getOpName = function getOpName() {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var array1 = this.operands[0].evaluateInternal(vars),
-				array2 = this.operands[1].evaluateInternal(vars);
-		if (array1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an array");
-		if (array2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an array");
-		array1 = array2;
-		return array1;
+                var array1 = this.operands[0].evaluateInternal(vars),
+                                array2 = this.operands[1].evaluateInternal(vars);
+                if (array1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an array");
+                if (array2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an array");
+                array1 = array2;
+                return array1;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$setequals", klass.parse(SetEqualsExpression));
+Expression.registerExpression("$setequals", base.parse(SetEqualsExpression));

+ 19 - 19
lib/pipeline/expressions/SetIntersectionExpression.js

@@ -9,24 +9,24 @@
  * @constructor
  * @constructor
  **/
  **/
 var SetIntersectionExpression = module.exports = function SetIntersectionExpression() {
 var SetIntersectionExpression = module.exports = function SetIntersectionExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 2) throw new Error("two args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 2) throw new Error("two args expected");
+    base.call(this);
 }, klass = SetIntersectionExpression,
 }, klass = SetIntersectionExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$setIntersection";
+                return "$setIntersection";
 };
 };
 
 
 /**
 /**
@@ -34,15 +34,15 @@ proto.getOpName = function getOpName() {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var object1 = this.operands[0].evaluateInternal(vars),
-				object2 = this.operands[1].evaluateInternal(vars);
-		if (object1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an object");
-		if (object2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an object");
+                var object1 = this.operands[0].evaluateInternal(vars),
+                                object2 = this.operands[1].evaluateInternal(vars);
+                if (object1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an object");
+                if (object2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an object");
 
 
-		var result = object1.filter(function(n) {
-				return object2.indexOf(n) > -1;
-		});
+                var result = object1.filter(function(n) {
+                                return object2.indexOf(n) > -1;
+                });
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$setIntersection", klass.parse(SetIntersectionExpression));
+Expression.registerExpression("$setIntersection", base.parse(SetIntersectionExpression));

+ 50 - 50
lib/pipeline/expressions/SetIsSubsetExpression.js

@@ -9,47 +9,47 @@
  * @constructor
  * @constructor
  **/
  **/
 var SetIsSubsetExpression = module.exports = function SetIsSubsetExpression() {
 var SetIsSubsetExpression = module.exports = function SetIsSubsetExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 2) throw new Error("two args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 2) throw new Error("two args expected");
+    base.call(this);
 }, klass = SetIsSubsetExpression,
 }, klass = SetIsSubsetExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+    Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$setissubset";
+    return "$setissubset";
 };
 };
 
 
 proto.optimize = function optimize(cachedRhsSet, operands) {
 proto.optimize = function optimize(cachedRhsSet, operands) {
 
 
-		// This optimize needs to be done, eventually
+    // This optimize needs to be done, eventually
 
 
-		// // perfore basic optimizations
-		//     intrusive_ptr<Expression> optimized = ExpressionNary::optimize();
+    // // perfore basic optimizations
+    //     intrusive_ptr<Expression> optimized = ExpressionNary::optimize();
 
 
-		//     // if ExpressionNary::optimize() created a new value, return it directly
-		//     if (optimized.get() != this)
-		//         return optimized;
+    //     // if ExpressionNary::optimize() created a new value, return it directly
+    //     if (optimized.get() != this)
+    //         return optimized;
 
 
-		//     if (ExpressionConstant* ec = dynamic_cast<ExpressionConstant*>(vpOperand[1].get())) {
-		//         const Value rhs = ec->getValue();
-		//         uassert(17311, str::stream() << "both operands of $setIsSubset must be arrays. Second "
-		//                                      << "argument is of type: " << typeName(rhs.getType()),
-		//                 rhs.getType() == Array);
+    //     if (ExpressionConstant* ec = dynamic_cast<ExpressionConstant*>(vpOperand[1].get())) {
+    //         const Value rhs = ec->getValue();
+    //         uassert(17311, str::stream() << "both operands of $setIsSubset must be arrays. Second "
+    //                                      << "argument is of type: " << typeName(rhs.getType()),
+    //                 rhs.getType() == Array);
 
 
-		//         return new Optimized(arrayToSet(rhs), vpOperand);
-		//     }
+    //         return new Optimized(arrayToSet(rhs), vpOperand);
+    //     }
 
 
-		//     return optimized;
+    //     return optimized;
 
 
 };
 };
 
 
@@ -58,31 +58,31 @@ proto.optimize = function optimize(cachedRhsSet, operands) {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var array1 = this.operands[0].evaluateInternal(vars),
-				array2 = this.operands[1].evaluateInternal(vars);
-		if (array1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an array");
-		if (array2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an array");
-
-		var sizeOfArray1 = array1.length;
-		var sizeOfArray2 = array2.length;
-		var outerLoop = 0;
-		var innerLoop = 0;
-		for (outerLoop = 0; outerLoop < sizeOfArray1; outerLoop++) {
-				for (innerLoop = 0; innerLoop < sizeOfArray2; innerLoop++) {
-						if (array2[outerLoop] == array1[innerLoop])
-								break;
-				}
-
-				/* If the above inner loop was not broken at all then
-           array2[i] is not present in array1[] */
-				if (innerLoop == sizeOfArray2)
-						return false;
-		}
-
-		/* If we reach here then all elements of array2[] 
-      are present in array1[] */
-		return true;
+    var array1 = this.operands[0].evaluateInternal(vars),
+        array2 = this.operands[1].evaluateInternal(vars);
+    if (array1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an array");
+    if (array2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an array");
+
+    var sizeOfArray1 = array1.length;
+    var sizeOfArray2 = array2.length;
+    var outerLoop = 0;
+    var innerLoop = 0;
+    for (outerLoop = 0; outerLoop < sizeOfArray1; outerLoop++) {
+        for (innerLoop = 0; innerLoop < sizeOfArray2; innerLoop++) {
+            if (array2[outerLoop] == array1[innerLoop])
+                break;
+        }
+
+        /* If the above inner loop was not broken at all then
+         array2[i] is not present in array1[] */
+        if (innerLoop == sizeOfArray2)
+            return false;
+    }
+
+    /* If we reach here then all elements of array2[]
+     are present in array1[] */
+    return true;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$setissubset", klass.parse(SetIsSubsetExpression));
+Expression.registerExpression("$setissubset", base.parse(SetIsSubsetExpression));

+ 24 - 24
lib/pipeline/expressions/SetUnionExpression.js

@@ -9,24 +9,24 @@
  * @constructor
  * @constructor
  **/
  **/
 var SetUnionExpression = module.exports = function SetUnionExpression() {
 var SetUnionExpression = module.exports = function SetUnionExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 2) throw new Error("two args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 2) throw new Error("two args expected");
+    base.call(this);
 }, klass = SetUnionExpression,
 }, klass = SetUnionExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+                base = require("./NaryExpression"),
+                proto = klass.prototype = Object.create(base.prototype, {
+                                constructor: {
+                                                value: klass
+                                }
+                });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$setUnion";
+                return "$setUnion";
 };
 };
 
 
 /**
 /**
@@ -34,21 +34,21 @@ proto.getOpName = function getOpName() {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var object1 = this.operands[0].evaluateInternal(vars),
-				object2 = this.operands[1].evaluateInternal(vars);
-		if (object1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an object");
-		if (object2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an object");
+                var object1 = this.operands[0].evaluateInternal(vars),
+                                object2 = this.operands[1].evaluateInternal(vars);
+                if (object1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an object");
+                if (object2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an object");
 
 
-		var object3 = {};
-		for (var attrname1 in object1) {
-				object3[attrname1] = object1[attrname1];
-		}
-		for (var attrname2 in object2) {
-				object3[attrname2] = object2[attrname2];
-		}
+                var object3 = {};
+                for (var attrname1 in object1) {
+                                object3[attrname1] = object1[attrname1];
+                }
+                for (var attrname2 in object2) {
+                                object3[attrname2] = object2[attrname2];
+                }
 
 
-		return object3;
+                return object3;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$setUnion", klass.parse(SetUnionExpression));
+Expression.registerExpression("$setUnion", base.parse(SetUnionExpression));

+ 6 - 6
lib/pipeline/expressions/SizeExpression.js

@@ -16,25 +16,25 @@ var SizeExpression = module.exports = function SizeExpression() {
     proto = klass.prototype = Object.create(base.prototype, {
     proto = klass.prototype = Object.create(base.prototype, {
         constructor: {
         constructor: {
             value: klass
             value: klass
-	}
+        }
     });
     });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$size";
+                return "$size";
 };
 };
 
 
 /**
 /**
  * Takes an array and return the size.
  * Takes an array and return the size.
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var array = this.operands[0].evaluateInternal(vars);
-		if (array instanceof Date) throw new Error("$size does not support dates; code 16376");
-		return array.length;
+                var array = this.operands[0].evaluateInternal(vars);
+                if (array instanceof Date) throw new Error("$size does not support dates; code 16376");
+                return array.length;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */

+ 21 - 21
lib/pipeline/expressions/StrcasecmpExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * A $strcasecmp pipeline expression.
  * A $strcasecmp pipeline expression.
  * @see evaluate
  * @see evaluate
  * @class StrcasecmpExpression
  * @class StrcasecmpExpression
@@ -9,39 +9,39 @@
  * @constructor
  * @constructor
  **/
  **/
 var StrcasecmpExpression = module.exports = function StrcasecmpExpression() {
 var StrcasecmpExpression = module.exports = function StrcasecmpExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 2) throw new Error("two args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 2) throw new Error("two args expected");
+    base.call(this);
 }, klass = StrcasecmpExpression,
 }, klass = StrcasecmpExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		NaryExpression = require("./NaryExpression"),
-		Expression = require("./Expression");
+                NaryExpression = require("./NaryExpression"),
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$strcasecmp";
+                return "$strcasecmp";
 };
 };
 
 
-/** 
+/**
  * Takes in two strings. Returns a number. $strcasecmp is positive if the first string is “greater than” the second and negative if the first string is “less than” the second. $strcasecmp returns 0 if the strings are identical.
  * Takes in two strings. Returns a number. $strcasecmp is positive if the first string is “greater than” the second and negative if the first string is “less than” the second. $strcasecmp returns 0 if the strings are identical.
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var val1 = this.operands[0].evaluateInternal(vars),
-				val2 = this.operands[1].evaluateInternal(vars),
-				str1 = Value.coerceToString(val1).toUpperCase(),
-				str2 = Value.coerceToString(val2).toUpperCase(),
-				cmp = Value.compare(str1, str2);
-		return cmp;
+                var val1 = this.operands[0].evaluateInternal(vars),
+                                val2 = this.operands[1].evaluateInternal(vars),
+                                str1 = Value.coerceToString(val1).toUpperCase(),
+                                str2 = Value.coerceToString(val2).toUpperCase(),
+                                cmp = Value.compare(str1, str2);
+                return cmp;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$strcasecmp", klass.parse(StrcasecmpExpression));
+Expression.registerExpression("$strcasecmp", base.parse(StrcasecmpExpression));

+ 22 - 22
lib/pipeline/expressions/SubstrExpression.js

@@ -9,24 +9,24 @@
  * @constructor
  * @constructor
  **/
  **/
 var SubstrExpression = module.exports = function SubstrExpression() {
 var SubstrExpression = module.exports = function SubstrExpression() {
-		this.fixedArity(3);
-		if (arguments.length !== 3) throw new Error("three args expected");
-		base.call(this);
+    this.nargs = 3;
+    if (arguments.length !== 3) throw new Error("three args expected");
+    base.call(this);
 }, klass = SubstrExpression,
 }, klass = SubstrExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+    Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$substr";
+                return "$substr";
 };
 };
 
 
 /**
 /**
@@ -34,17 +34,17 @@ proto.getOpName = function getOpName() {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var val = this.operands[0].evaluateInternal(vars),
-				idx = this.operands[1].evaluateInternal(vars),
-				len = this.operands[2].evaluateInternal(vars),
-				str = Value.coerceToString(val);
-		if (typeof(idx) != "number") throw new Error(this.getOpName() + ": starting index must be a numeric type; code 16034");
-		if (typeof(len) != "number") throw new Error(this.getOpName() + ": length must be a numeric type; code 16035");
-		if (idx >= str.length) return "";
-		//TODO: Need to handle -1
-		len = (len === -1 ? undefined : len);
-		return str.substr(idx, len);
+                var val = this.operands[0].evaluateInternal(vars),
+                                idx = this.operands[1].evaluateInternal(vars),
+                                len = this.operands[2].evaluateInternal(vars),
+                                str = Value.coerceToString(val);
+                if (typeof(idx) != "number") throw new Error(this.getOpName() + ": starting index must be a numeric type; code 16034");
+                if (typeof(len) != "number") throw new Error(this.getOpName() + ": length must be a numeric type; code 16035");
+                if (idx >= str.length) return "";
+                //TODO: Need to handle -1
+                len = (len === -1 ? undefined : len);
+                return str.substr(idx, len);
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$substr", klass.parse(SubstrExpression));
+Expression.registerExpression("$substr", base.parse(SubstrExpression));

+ 18 - 18
lib/pipeline/expressions/SubtractExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * A $subtract pipeline expression.
  * A $subtract pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class SubtractExpression
  * @class SubtractExpression
@@ -9,35 +9,35 @@
  * @constructor
  * @constructor
  **/
  **/
 var SubtractExpression = module.exports = function SubtractExpression() {
 var SubtractExpression = module.exports = function SubtractExpression() {
-		this.fixedArity(2);
-		if (arguments.length !== 2) throw new Error("two args expected");
-		base.call(this);
+    this.nargs = 2;
+    if (arguments.length !== 2) throw new Error("two args expected");
+    base.call(this);
 }, klass = SubtractExpression,
 }, klass = SubtractExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$subtract";
+                return "$subtract";
 };
 };
 
 
-/** 
+/**
  * Takes an array that contains a pair of numbers and subtracts the second from the first, returning their difference.
  * Takes an array that contains a pair of numbers and subtracts the second from the first, returning their difference.
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var left = this.operands[0].evaluateInternal(vars),
-				right = this.operands[1].evaluateInternal(vars);
-		if (left instanceof Date || right instanceof Date) throw new Error("$subtract does not support dates; code 16376");
-		return left - right;
+                var left = this.operands[0].evaluateInternal(vars),
+                                right = this.operands[1].evaluateInternal(vars);
+                if (left instanceof Date || right instanceof Date) throw new Error("$subtract does not support dates; code 16376");
+                return left - right;
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$subtract", klass.parse(SubtractExpression));
+Expression.registerExpression("$subtract", base.parse(SubtractExpression));

+ 17 - 17
lib/pipeline/expressions/ToLowerExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * A $toLower pipeline expression.
  * A $toLower pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class ToLowerExpression
  * @class ToLowerExpression
@@ -9,34 +9,34 @@
  * @constructor
  * @constructor
  **/
  **/
 var ToLowerExpression = module.exports = function ToLowerExpression() {
 var ToLowerExpression = module.exports = function ToLowerExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one args expected");
-		base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one args expected");
+    base.call(this);
 }, klass = ToLowerExpression,
 }, klass = ToLowerExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$toLower";
+                return "$toLower";
 };
 };
 
 
-/** 
+/**
  * Takes a single string and converts that string to lowercase, returning the result. All uppercase letters become lowercase.
  * Takes a single string and converts that string to lowercase, returning the result. All uppercase letters become lowercase.
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var val = this.operands[0].evaluateInternal(vars),
-				str = Value.coerceToString(val);
-		return str.toLowerCase();
+                var val = this.operands[0].evaluateInternal(vars),
+                                str = Value.coerceToString(val);
+                return str.toLowerCase();
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$toLower", klass.parse(ToLowerExpression));
+Expression.registerExpression("$toLower", base.parse(ToLowerExpression));

+ 17 - 17
lib/pipeline/expressions/ToUpperExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * A $toUpper pipeline expression.
  * A $toUpper pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class ToUpperExpression
  * @class ToUpperExpression
@@ -9,34 +9,34 @@
  * @constructor
  * @constructor
  **/
  **/
 var ToUpperExpression = module.exports = function ToUpperExpression() {
 var ToUpperExpression = module.exports = function ToUpperExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one args expected");
-		base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one args expected");
+    base.call(this);
 }, klass = ToUpperExpression,
 }, klass = ToUpperExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+                                }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		Expression = require("./Expression");
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$toUpper";
+                return "$toUpper";
 };
 };
 
 
-/** 
+/**
  * Takes a single string and converts that string to lowercase, returning the result. All uppercase letters become lowercase.
  * Takes a single string and converts that string to lowercase, returning the result. All uppercase letters become lowercase.
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var val = this.operands[0].evaluateInternal(vars),
-				str = Value.coerceToString(val);
-		return str.toUpperCase();
+                var val = this.operands[0].evaluateInternal(vars),
+                                str = Value.coerceToString(val);
+                return str.toUpperCase();
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$toUpper", klass.parse(ToUpperExpression));
+Expression.registerExpression("$toUpper", base.parse(ToUpperExpression));

+ 22 - 22
lib/pipeline/expressions/WeekExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
 
 
-/** 
+/**
  * A $week pipeline expression.
  * A $week pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class WeekExpression
  * @class WeekExpression
@@ -9,28 +9,28 @@
  * @constructor
  * @constructor
  **/
  **/
 var WeekExpression = module.exports = function WeekExpression() {
 var WeekExpression = module.exports = function WeekExpression() {
-		this.fixedArity(1);
-		if (arguments.length !== 1) throw new Error("one args expected");
-		base.call(this);
+    this.nargs = 1;
+    if (arguments.length !== 1) throw new Error("one args expected");
+    base.call(this);
 }, klass = WeekExpression,
 }, klass = WeekExpression,
-		base = require("./NaryExpression"),
-		proto = klass.prototype = Object.create(base.prototype, {
-				constructor: {
-						value: klass
-				}
-		});
+    base = require("./NaryExpression"),
+    proto = klass.prototype = Object.create(base.prototype, {
+        constructor: {
+            value: klass
+        }
+    });
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
-		DayOfYearExpression = require("./DayOfYearExpression"),
-		Expression = require("./Expression");
+                DayOfYearExpression = require("./DayOfYearExpression"),
+                Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-		return "$week";
+                return "$week";
 };
 };
 
 
-/** 
+/**
  * Takes a date and returns the week of the year as a number between 0 and 53.
  * Takes a date and returns the week of the year as a number between 0 and 53.
  * Weeks begin on Sundays, and week 1 begins with the first Sunday of the year.
  * Weeks begin on Sundays, and week 1 begins with the first Sunday of the year.
  * Days preceding the first Sunday of the year are in week 0.
  * Days preceding the first Sunday of the year are in week 0.
@@ -38,14 +38,14 @@ proto.getOpName = function getOpName() {
  * @method evaluateInternal
  * @method evaluateInternal
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-		var date = this.operands[0].evaluateInternal(vars),
-				dayOfWeek = date.getUTCDay(),
-				dayOfYear = DayOfYearExpression.getDateDayOfYear(date),
-				prevSundayDayOfYear = dayOfYear - dayOfWeek, // may be negative
-				nextSundayDayOfYear = prevSundayDayOfYear + 7; // must be positive
-		// Return the zero based index of the week of the next sunday, equal to the one based index of the week of the previous sunday, which is to be returned.
-		return (nextSundayDayOfYear / 7) | 0; // also, the `| 0` here truncates this so that we return an integer
+                var date = this.operands[0].evaluateInternal(vars),
+                                dayOfWeek = date.getUTCDay(),
+                                dayOfYear = DayOfYearExpression.getDateDayOfYear(date),
+                                prevSundayDayOfYear = dayOfYear - dayOfWeek, // may be negative
+                                nextSundayDayOfYear = prevSundayDayOfYear + 7; // must be positive
+                // Return the zero based index of the week of the next sunday, equal to the one based index of the week of the previous sunday, which is to be returned.
+                return (nextSundayDayOfYear / 7) | 0; // also, the `| 0` here truncates this so that we return an integer
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$week", klass.parse(WeekExpression));
+Expression.registerExpression("$week", base.parse(WeekExpression));

+ 48 - 48
test/lib/pipeline/expressions/AllElementsTrueExpression.js

@@ -1,71 +1,71 @@
 "use strict";
 "use strict";
 var assert = require("assert"),
 var assert = require("assert"),
-		AllElementsTrueExpression = require("../../../../lib/pipeline/expressions/AllElementsTrueExpression"),
-		Expression = require("../../../../lib/pipeline/expressions/Expression");
+                AllElementsTrueExpression = require("../../../../lib/pipeline/expressions/AllElementsTrueExpression"),
+                Expression = require("../../../../lib/pipeline/expressions/Expression");
 
 
 var allElementsTrueExpression = new AllElementsTrueExpression();
 var allElementsTrueExpression = new AllElementsTrueExpression();
 
 
 module.exports = {
 module.exports = {
 
 
-		"AllElementsTrueExpression": {
+                "AllElementsTrueExpression": {
 
 
-				"constructor()": {
+                                "constructor()": {
 
 
-						"should not throw Error when constructing without args": function testConstructor() {
-								assert.doesNotThrow(function() {
-										new AllElementsTrueExpression();
-								});
-						}
+                                                "should not throw Error when constructing without args": function testConstructor() {
+                                                                assert.doesNotThrow(function() {
+                                                                                new AllElementsTrueExpression();
+                                                                });
+                                                }
 
 
-				},
+                                },
 
 
-				"#getOpName()": {
+                                "#getOpName()": {
 
 
-						"should return the correct op name; $allElements": function testOpName() {
-								assert.equal(new AllElementsTrueExpression().getOpName(), "$allElementsTrue");
-						}
+                                                "should return the correct op name; $allElements": function testOpName() {
+                                                                assert.equal(new AllElementsTrueExpression().getOpName(), "$allElementsTrue");
+                                                }
 
 
-				},
+                                },
 
 
-				"#evaluateInternal()": {
-						
-						"should return error if parameter is empty:": function testEmpty() {
-								assert.throws(function() {
-										allElementsTrueExpression.evaluateInternal("asdf");
-								});
-						},
+                                "#evaluateInternal()": {
 
 
-						"should return error if parameter is not an array": function testNonArray() {
-								assert.throws(function() {
-										allElementsTrueExpression.evaluateInternal("This is not an array");
-								});
-						},
+                                                "should return error if parameter is empty:": function testEmpty() {
+                                                                assert.throws(function() {
+                                                                                allElementsTrueExpression.evaluateInternal("asdf");
+                                                                });
+                                                },
 
 
-						"should return false if first element is false; [false, true, true true]": function testFirstFalse() {
-								assert.equal(allElementsTrueExpression.evaluateInternal(
-										Expression.parseOperand({
-												$allElementsTrue: [false, true, true, true]
-										}).evaluate()), false);
-						},
+                                                "should return error if parameter is not an array": function testNonArray() {
+                                                                assert.throws(function() {
+                                                                                allElementsTrueExpression.evaluateInternal("This is not an array");
+                                                                });
+                                                },
 
 
-						"should return false if last element is false; [true, true, true, false]": function testLastFalse() {
-								assert.equal(allElementsTrueExpression.evaluateInternal(
-										Expression.parseOperand({
-												$allElementsTrue: [true, true, true, false]
-										}).evaluate()), false);
-						},
+                                                "should return false if first element is false; [false, true, true true]": function testFirstFalse() {
+                                                                assert.equal(allElementsTrueExpression.evaluateInternal(
+                                                                                Expression.parseOperand({
+                                                                                                $allElementsTrue: [false, true, true, true]
+                                                                                }).evaluate()), false);
+                                                },
 
 
-						"should return true if all elements are true; [true,true,true,true]": function testAllTrue() {
-								assert.equal(allElementsTrueExpression.evaluateInternal(
-										Expression.parseOperand({
-												$allElementsTrue: [true, true, true, true]
-										}).evaluate()), true);
-						},
+                                                "should return false if last element is false; [true, true, true, false]": function testLastFalse() {
+                                                                assert.equal(allElementsTrueExpression.evaluateInternal(
+                                                                                Expression.parseOperand({
+                                                                                                $allElementsTrue: [true, true, true, false]
+                                                                                }).evaluate()), false);
+                                                },
 
 
-				}
+                                                "should return true if all elements are true; [true,true,true,true]": function testAllTrue() {
+                                                                assert.equal(allElementsTrueExpression.evaluateInternal(
+                                                                                Expression.parseOperand({
+                                                                                                $allElementsTrue: [true, true, true, true]
+                                                                                }).evaluate()), true);
+                                                },
 
 
-		}
+                                }
+
+                }
 
 
 };
 };
 
 
-if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);

+ 308 - 308
test/lib/pipeline/expressions/CompareExpression.js

@@ -1,367 +1,367 @@
 "use strict";
 "use strict";
 var assert = require("assert"),
 var assert = require("assert"),
-		Expression = require("../../../../lib/pipeline/expressions/Expression"),
-		CompareExpression = require("../../../../lib/pipeline/expressions/CompareExpression"),
-		FieldRangeExpression = require("../../../../lib/pipeline/expressions/FieldRangeExpression"),
-		VariablesParseState = require("../../../../Lib/pipeline/expressions/VariablesParseState"),
-		VariablesIdGenerator = require("../../../../Lib/pipeline/expressions/VariablesIdGenerator"),
-		ConstantExpression = require("../../../../Lib/pipeline/expressions/ConstantExpression");
+                Expression = require("../../../../lib/pipeline/expressions/Expression"),
+                CompareExpression = require("../../../../lib/pipeline/expressions/CompareExpression"),
+                FieldRangeExpression = require("../../../../lib/pipeline/expressions/FieldRangeExpression"),
+                VariablesParseState = require("../../../../Lib/pipeline/expressions/VariablesParseState"),
+                VariablesIdGenerator = require("../../../../Lib/pipeline/expressions/VariablesIdGenerator"),
+                ConstantExpression = require("../../../../Lib/pipeline/expressions/ConstantExpression");
 
 
 module.exports = {
 module.exports = {
 
 
-		"CompareExpression": {
-
-				"constructor()": {
-
-						"should throw Error if no args": function testConstructor() {
-								assert.throws(function() {
-										new CompareExpression();
-								});
-						}
-
-				},
-
-				"#getOpName()": {
-
-						"should return the correct op name; $eq, $ne, $gt, $gte, $lt, $lte, $cmp": function testOpName() {
-								assert.equal((new CompareExpression(CompareExpression.EQ)).getOpName(), "$eq");
-								assert.equal((new CompareExpression(CompareExpression.NE)).getOpName(), "$ne");
-								assert.equal((new CompareExpression(CompareExpression.GT)).getOpName(), "$gt");
-								assert.equal((new CompareExpression(CompareExpression.GTE)).getOpName(), "$gte");
-								assert.equal((new CompareExpression(CompareExpression.LT)).getOpName(), "$lt");
-								assert.equal((new CompareExpression(CompareExpression.LTE)).getOpName(), "$lte");
-								assert.equal((new CompareExpression(CompareExpression.CMP)).getOpName(), "$cmp");
-						}
-
-				},
-
-				"#evaluateInternal()": {
-
-						"$eq": {
-
-								"should return false if first < second; {$eq:[1,2]}": function testEqLt() {
-										//debugger;
-										var idGenerator = new VariablesIdGenerator();
-										var vps = new VariablesParseState(idGenerator);
-										var parseOp = Expression.parseOperand({
-												$eq: [{
-														$const: 1
-												}, {
-														$const: 2
-												}]
-										}, vps);
-										var result = parseOp.evaluateInternal({});
-
-										//assert.equal(new CompareExpression( CompareExpression.EQ).evaluateInternal({"$eq":[1,2]}), false);
-										assert.equal(result, false);
-
-								},
-
-								"should return true if first == second; {$eq:[1,1]}": function testEqEq() {
-										var idGenerator = new VariablesIdGenerator();
-										var vps = new VariablesParseState(idGenerator);
-
-										assert.equal(Expression.parseOperand({
-												$eq: [1, 1]
-										}, vps).evaluateInternal({}), true);
-								},
-
-								"should return false if first > second {$eq:[1,0]}": function testEqGt() {
-										var idGenerator = new VariablesIdGenerator();
-										var vps = new VariablesParseState(idGenerator);
-										assert.equal(Expression.parseOperand({
-												$eq: [1, 0]
-										}).evaluateInternal({}), false);
-								},
-
-								"should return false if first and second are different types {$eq:[null,0]}": function testEqGt() {
-										var idGenerator = new VariablesIdGenerator();
-										var vps = new VariablesParseState(idGenerator);
-										assert.equal(Expression.parseOperand({
-												$eq: [null, 0]
-										}, vps).evaluateInternal({}), false);
-								},
-
-								"should return false if first and second are different types {$eq:[undefined,0]}": function testEqGt() {
-										var idGenerator = new VariablesIdGenerator();
-										var vps = new VariablesParseState(idGenerator);
-										assert.equal(Expression.parseOperand({
-												$eq: [undefined, 0]
-										}, vps).evaluateInternal({}), false);
-								},
-
-								"should return false if first and second are different arrays {$eq:[[1],[null]]}": function testEqGt() {
-										var idGenerator = new VariablesIdGenerator();
-										var vps = new VariablesParseState(idGenerator);
-										assert.equal(Expression.parseOperand({
-												$eq: [
-														[1],
-														[null]
-												]
-										}, vps).evaluateInternal({}), false);
-								},
-
-								"should return false if first and second are different arrays {$eq:[[1],[]]}": function testEqGt() {
-										assert.equal(Expression.parseOperand({
-												$eq: [
-														[1],
-														[]
-												]
-										}, vps).evaluateInternal({}), false);
-										var idGenerator = new VariablesIdGenerator();
-										var vps = new VariablesParseState(idGenerator);
-								},
-
-								"should return true if first and second are the same arrays {$eq:[[1],[1]]}": function testEqGt() {
-										var idGenerator = new VariablesIdGenerator();
-										var vps = new VariablesParseState(idGenerator);
-										assert.equal(Expression.parseOperand({
-												$eq: [
-														[1],
-														[1]
-												]
-										}, vps).evaluateInternal({}), true);
-								}
-						},
-
-						// 	"$ne": {
-
-						// 		"should return true if first < second; {$ne:[1,2]}": function testNeLt(){
-						// 			assert.equal(Expression.parseOperand({$ne:[1,2]}).evaluateInternal({}), true);
-						// 		},
-
-						// 		"should return false if first == second; {$ne:[1,1]}": function testNeLt(){
-						// 			assert.equal(Expression.parseOperand({$ne:[1,1]}).evaluateInternal({}), false);
-						// 		},
-
-						// 		"should return true if first > second; {$ne:[1,0]}": function testNeGt(){
-						// 			assert.equal(Expression.parseOperand({$ne:[1,0]}).evaluateInternal({}), true);
-						// 		}
-
-						// 	},
-
-						// 	"$gt": {
-
-						// 		"should return false if first < second; {$gt:[1,2]}": function testGtLt(){
-						// 			assert.equal(Expression.parseOperand({$gt:[1,2]}).evaluateInternal({}), false);
-						// 		},
-
-						// 		"should return false if first == second; {$gt:[1,1]}": function testGtLt(){
-						// 			assert.equal(Expression.parseOperand({$gt:[1,1]}).evaluateInternal({}), false);
-						// 		},
-
-						// 		"should return true if first > second; {$gt:[1,0]}": function testGtGt(){
-						// 			assert.equal(Expression.parseOperand({$gt:[1,0]}).evaluateInternal({}), true);
-						// 		}
-
-						// 	},
-
-						// 	"$gte": {
-
-						// 		"should return false if first < second; {$gte:[1,2]}": function testGteLt(){
-						// 			assert.equal(Expression.parseOperand({$gte:[1,2]}).evaluateInternal({}), false);
-						// 		},
-
-						// 		"should return true if first == second; {$gte:[1,1]}": function testGteLt(){
-						// 			assert.equal(Expression.parseOperand({$gte:[1,1]}).evaluateInternal({}), true);
-						// 		},
-
-						// 		"should return true if first > second; {$gte:[1,0]}": function testGteGt(){
-						// 			assert.equal(Expression.parseOperand({$gte:[1,0]}).evaluateInternal({}), true);
-						// 		}
-
-						// 	},
-
-						// 	"$lt": {
-
-						// 		"should return true if first < second; {$lt:[1,2]}": function testLtLt(){
-						// 			assert.equal(Expression.parseOperand({$lt:[1,2]}).evaluateInternal({}), true);
-						// 		},
+                "CompareExpression": {
+
+                                "constructor()": {
+
+                                                "should throw Error if no args": function testConstructor() {
+                                                                assert.throws(function() {
+                                                                                new CompareExpression();
+                                                                });
+                                                }
+
+                                },
+
+                                "#getOpName()": {
+
+                                                "should return the correct op name; $eq, $ne, $gt, $gte, $lt, $lte, $cmp": function testOpName() {
+                                                                assert.equal((new CompareExpression(CompareExpression.EQ)).getOpName(), "$eq");
+                                                                assert.equal((new CompareExpression(CompareExpression.NE)).getOpName(), "$ne");
+                                                                assert.equal((new CompareExpression(CompareExpression.GT)).getOpName(), "$gt");
+                                                                assert.equal((new CompareExpression(CompareExpression.GTE)).getOpName(), "$gte");
+                                                                assert.equal((new CompareExpression(CompareExpression.LT)).getOpName(), "$lt");
+                                                                assert.equal((new CompareExpression(CompareExpression.LTE)).getOpName(), "$lte");
+                                                                assert.equal((new CompareExpression(CompareExpression.CMP)).getOpName(), "$cmp");
+                                                }
+
+                                },
+
+                                "#evaluateInternal()": {
+
+                                                "$eq": {
+
+                                                                "should return false if first < second; {$eq:[1,2]}": function testEqLt() {
+                                                                                //debugger;
+                                                                                var idGenerator = new VariablesIdGenerator();
+                                                                                var vps = new VariablesParseState(idGenerator);
+                                                                                var parseOp = Expression.parseOperand({
+                                                                                                $eq: [{
+                                                                                                                $const: 1
+                                                                                                }, {
+                                                                                                                $const: 2
+                                                                                                }]
+                                                                                }, vps);
+                                                                                var result = parseOp.evaluateInternal({});
+
+                                                                                //assert.equal(new CompareExpression( CompareExpression.EQ).evaluateInternal({"$eq":[1,2]}), false);
+                                                                                assert.equal(result, false);
+
+                                                                },
+
+                                                                "should return true if first == second; {$eq:[1,1]}": function testEqEq() {
+                                                                                var idGenerator = new VariablesIdGenerator();
+                                                                                var vps = new VariablesParseState(idGenerator);
+
+                                                                                assert.equal(Expression.parseOperand({
+                                                                                                $eq: [1, 1]
+                                                                                }, vps).evaluateInternal({}), true);
+                                                                },
+
+                                                                "should return false if first > second {$eq:[1,0]}": function testEqGt() {
+                                                                                var idGenerator = new VariablesIdGenerator();
+                                                                                var vps = new VariablesParseState(idGenerator);
+                                                                                assert.equal(Expression.parseOperand({
+                                                                                                $eq: [1, 0]
+                                                                                }).evaluateInternal({}), false);
+                                                                },
+
+                                                                "should return false if first and second are different types {$eq:[null,0]}": function testEqGt() {
+                                                                                var idGenerator = new VariablesIdGenerator();
+                                                                                var vps = new VariablesParseState(idGenerator);
+                                                                                assert.equal(Expression.parseOperand({
+                                                                                                $eq: [null, 0]
+                                                                                }, vps).evaluateInternal({}), false);
+                                                                },
+
+                                                                "should return false if first and second are different types {$eq:[undefined,0]}": function testEqGt() {
+                                                                                var idGenerator = new VariablesIdGenerator();
+                                                                                var vps = new VariablesParseState(idGenerator);
+                                                                                assert.equal(Expression.parseOperand({
+                                                                                                $eq: [undefined, 0]
+                                                                                }, vps).evaluateInternal({}), false);
+                                                                },
+
+                                                                "should return false if first and second are different arrays {$eq:[[1],[null]]}": function testEqGt() {
+                                                                                var idGenerator = new VariablesIdGenerator();
+                                                                                var vps = new VariablesParseState(idGenerator);
+                                                                                assert.equal(Expression.parseOperand({
+                                                                                                $eq: [
+                                                                                                                [1],
+                                                                                                                [null]
+                                                                                                ]
+                                                                                }, vps).evaluateInternal({}), false);
+                                                                },
+
+                                                                "should return false if first and second are different arrays {$eq:[[1],[]]}": function testEqGt() {
+                                                                                assert.equal(Expression.parseOperand({
+                                                                                                $eq: [
+                                                                                                                [1],
+                                                                                                                []
+                                                                                                ]
+                                                                                }, vps).evaluateInternal({}), false);
+                                                                                var idGenerator = new VariablesIdGenerator();
+                                                                                var vps = new VariablesParseState(idGenerator);
+                                                                },
+
+                                                                "should return true if first and second are the same arrays {$eq:[[1],[1]]}": function testEqGt() {
+                                                                                var idGenerator = new VariablesIdGenerator();
+                                                                                var vps = new VariablesParseState(idGenerator);
+                                                                                assert.equal(Expression.parseOperand({
+                                                                                                $eq: [
+                                                                                                                [1],
+                                                                                                                [1]
+                                                                                                ]
+                                                                                }, vps).evaluateInternal({}), true);
+                                                                }
+                                                },
+
+                                                //      "$ne": {
+
+                                                //              "should return true if first < second; {$ne:[1,2]}": function testNeLt(){
+                                                //                      assert.equal(Expression.parseOperand({$ne:[1,2]}).evaluateInternal({}), true);
+                                                //              },
+
+                                                //              "should return false if first == second; {$ne:[1,1]}": function testNeLt(){
+                                                //                      assert.equal(Expression.parseOperand({$ne:[1,1]}).evaluateInternal({}), false);
+                                                //              },
+
+                                                //              "should return true if first > second; {$ne:[1,0]}": function testNeGt(){
+                                                //                      assert.equal(Expression.parseOperand({$ne:[1,0]}).evaluateInternal({}), true);
+                                                //              }
+
+                                                //      },
+
+                                                //      "$gt": {
+
+                                                //              "should return false if first < second; {$gt:[1,2]}": function testGtLt(){
+                                                //                      assert.equal(Expression.parseOperand({$gt:[1,2]}).evaluateInternal({}), false);
+                                                //              },
+
+                                                //              "should return false if first == second; {$gt:[1,1]}": function testGtLt(){
+                                                //                      assert.equal(Expression.parseOperand({$gt:[1,1]}).evaluateInternal({}), false);
+                                                //              },
+
+                                                //              "should return true if first > second; {$gt:[1,0]}": function testGtGt(){
+                                                //                      assert.equal(Expression.parseOperand({$gt:[1,0]}).evaluateInternal({}), true);
+                                                //              }
+
+                                                //      },
+
+                                                //      "$gte": {
+
+                                                //              "should return false if first < second; {$gte:[1,2]}": function testGteLt(){
+                                                //                      assert.equal(Expression.parseOperand({$gte:[1,2]}).evaluateInternal({}), false);
+                                                //              },
+
+                                                //              "should return true if first == second; {$gte:[1,1]}": function testGteLt(){
+                                                //                      assert.equal(Expression.parseOperand({$gte:[1,1]}).evaluateInternal({}), true);
+                                                //              },
+
+                                                //              "should return true if first > second; {$gte:[1,0]}": function testGteGt(){
+                                                //                      assert.equal(Expression.parseOperand({$gte:[1,0]}).evaluateInternal({}), true);
+                                                //              }
+
+                                                //      },
+
+                                                //      "$lt": {
+
+                                                //              "should return true if first < second; {$lt:[1,2]}": function testLtLt(){
+                                                //                      assert.equal(Expression.parseOperand({$lt:[1,2]}).evaluateInternal({}), true);
+                                                //              },
 
 
-						// 		"should return false if first == second; {$lt:[1,1]}": function testLtLt(){
-						// 			assert.equal(Expression.parseOperand({$lt:[1,1]}).evaluateInternal({}), false);
-						// 		},
+                                                //              "should return false if first == second; {$lt:[1,1]}": function testLtLt(){
+                                                //                      assert.equal(Expression.parseOperand({$lt:[1,1]}).evaluateInternal({}), false);
+                                                //              },
 
 
-						// 		"should return false if first > second; {$lt:[1,0]}": function testLtGt(){
-						// 			assert.equal(Expression.parseOperand({$lt:[1,0]}).evaluateInternal({}), false);
-						// 		}
+                                                //              "should return false if first > second; {$lt:[1,0]}": function testLtGt(){
+                                                //                      assert.equal(Expression.parseOperand({$lt:[1,0]}).evaluateInternal({}), false);
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
-						// 	"$lte": {
+                                                //      "$lte": {
 
 
-						// 		"should return true if first < second; {$lte:[1,2]}": function testLteLt(){
-						// 			assert.equal(Expression.parseOperand({$lte:[1,2]}).evaluateInternal({}), true);
-						// 		},
+                                                //              "should return true if first < second; {$lte:[1,2]}": function testLteLt(){
+                                                //                      assert.equal(Expression.parseOperand({$lte:[1,2]}).evaluateInternal({}), true);
+                                                //              },
 
 
-						// 		"should return true if first == second; {$lte:[1,1]}": function testLteLt(){
-						// 			assert.equal(Expression.parseOperand({$lte:[1,1]}).evaluateInternal({}), true);
-						// 		},
+                                                //              "should return true if first == second; {$lte:[1,1]}": function testLteLt(){
+                                                //                      assert.equal(Expression.parseOperand({$lte:[1,1]}).evaluateInternal({}), true);
+                                                //              },
 
 
-						// 		"should return false if first > second; {$lte:[1,0]}": function testLteGt(){
-						// 			assert.equal(Expression.parseOperand({$lte:[1,0]}).evaluateInternal({}), false);
-						// 		}
+                                                //              "should return false if first > second; {$lte:[1,0]}": function testLteGt(){
+                                                //                      assert.equal(Expression.parseOperand({$lte:[1,0]}).evaluateInternal({}), false);
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
-						// 	"$cmp": {
+                                                //      "$cmp": {
 
 
-						// 		"should return -1 if first < second; {$cmp:[1,2]}": function testCmpLt(){
-						// 			assert.equal(Expression.parseOperand({$cmp:[1,2]}).evaluateInternal({}), -1);
-						// 		},
+                                                //              "should return -1 if first < second; {$cmp:[1,2]}": function testCmpLt(){
+                                                //                      assert.equal(Expression.parseOperand({$cmp:[1,2]}).evaluateInternal({}), -1);
+                                                //              },
 
 
-						// 		"should return 0 if first < second; {$cmp:[1,1]}": function testCmpLt(){
-						// 			assert.equal(Expression.parseOperand({$cmp:[1,1]}).evaluateInternal({}), 0);
-						// 		},
+                                                //              "should return 0 if first < second; {$cmp:[1,1]}": function testCmpLt(){
+                                                //                      assert.equal(Expression.parseOperand({$cmp:[1,1]}).evaluateInternal({}), 0);
+                                                //              },
 
 
-						// 		"should return 1 if first < second; {$cmp:[1,0]}": function testCmpLt(){
-						// 			assert.equal(Expression.parseOperand({$cmp:[1,0]}).evaluateInternal({}), 1);
-						// 		},
+                                                //              "should return 1 if first < second; {$cmp:[1,0]}": function testCmpLt(){
+                                                //                      assert.equal(Expression.parseOperand({$cmp:[1,0]}).evaluateInternal({}), 1);
+                                                //              },
 
 
-						// 		"should return 1 even if comparison is larger; {$cmp:['z','a']}": function testCmpBracketed(){
-						// 			assert.equal(Expression.parseOperand({$cmp:['z','a']}).evaluateInternal({}), 1);
-						// 		}
+                                                //              "should return 1 even if comparison is larger; {$cmp:['z','a']}": function testCmpBracketed(){
+                                                //                      assert.equal(Expression.parseOperand({$cmp:['z','a']}).evaluateInternal({}), 1);
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
-						// 	"should throw Error": {
+                                                //      "should throw Error": {
 
 
-						// 		"if zero operands are provided; {$ne:[]}": function testZeroOperands(){
-						// 			assert.throws(function(){
-						// 				Expression.parseOperand({$ne:[]}).evaluateInternal({});
-						// 			});
-						// 		},
+                                                //              "if zero operands are provided; {$ne:[]}": function testZeroOperands(){
+                                                //                      assert.throws(function(){
+                                                //                              Expression.parseOperand({$ne:[]}).evaluateInternal({});
+                                                //                      });
+                                                //              },
 
 
-						// 		"if one operand is provided; {$eq:[1]}": function testOneOperand(){
-						// 			assert.throws(function(){
-						// 				Expression.parseOperand({$eq:[1]}).evaluateInternal({});
-						// 			});
-						// 		},
+                                                //              "if one operand is provided; {$eq:[1]}": function testOneOperand(){
+                                                //                      assert.throws(function(){
+                                                //                              Expression.parseOperand({$eq:[1]}).evaluateInternal({});
+                                                //                      });
+                                                //              },
 
 
-						// 		"if three operands are provided; {$gt:[2,3,4]}": function testThreeOperands(){
-						// 			assert.throws(function(){
-						// 				Expression.parseOperand({$gt:[2,3,4]}).evaluateInternal({});
-						// 			});
-						// 		}
-						// 	}
+                                                //              "if three operands are provided; {$gt:[2,3,4]}": function testThreeOperands(){
+                                                //                      assert.throws(function(){
+                                                //                              Expression.parseOperand({$gt:[2,3,4]}).evaluateInternal({});
+                                                //                      });
+                                                //              }
+                                                //      }
 
 
-						// },
+                                                // },
 
 
-						// "#optimize()": {
+                                                // "#optimize()": {
 
 
-						// 	"should optimize constants; {$eq:[1,1]}": function testOptimizeConstants(){
-						// 		assert.deepEqual(Expression.parseOperand({$eq:[1,1]}).optimize().toJSON(true), {$const:true});
-						// 	},
+                                                //      "should optimize constants; {$eq:[1,1]}": function testOptimizeConstants(){
+                                                //              assert.deepEqual(Expression.parseOperand({$eq:[1,1]}).optimize().toJSON(true), {$const:true});
+                                                //      },
 
 
-						// 	"should not optimize if $cmp op; {$cmp:[1,'$a']}": function testNoOptimizeCmp(){
-						// 		assert.deepEqual(Expression.parseOperand({$cmp:[1,'$a']}).optimize().toJSON(), {$cmp:[1,'$a']});
-						// 	},
+                                                //      "should not optimize if $cmp op; {$cmp:[1,'$a']}": function testNoOptimizeCmp(){
+                                                //              assert.deepEqual(Expression.parseOperand({$cmp:[1,'$a']}).optimize().toJSON(), {$cmp:[1,'$a']});
+                                                //      },
 
 
-						// 	"should not optimize if $ne op; {$ne:[1,'$a']}": function testNoOptimizeNe(){
-						// 		assert.deepEqual(Expression.parseOperand({$ne:[1,'$a']}).optimize().toJSON(), {$ne:[1,'$a']});
-						// 	},
+                                                //      "should not optimize if $ne op; {$ne:[1,'$a']}": function testNoOptimizeNe(){
+                                                //              assert.deepEqual(Expression.parseOperand({$ne:[1,'$a']}).optimize().toJSON(), {$ne:[1,'$a']});
+                                                //      },
 
 
-						// 	"should not optimize if no constants; {$ne:['$a','$b']}": function testNoOptimizeNoConstant(){
-						// 		assert.deepEqual(Expression.parseOperand({$ne:['$a','$b']}).optimize().toJSON(), {$ne:['$a','$b']});
-						// 	},
+                                                //      "should not optimize if no constants; {$ne:['$a','$b']}": function testNoOptimizeNoConstant(){
+                                                //              assert.deepEqual(Expression.parseOperand({$ne:['$a','$b']}).optimize().toJSON(), {$ne:['$a','$b']});
+                                                //      },
 
 
-						// 	"should not optimize without an immediate field path;": {
+                                                //      "should not optimize without an immediate field path;": {
 
 
-						// 		"{$eq:[{$and:['$a']},1]}": function testNoOptimizeWithoutFieldPath(){
-						// 			assert.deepEqual(Expression.parseOperand({$eq:[{$and:['$a']},1]}).optimize().toJSON(), {$eq:[{$and:['$a']},1]});
-						// 		},
+                                                //              "{$eq:[{$and:['$a']},1]}": function testNoOptimizeWithoutFieldPath(){
+                                                //                      assert.deepEqual(Expression.parseOperand({$eq:[{$and:['$a']},1]}).optimize().toJSON(), {$eq:[{$and:['$a']},1]});
+                                                //              },
 
 
-						// 		"(reversed); {$eq:[1,{$and:['$a']}]}": function testNoOptimizeWithoutFieldPathReverse(){
-						// 			assert.deepEqual(Expression.parseOperand({$eq:[1,{$and:['$a']}]}).optimize().toJSON(), {$eq:[1,{$and:['$a']}]});
-						// 		}
+                                                //              "(reversed); {$eq:[1,{$and:['$a']}]}": function testNoOptimizeWithoutFieldPathReverse(){
+                                                //                      assert.deepEqual(Expression.parseOperand({$eq:[1,{$and:['$a']}]}).optimize().toJSON(), {$eq:[1,{$and:['$a']}]});
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
-						// 	"should optimize $eq expressions;": {
+                                                //      "should optimize $eq expressions;": {
 
 
-						// 		"{$eq:['$a',1]}": function testOptimizeEq(){
-						// 			var expr = Expression.parseOperand({$eq:['$a',1]}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$eq:['$a',1]});
-						// 		},
+                                                //              "{$eq:['$a',1]}": function testOptimizeEq(){
+                                                //                      var expr = Expression.parseOperand({$eq:['$a',1]}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$eq:['$a',1]});
+                                                //              },
 
 
-						// 		"{$eq:[1,'$a']} (reversed)": function testOptimizeEqReverse(){
-						// 			var expr = Expression.parseOperand({$eq:[1,'$a']}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$eq:['$a',1]});
-						// 		}
+                                                //              "{$eq:[1,'$a']} (reversed)": function testOptimizeEqReverse(){
+                                                //                      var expr = Expression.parseOperand({$eq:[1,'$a']}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$eq:['$a',1]});
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
-						// 	"should optimize $lt expressions;": {
+                                                //      "should optimize $lt expressions;": {
 
 
-						// 		"{$lt:['$a',1]}": function testOptimizeLt(){
-						// 			var expr = Expression.parseOperand({$lt:['$a',1]}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$lt:['$a',1]});
-						// 		},
+                                                //              "{$lt:['$a',1]}": function testOptimizeLt(){
+                                                //                      var expr = Expression.parseOperand({$lt:['$a',1]}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$lt:['$a',1]});
+                                                //              },
 
 
-						// 		"{$lt:[1,'$a']} (reversed)": function testOptimizeLtReverse(){
-						// 			var expr = Expression.parseOperand({$lt:[1,'$a']}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$gt:['$a',1]});
-						// 		}
+                                                //              "{$lt:[1,'$a']} (reversed)": function testOptimizeLtReverse(){
+                                                //                      var expr = Expression.parseOperand({$lt:[1,'$a']}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$gt:['$a',1]});
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
-						// 	"should optimize $lte expressions;": {
+                                                //      "should optimize $lte expressions;": {
 
 
-						// 		"{$lte:['$b',2]}": function testOptimizeLte(){
-						// 			var expr = Expression.parseOperand({$lte:['$b',2]}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$lte:['$b',2]});
-						// 		},
+                                                //              "{$lte:['$b',2]}": function testOptimizeLte(){
+                                                //                      var expr = Expression.parseOperand({$lte:['$b',2]}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$lte:['$b',2]});
+                                                //              },
 
 
-						// 		"{$lte:[2,'$b']} (reversed)": function testOptimizeLteReverse(){
-						// 			var expr = Expression.parseOperand({$lte:[2,'$b']}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$gte:['$b',2]});
-						// 		}
+                                                //              "{$lte:[2,'$b']} (reversed)": function testOptimizeLteReverse(){
+                                                //                      var expr = Expression.parseOperand({$lte:[2,'$b']}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$gte:['$b',2]});
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
-						// 	"should optimize $gt expressions;": {
+                                                //      "should optimize $gt expressions;": {
 
 
-						// 		"{$gt:['$b',2]}": function testOptimizeGt(){
-						// 			var expr = Expression.parseOperand({$gt:['$b',2]}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$gt:['$b',2]});
-						// 		},
+                                                //              "{$gt:['$b',2]}": function testOptimizeGt(){
+                                                //                      var expr = Expression.parseOperand({$gt:['$b',2]}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$gt:['$b',2]});
+                                                //              },
 
 
-						// 		"{$gt:[2,'$b']} (reversed)": function testOptimizeGtReverse(){
-						// 			var expr = Expression.parseOperand({$gt:[2,'$b']}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$lt:['$b',2]});
-						// 		}
+                                                //              "{$gt:[2,'$b']} (reversed)": function testOptimizeGtReverse(){
+                                                //                      var expr = Expression.parseOperand({$gt:[2,'$b']}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$lt:['$b',2]});
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
-						// 	"should optimize $gte expressions;": {
+                                                //      "should optimize $gte expressions;": {
 
 
-						// 		"{$gte:['$b',2]}": function testOptimizeGte(){
-						// 			var expr = Expression.parseOperand({$gte:['$b',2]}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$gte:['$b',2]});
-						// 		},
+                                                //              "{$gte:['$b',2]}": function testOptimizeGte(){
+                                                //                      var expr = Expression.parseOperand({$gte:['$b',2]}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$gte:['$b',2]});
+                                                //              },
 
 
-						// 		"{$gte:[2,'$b']} (reversed)": function testOptimizeGteReverse(){
-						// 			var expr = Expression.parseOperand({$gte:[2,'$b']}).optimize();
-						// 			assert(expr instanceof FieldRangeExpression, "not optimized");
-						// 			assert.deepEqual(expr.toJSON(), {$lte:['$b',2]});
-						// 		}
+                                                //              "{$gte:[2,'$b']} (reversed)": function testOptimizeGteReverse(){
+                                                //                      var expr = Expression.parseOperand({$gte:[2,'$b']}).optimize();
+                                                //                      assert(expr instanceof FieldRangeExpression, "not optimized");
+                                                //                      assert.deepEqual(expr.toJSON(), {$lte:['$b',2]});
+                                                //              }
 
 
-						// 	},
+                                                //      },
 
 
 
 
-				}
+                                }
 
 
-		}
+                }
 
 
 };
 };
 
 
-if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);