|
|
@@ -8,13 +8,10 @@
|
|
|
* @constructor
|
|
|
**/
|
|
|
var CondExpression = module.exports = function CondExpression(vars) {
|
|
|
- this.pCond = this.evaluateInternal(vars);
|
|
|
- this.idx = this.pCond.coerceToBool() ? 1 : 2;
|
|
|
- if (arguments.length !== 3) throw new Error("three args expected");
|
|
|
+ if (arguments.length !== 0) throw new Error("zero args expected");
|
|
|
base.call(this);
|
|
|
}, klass = CondExpression,
|
|
|
- FixedArityExpression = require("./FixedArityExpressionT")(klass, 3),
|
|
|
- base = FixedArityExpression,
|
|
|
+ base = require("./FixedArityExpressionT")(klass, 3),
|
|
|
proto = klass.prototype = Object.create(base.prototype, {
|
|
|
constructor: {
|
|
|
value: klass
|
|
|
@@ -23,41 +20,80 @@ var CondExpression = module.exports = function CondExpression(vars) {
|
|
|
|
|
|
// DEPENDENCIES
|
|
|
var Value = require("../Value"),
|
|
|
- Expression = require("./Expression");
|
|
|
+ Expression = require("./Expression"),
|
|
|
+ FixedArityExpressionT = require("./FixedArityExpressionT");
|
|
|
|
|
|
// PROTOTYPE MEMBERS
|
|
|
+klass.opName = "$cond";
|
|
|
proto.getOpName = function getOpName() {
|
|
|
- return "$cond";
|
|
|
+ return klass.opName;
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @param expr - I expect this to be the RHS of $cond:{...} or $cond:[,,,]
|
|
|
+ * @param vps
|
|
|
+ * @returns {*}
|
|
|
+ */
|
|
|
klass.parse = function parse(expr, vps) {
|
|
|
- this.checkArgLimit(3);
|
|
|
+ // There may only be one argument - an array of 3 items, or a hash containing 3 keys.
|
|
|
+ //this.checkArgLimit(3);
|
|
|
|
|
|
// if not an object, return;
|
|
|
- if (typeof(expr) !== Object)
|
|
|
- return Expression.parse(expr, vps);
|
|
|
+ // todo I don't understand why we'd do this. shouldn't expr be {}, [], or wrong?
|
|
|
+ if (typeof(expr) !== Object || )
|
|
|
+ return FixedArityExpressionT.parse(expr, vps);
|
|
|
|
|
|
- // verify
|
|
|
- if (Expression.parseOperand(expr) !== "$cond")
|
|
|
- throw new Error("Invalid expression");
|
|
|
+ // ...or expr could be the entirety of $cond:{...} or $cond:[,,,].
|
|
|
+ if(!(klass.opName in expr)) {
|
|
|
+ throw new Error("Invalid expression. Expected to see '"+klass.opName+"'");
|
|
|
+ }
|
|
|
|
|
|
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");
|
|
|
+ // If this is an Object and not an array, verify all the bits are specified.
|
|
|
+ // If this is an Object that is an array, verify there are three bits.
|
|
|
+ // (My issue here is that we got to this parse function when we parsed the $cond:{...} item, and we're calling
|
|
|
+ // parseOperand (again) without altering the input.)
|
|
|
+// var args = Expression.parseOperand(expr, vps);
|
|
|
+
|
|
|
+ var args = expr[getOpName()];
|
|
|
+
|
|
|
+ if (typeof args !== 'object') throw new Error("this should not happen");
|
|
|
+ if (args instanceof Array) {
|
|
|
+ // it's the array form. Convert it to the object form.
|
|
|
+ if (args.length !== 3) throw new Error("$cond requires exactly three arguments");
|
|
|
+ args = {if: args[0], then: args[1], else: args[2]};
|
|
|
+ }
|
|
|
+
|
|
|
+ // One way or the other, args is now in object form.
|
|
|
+ Object.keys(args).forEach(function(arg) {
|
|
|
+ if (arg === 'if') {
|
|
|
+ ret.operands[0] = Expression.parseOperand(args['if'], vps);
|
|
|
+ }
|
|
|
+ else if (arg === 'then') {
|
|
|
+ ret.operands[1] = Expression.parseOperand(args['then'], vps);
|
|
|
+ }
|
|
|
+ else if (arg === 'else') {
|
|
|
+ ret.operands[2] = Expression.parseOperand(args['else'], vps);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ throw new Error("Unrecognized parameter to $cond: '" + arg + "'; code 17083");
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
+ if (!ret.operands[0]) throw new Error("Missing 'if' parameter to $cond; code 17080");
|
|
|
+ if (!ret.operands[1]) throw new Error("Missing 'then' parameter to $cond; code 17081");
|
|
|
+ if (!ret.operands[2]) throw new Error("Missing 'else' parameter to $cond; code 17082");
|
|
|
|
|
|
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: { if: <boolean-expression>, then: <true-case>, else: <false-case-> } }
|
|
|
+ * -or-
|
|
|
+ * { $cond: [ <boolean-expression>, <true-case>, <false-case> ] }
|
|
|
* @method evaluate
|
|
|
**/
|
|
|
proto.evaluateInternal = function evaluateInternal(vars) {
|
|
|
@@ -74,4 +110,4 @@ proto.evaluateInternal = function evaluateInternal(vars) {
|
|
|
};
|
|
|
|
|
|
/** Register Expression */
|
|
|
-Expression.registerExpression("$cond", klass.parse);
|
|
|
+Expression.registerExpression(klass.opName, klass.parse);
|