Created Node.map, changed traverse to use Node.map

This commit is contained in:
jos 2014-11-14 11:25:48 +01:00
parent 20c96894ab
commit a1f60db0d1
25 changed files with 351 additions and 201 deletions

View File

@ -52,26 +52,36 @@ ArrayNode.prototype._compile = function (defs) {
};
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
ArrayNode.prototype._traverse = function (callback) {
ArrayNode.prototype.forEach = function (callback) {
for (var i = 0; i < this.nodes.length; i++) {
var node = this.nodes[i];
callback(node, 'nodes.' + i, this);
node._traverse(callback);
}
};
/**
* Create a clone of this node
* Create a new ArrayNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {ArrayNode} Returns a transformed copy of the node
*/
ArrayNode.prototype.map = function (callback) {
var nodes = [];
for (var i = 0; i < this.nodes.length; i++) {
nodes[i] = callback(this.nodes[i], 'nodes.' + i, this);
}
return new ArrayNode(nodes);
};
/**
* Create a clone of this node, a shallow copy
* @return {ArrayNode}
*/
ArrayNode.prototype.clone = function() {
return new ArrayNode(this.nodes.map(function(node) {
return node.clone();
}))
return new ArrayNode(this.nodes.slice(0))
};
/**

View File

@ -47,21 +47,29 @@ AssignmentNode.prototype._compile = function (defs) {
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
AssignmentNode.prototype._traverse = function (callback) {
AssignmentNode.prototype.forEach = function (callback) {
callback(this.expr, 'expr', this);
this.expr._traverse(callback);
};
/**
* Create a clone of this node
* Create a new AssignmentNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {AssignmentNode} Returns a transformed copy of the node
*/
AssignmentNode.prototype.map = function (callback) {
return new AssignmentNode(this.name, callback(this.expr, 'expr', this));
};
/**
* Create a clone of this node, a shallow copy
* @return {AssignmentNode}
*/
AssignmentNode.prototype.clone = function() {
return new AssignmentNode(this.name, this.expr.clone());
return new AssignmentNode(this.name, this.expr);
};
/**

View File

@ -66,26 +66,41 @@ BlockNode.prototype._compile = function (defs) {
};
/**
* Recursively execute a callback for each of the child blocks of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child blocks of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
BlockNode.prototype._traverse = function (callback) {
BlockNode.prototype.forEach = function (callback) {
for (var i = 0; i < this.blocks.length; i++) {
var node = this.blocks[i].node;
callback(node, 'blocks.' + i + '.node', this);
node._traverse(callback);
callback(this.blocks[i].node, 'blocks.' + i + '.node', this);
}
};
/**
* Create a clone of this node
* Create a new BlockNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {BlockNode} Returns a transformed copy of the node
*/
BlockNode.prototype.map = function (callback) {
var blocks = [];
for (var i = 0; i < this.blocks.length; i++) {
var block = this.blocks[i];
blocks[i] = {
node: callback(block.node, 'blocks.' + i + '.node', this),
visible: block.visible
};
}
return new BlockNode(blocks);
};
/**
* Create a clone of this node, a shallow copy
* @return {BlockNode}
*/
BlockNode.prototype.clone = function() {
var blocks = this.blocks.map(function(block) {
return {
node: block.node.clone(),
node: block.node,
visible: block.visible
};
});

View File

@ -83,27 +83,35 @@ ConditionalNode.prototype._compile = function(defs) {
};
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
ConditionalNode.prototype._traverse = function (callback) {
ConditionalNode.prototype.forEach = function (callback) {
callback(this.condition, 'condition', this);
this.condition._traverse(callback);
callback(this.trueExpr, 'trueExpr', this);
this.trueExpr._traverse(callback);
callback(this.falseExpr, 'falseExpr', this);
this.falseExpr._traverse(callback);
};
/**
* Create a clone of this node
* Create a new ConditionalNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {ConditionalNode} Returns a transformed copy of the node
*/
ConditionalNode.prototype.map = function (callback) {
return new ConditionalNode(
callback(this.condition, 'condition', this),
callback(this.trueExpr, 'trueExpr', this),
callback(this.falseExpr, 'falseExpr', this)
);
};
/**
* Create a clone of this node, a shallow copy
* @return {ConditionalNode}
*/
ConditionalNode.prototype.clone = function() {
return new ConditionalNode(this.condition.clone(), this.trueExpr.clone(), this.falseExpr.clone());
return new ConditionalNode(this.condition, this.trueExpr, this.falseExpr);
};
/**

View File

@ -115,15 +115,25 @@ ConstantNode.prototype._compile = function (defs) {
/**
* Execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* @param {function(child: Node, path: string, parent: Node)} callback
*/
ConstantNode.prototype._traverse = function (callback) {
ConstantNode.prototype.forEach = function (callback) {
// nothing to do, we don't have childs
};
/**
* Create a clone of this node
* Create a new ConstantNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node) : Node} callback
* @returns {ConstantNode} Returns a clone of the node
*/
ConstantNode.prototype.map = function (callback) {
return this.clone();
};
/**
* Create a clone of this node, a shallow copy
* @return {ConstantNode}
*/
ConstantNode.prototype.clone = function() {

View File

@ -64,21 +64,32 @@ FunctionAssignmentNode.prototype._compile = function (defs) {
};
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
* @private
*/
FunctionAssignmentNode.prototype._traverse = function (callback) {
FunctionAssignmentNode.prototype.forEach = function (callback) {
callback(this.expr, 'expr', this);
this.expr._traverse(callback);
};
/**
* Create a clone of this node
* Create a new FunctionAssignmentNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {FunctionAssignmentNode} Returns a transformed copy of the node
*/
FunctionAssignmentNode.prototype.map = function (callback) {
var expr = callback(this.expr, 'expr', this);
return new FunctionAssignmentNode(this.name, this.params.slice(0), expr);
};
/**
* Create a clone of this node, a shallow copy
* @return {FunctionAssignmentNode}
*/
FunctionAssignmentNode.prototype.clone = function() {
return new FunctionAssignmentNode(this.name, this.params.concat(), this.expr.clone());
return new FunctionAssignmentNode(this.name, this.params.slice(0), this.expr);
};
/**

View File

@ -46,8 +46,8 @@ FunctionNode.prototype._compile = function (defs) {
var isRaw = (typeof fn === 'function') && (fn.rawArgs == true);
// compile the parameters
var args = this.args.map(function (param) {
return param._compile(defs);
var args = this.args.map(function (arg) {
return arg._compile(defs);
});
if (isRaw) {
@ -71,27 +71,35 @@ FunctionNode.prototype._compile = function (defs) {
};
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
FunctionNode.prototype._traverse = function (callback) {
// args
FunctionNode.prototype.forEach = function (callback) {
for (var i = 0; i < this.args.length; i++) {
var param = this.args[i];
callback(param, 'args.' + i, this);
param._traverse(callback);
callback(this.args[i], 'args.' + i, this);
}
};
/**
* Create a clone of this node
* Create a new FunctionNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {FunctionNode} Returns a transformed copy of the node
*/
FunctionNode.prototype.map = function (callback) {
var args = [];
for (var i = 0; i < this.args.length; i++) {
args[i] = callback(this.args[i], 'args.' + i, this);
}
return new FunctionNode(this.name, args);
};
/**
* Create a clone of this node, a shallow copy
* @return {FunctionNode}
*/
FunctionNode.prototype.clone = function() {
return new FunctionNode(this.name, this.args.map(function (param) {
return param.clone();
}));
return new FunctionNode(this.name, this.args.slice(0));
};
/**

View File

@ -152,23 +152,36 @@ IndexNode.prototype.compileSubset = function(defs, replacement) {
};
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
IndexNode.prototype._traverse = function (callback) {
IndexNode.prototype.forEach = function (callback) {
// object
callback(this.object, 'object', this);
this.object._traverse(callback);
// ranges
for (var i = 0; i < this.ranges.length; i++) {
var range = this.ranges[i];
callback(range, 'ranges.' + i, this);
range._traverse(callback);
callback(this.ranges[i], 'ranges.' + i, this);
}
};
/**
* Create a new IndexNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {IndexNode} Returns a transformed copy of the node
*/
IndexNode.prototype.map = function (callback) {
var object = callback(this.object, 'object', this);
var ranges = [];
for (var i = 0; i < this.ranges.length; i++) {
ranges[i] = callback(this.ranges[i], 'ranges.' + i, this);
}
return new IndexNode(object, ranges);
};
/**
* Get the name of the object linked to this IndexNode
* @return {string} name
@ -178,13 +191,11 @@ IndexNode.prototype.objectName = function() {
};
/**
* Create a clone of this node
* Create a clone of this node, a shallow copy
* @return {IndexNode}
*/
IndexNode.prototype.clone = function() {
return new IndexNode(this.object.clone(), this.ranges.map(function (range) {
return range.clone();
}));
return new IndexNode(this.object, this.ranges.slice(0));
};
/**

View File

@ -76,38 +76,59 @@ Node.prototype._compile = function (defs) {
/**
* Execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @param {function(child: Node, path: string, parent: Node)} callback
* @private
*/
Node.prototype._traverse = function (callback) {
// must be implemented by each of the Node implementations having child nodes
throw new Error('Cannot traverse a Node interface');
Node.prototype.forEach = function (callback) {
// must be implemented by each of the Node implementations
throw new Error('Cannot run forEach on a Node interface');
};
/**
* Create a new Node having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {OperatorNode} Returns a transformed copy of the node
*/
Node.prototype.map = function (callback) {
// must be implemented by each of the Node implementations
throw new Error('Cannot run map on a Node interface');
};
/**
* Recursively traverse all nodes in a node tree. Executes given callback for
* this node and each of its child nodes. Similar to Array.forEach, except
* recursive.
* @param {function(Node, string, Node)} callback
* this node and each of its child nodes.
* @param {function(node: Node, path: string, parent: Node)} callback
* A callback called for every node in the node tree.
* Signature: callback(node: Node, index: string, parent: Node) : Node
*/
Node.prototype.traverse = function (callback) {
// execute callback for itself
callback(this, null, null);
// traverse over all children
// recursively traverse over all childs
this._traverse(callback);
};
/**
* Transform a node tree via a transform function. Similar to Array.map,
* but recursively executed on all nodes in the node tree.
* Recursively traverse all childs of this node
* @param {function(node: Node, path: string, parent: Node)} callback
* A callback called for every node in the node tree.
* @private
*/
Node.prototype._traverse = function (callback) {
this.forEach(function(child, path, parent) {
callback(child, path, parent);
child._traverse(callback);
});
};
/**
* Recursively transform a node tree via a transform function.
*
* For example, to replace all nodes of type SymbolNode having name 'x' with a
* ConstantNode with value 2:
*
* var res = Node.transform(function (node) {
* var res = Node.transform(function (node, path, parent) {
* if (node instanceof SymbolNode) && (node.name == 'x')) {
* return new ConstantNode(2);
* }
@ -116,7 +137,7 @@ Node.prototype.traverse = function (callback) {
* }
* });
*
* @param {function(Node, string, Node)} callback
* @param {function(node: Node, path: string, parent: Node) : Node} callback
* A mapping function accepting a node, and returning
* a replacement for the node or the original node.
* Signature: callback(node: Node, index: string, parent: Node) : Node
@ -124,30 +145,33 @@ Node.prototype.traverse = function (callback) {
*/
Node.prototype.transform = function (callback) {
// check itself
var res = callback(this, null, null);
if (res === this) {
// recurse over the child nodes
res._traverse(function (node, index, parent) {
var replacement = callback(node, index, parent);
if (index.indexOf('.') !== -1) {
// traverse path
var props = index.split('.');
var obj = parent;
while (props.length > 1) {
obj = obj[props.shift()];
}
obj[props.shift()] = replacement;
}
else {
parent[index] = replacement;
}
});
var replacement = callback(this, null, null);
if (replacement !== this) {
return replacement;
}
return res;
// traverse over all childs
return this._transform(callback);
};
/**
* Recursively transform all childs of this node
* @param {function(node: Node, path: string, parent: Node) : Node} callback
* A mapping function accepting a node, and returning
* a replacement for the node or the original node.
* Signature: callback(node: Node, index: string, parent: Node) : Node
* @return {Node} Returns the original node or its replacement
* @private
*/
Node.prototype._transform = function (callback) {
return this.map(function(child, path, parent) {
var replacement = callback(child, path, parent);
return (replacement !== child) ? replacement : child._transform(callback);
});
};
// TODO: create map and forEach
/**
* Find any node in the node tree matching given filter function. For example, to
* find all nodes of type SymbolNode having name 'x':
@ -184,11 +208,12 @@ Node.prototype.match = function () {
};
/**
* Create a clone of this node
* Create a clone of this node, a shallow copy
* @return {Node}
*/
Node.prototype.clone = function() {
return new Node();
// must be implemented by each of the Node implementations
throw new Error('Cannot clone a Node interface');
};
/**

View File

@ -43,33 +43,42 @@ OperatorNode.prototype._compile = function (defs) {
throw new Error('Function ' + this.fn + ' missing in provided namespace "math"');
}
var args = this.args.map(function (param) {
return param._compile(defs);
var args = this.args.map(function (arg) {
return arg._compile(defs);
});
return 'math.' + this.fn + '(' + args.join(', ') + ')';
};
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
OperatorNode.prototype._traverse = function (callback) {
OperatorNode.prototype.forEach = function (callback) {
for (var i = 0; i < this.args.length; i++) {
var param = this.args[i];
callback(param, 'args.' + i, this);
param._traverse(callback);
callback(this.args[i], 'args.' + i, this);
}
};
/**
* Create a clone of this node
* Create a new OperatorNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {OperatorNode} Returns a transformed copy of the node
*/
OperatorNode.prototype.map = function (callback) {
var args = [];
for (var i = 0; i < this.args.length; i++) {
args[i] = callback(this.args[i], 'args.' + i, this);
}
return new OperatorNode(this.op, this.fn, args);
};
/**
* Create a clone of this node, a shallow copy
* @return {OperatorNode}
*/
OperatorNode.prototype.clone = function() {
return new OperatorNode(this.op, this.fn, this.args.map(function (param) {
return param.clone();
}));
return new OperatorNode(this.op, this.fn, this.args.slice(0));
};
/**

View File

@ -49,33 +49,39 @@ RangeNode.prototype._compile = function (defs) {
};
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
RangeNode.prototype._traverse = function (callback) {
RangeNode.prototype.forEach = function (callback) {
callback(this.start, 'start', this);
this.start._traverse(callback);
if (this.step) {
callback(this.step, 'step', this);
this.step._traverse(callback);
}
callback(this.end, 'end', this);
this.end._traverse(callback);
};
/**
* Create a clone of this node
* Create a new RangeNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {RangeNode} Returns a transformed copy of the node
*/
RangeNode.prototype.map = function (callback) {
return new RangeNode(
callback(this.start, 'start', this),
callback(this.end, 'end', this),
this.step && callback(this.step, 'step', this)
);
};
/**
* Create a clone of this node, a shallow copy
* @return {RangeNode}
*/
RangeNode.prototype.clone = function() {
return new RangeNode(
this.start.clone(),
this.end.clone(),
this.step && this.step.clone()
);
return new RangeNode(this.start, this.end, this.step && this.step);
};
/**

View File

@ -56,13 +56,22 @@ SymbolNode.prototype._compile = function (defs) {
/**
* Execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* @param {function(child: Node, path: string, parent: Node)} callback
*/
SymbolNode.prototype._traverse = function (callback) {
SymbolNode.prototype.forEach = function (callback) {
// nothing to do, we don't have childs
};
/**
* Create a new SymbolNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node) : Node} callback
* @returns {SymbolNode} Returns a clone of the node
*/
SymbolNode.prototype.map = function (callback) {
return this.clone();
};
/**
* Throws an error 'Undefined symbol {name}'
* @param {String} name
@ -72,7 +81,7 @@ function undef (name) {
}
/**
* Create a clone of this node
* Create a clone of this node, a shallow copy
* @return {SymbolNode}
*/
SymbolNode.prototype.clone = function() {

View File

@ -45,24 +45,33 @@ UpdateNode.prototype._compile = function (defs) {
};
/**
* Recursively execute a callback for each of the child nodes of this node
* @param {function(Node, string, Node)} callback
* @private
* Execute a callback for each of the child nodes of this node
* @param {function(child: Node, path: string, parent: Node)} callback
*/
UpdateNode.prototype._traverse = function (callback) {
UpdateNode.prototype.forEach = function (callback) {
callback(this.index, 'index', this);
this.index._traverse(callback);
callback(this.expr, 'expr', this);
this.expr._traverse(callback);
};
/**
* Create a clone of this node
* Create a new UpdateNode having it's childs be the results of calling
* the provided callback function for each of the childs of the original node.
* @param {function(child: Node, path: string, parent: Node): Node} callback
* @returns {UpdateNode} Returns a transformed copy of the node
*/
UpdateNode.prototype.map = function (callback) {
return new UpdateNode(
callback(this.index, 'index', this),
callback(this.expr, 'expr', this)
);
};
/**
* Create a clone of this node, a shallow copy
* @return {UpdateNode}
*/
UpdateNode.prototype.clone = function() {
return new UpdateNode(this.index.clone(), this.expr.clone());
return new UpdateNode(this.index, this.expr);
};
/**

View File

@ -91,7 +91,7 @@ describe('ArrayNode', function() {
return (node instanceof SymbolNode) && (node.name == 'x') ? d : node;
});
assert.strictEqual(e, c);
assert.notStrictEqual(e, c);
assert.deepEqual(e.nodes[0], d);
assert.deepEqual(e.nodes[1], b);
});
@ -115,25 +115,26 @@ describe('ArrayNode', function() {
var c = new ArrayNode([a, b]);
var count = 0;
c.traverse(function (node, index, parent) {
c.traverse(function (node, path, parent) {
console.log('traverse', node.toString(), path)
count++;
switch(count) {
case 1:
assert.strictEqual(node, c);
assert.strictEqual(index, null);
assert.strictEqual(path, null);
assert.strictEqual(parent, null);
break;
case 2:
assert.strictEqual(node, a);
assert.strictEqual(index, 'nodes.0');
assert.strictEqual(path, 'nodes.0');
assert.strictEqual(parent, c);
break;
case 3:
assert.strictEqual(node, b);
assert.strictEqual(index, 'nodes.1');
assert.strictEqual(path, 'nodes.1');
assert.strictEqual(parent, c);
break;
}
@ -152,8 +153,8 @@ describe('ArrayNode', function() {
assert(d instanceof ArrayNode);
assert.deepEqual(c, d);
assert.notStrictEqual(c, d);
assert.notStrictEqual(c.nodes[0], d.nodes[0]);
assert.notStrictEqual(c.nodes[1], d.nodes[1]);
assert.strictEqual(c.nodes[0], d.nodes[0]);
assert.strictEqual(c.nodes[1], d.nodes[1]);
});
it ('should stringify an ArrayNode', function () {

View File

@ -81,7 +81,7 @@ describe('AssignmentNode', function() {
return node instanceof SymbolNode && node.name == 'x' ? e : node;
});
assert.strictEqual(f, d);
assert.notStrictEqual(f, d);
assert.deepEqual(f.expr.args[0], e);
assert.deepEqual(f.expr.args[1], b);
});
@ -139,7 +139,7 @@ describe('AssignmentNode', function() {
assert(e instanceof AssignmentNode);
assert.deepEqual(e, d);
assert.notStrictEqual(e, d);
assert.notStrictEqual(e.expr, d.expr);
assert.strictEqual(e.expr, d.expr);
});
it ('should stringify a AssignmentNode', function () {

View File

@ -91,7 +91,7 @@ describe('BlockNode', function() {
return node instanceof SymbolNode && node.name == 'x' ? d : node;
});
assert.strictEqual(e, a);
assert.notStrictEqual(e, a);
assert.deepEqual(e.blocks[0].node, d);
assert.deepEqual(e.blocks[1].node, c);
});
@ -156,8 +156,11 @@ describe('BlockNode', function() {
assert(d instanceof BlockNode);
assert.deepEqual(a, d);
assert.notStrictEqual(a, d);
assert.notStrictEqual(a.blocks, d.blocks);
assert.notStrictEqual(a.blocks[0], d.blocks[0]);
assert.notStrictEqual(a.blocks[1], d.blocks[1]);
assert.strictEqual(a.blocks[0].node, d.blocks[0].node);
assert.strictEqual(a.blocks[1].node, d.blocks[1].node);
});
it ('should stringify a BlockNode', function () {

View File

@ -117,7 +117,7 @@ describe('ConditionalNode', function() {
return node instanceof ConstantNode && node.value == '1' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.condition, e);
assert.deepEqual(f.trueExpr, a);
assert.deepEqual(f.falseExpr, b);
@ -134,7 +134,7 @@ describe('ConditionalNode', function() {
return node instanceof ConstantNode && node.value == '2' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.condition, condition);
assert.deepEqual(f.trueExpr, e);
assert.deepEqual(f.falseExpr, b);
@ -151,7 +151,7 @@ describe('ConditionalNode', function() {
return node instanceof ConstantNode && node.value == '3' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.condition, condition);
assert.deepEqual(f.trueExpr, a);
assert.deepEqual(f.falseExpr, e);
@ -182,9 +182,9 @@ describe('ConditionalNode', function() {
assert(d instanceof ConditionalNode);
assert.deepEqual(d, c);
assert.notStrictEqual(d, c);
assert.notStrictEqual(d.condition, c.condition);
assert.notStrictEqual(d.trueExpr, c.trueExpr);
assert.notStrictEqual(d.falseExpr, c.falseExpr);
assert.strictEqual(d.condition, c.condition);
assert.strictEqual(d.trueExpr, c.trueExpr);
assert.strictEqual(d.falseExpr, c.falseExpr);
});
it ('should stringify a ConditionalNode', function () {

View File

@ -87,7 +87,7 @@ describe('ConstantNode', function() {
var d = a.transform(function (node) {
return node instanceof ConstantNode && node.value == '99' ? b : node;
});
assert.strictEqual(d, a);
assert.notStrictEqual(d, a);
assert.deepEqual(d, a);
});

View File

@ -86,7 +86,7 @@ describe('FunctionAssignmentNode', function() {
return node instanceof SymbolNode && node.name == 'x' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.expr.args[0], a);
assert.deepEqual(f.expr.args[1], e);
});
@ -117,7 +117,7 @@ describe('FunctionAssignmentNode', function() {
assert(e instanceof FunctionAssignmentNode);
assert.deepEqual(e, d);
assert.notStrictEqual(e, d);
assert.notStrictEqual(e.expr, d.expr);
assert.strictEqual(e.expr, d.expr);
});
it ('should stringify a FunctionAssignmentNode', function () {

View File

@ -107,7 +107,7 @@ describe('FunctionNode', function() {
return node instanceof SymbolNode && node.name == 'x' ? g : node;
});
assert.strictEqual(h, f);
assert.notStrictEqual(h, f);
assert.deepEqual(h.args[0].args[0], g);
assert.deepEqual(h.args[0].args[1], b);
assert.deepEqual(h.name, 'multiply');
@ -127,7 +127,7 @@ describe('FunctionNode', function() {
return node;
});
assert.strictEqual(f, d);
assert.notStrictEqual(f, d);
assert.deepEqual(f.name, 'subtract');
});
@ -152,25 +152,25 @@ describe('FunctionNode', function() {
var d = new FunctionNode('add', [b, c]);
var count = 0;
d.traverse(function (node, index, parent) {
d.traverse(function (node, path, parent) {
count++;
switch(count) {
case 1:
assert.strictEqual(node, d);
assert.strictEqual(index, null);
assert.strictEqual(path, null);
assert.strictEqual(parent, null);
break;
case 2:
assert.strictEqual(node, b);
assert.strictEqual(index, 'args.0');
assert.strictEqual(path, 'args.0');
assert.strictEqual(parent, d);
break;
case 3:
assert.strictEqual(node, c);
assert.strictEqual(index, 'args.1');
assert.strictEqual(path, 'args.1');
assert.strictEqual(parent, d);
break;
}
@ -190,8 +190,9 @@ describe('FunctionNode', function() {
assert.deepEqual(e, d);
assert.notStrictEqual(e, d);
assert.equal(e.name, d.name);
assert.notStrictEqual(e.args[0], d.args[0]);
assert.notStrictEqual(e.args[1], d.args[1]);
assert.notStrictEqual(e.args, d.args);
assert.strictEqual(e.args[0], d.args[0]);
assert.strictEqual(e.args[1], d.args[1]);
});
it ('should stringify a FunctionNode', function () {

View File

@ -143,7 +143,7 @@ describe('IndexNode', function() {
return node instanceof SymbolNode ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.object, e);
assert.deepEqual(f.ranges[0], b);
assert.deepEqual(f.ranges[1], c);
@ -160,7 +160,7 @@ describe('IndexNode', function() {
return node instanceof ConstantNode && node.value == '1' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.object, a);
assert.deepEqual(f.ranges[0], b);
assert.deepEqual(f.ranges[1], e);
@ -190,9 +190,10 @@ describe('IndexNode', function() {
assert(d instanceof IndexNode);
assert.deepEqual(d, n);
assert.notStrictEqual(d, n);
assert.notStrictEqual(d.object, n.object);
assert.notStrictEqual(d.ranges[0], n.ranges[0]);
assert.notStrictEqual(d.ranges[1], n.ranges[1]);
assert.strictEqual(d.object, n.object);
assert.notStrictEqual(d.ranges, n.ranges);
assert.strictEqual(d.ranges[0], n.ranges[0]);
assert.strictEqual(d.ranges[1], n.ranges[1]);
});
it ('should stringify an IndexNode', function () {

View File

@ -7,7 +7,10 @@ var Node = require('../../../lib/expression/node/Node');
describe('Node', function() {
function MyNode () {}
MyNode.prototype = new Node();
MyNode.prototype._traverse = function () {};
MyNode.prototype.forEach = function () {};
MyNode.prototype.map = function () {
return new MyNode();
};
it ('should create a Node', function () {
var n = new Node();
@ -40,7 +43,7 @@ describe('Node', function() {
c = a.transform(function (node) {
return node;
});
assert.strictEqual(c, a);
assert.notStrictEqual(c, a);
});
it ('should transform a Node using a replacement function', function () {
@ -53,11 +56,11 @@ describe('Node', function() {
assert.strictEqual(c, b);
});
it ('should clone a Node', function () {
var a = new Node();
var b = a.clone();
assert.deepEqual(a, b);
assert.notStrictEqual(a, b);
it ('should throw an error when cloning a Node interface', function () {
assert.throws(function () {
var a = new Node();
a.clone();
}, /Cannot clone a Node interface/);
});
it ('should test whether an object is a Node', function () {

View File

@ -76,7 +76,8 @@ describe('OperatorNode', function() {
return node instanceof SymbolNode && node.name == 'x' ? f : node;
});
assert.strictEqual(g, e);
assert.notStrictEqual(g, e);
assert.notStrictEqual(g.args[0], e.args[0]);
assert.strictEqual(g.args[0].args[0], f);
assert.deepEqual(g.args[0].args[1], b);
assert.deepEqual(g.args[1], f);
@ -107,8 +108,9 @@ describe('OperatorNode', function() {
assert(d instanceof OperatorNode);
assert.deepEqual(d, c);
assert.notStrictEqual(d, c);
assert.notStrictEqual(d.args[0], c.args[0]);
assert.notStrictEqual(d.args[1], c.args[1]);
assert.notStrictEqual(d.args, c.args);
assert.strictEqual(d.args[0], c.args[0]);
assert.strictEqual(d.args[1], c.args[1]);
});
it ('should stringify an OperatorNode', function () {

View File

@ -69,7 +69,7 @@ describe('RangeNode', function() {
return node instanceof ConstantNode && node.value == '0' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.start, e);
assert.deepEqual(f.end, end);
assert.deepEqual(f.step, step);
@ -86,7 +86,7 @@ describe('RangeNode', function() {
return node instanceof ConstantNode && node.value == '10' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.start, start);
assert.deepEqual(f.end, e);
assert.deepEqual(f.step, step);
@ -103,7 +103,7 @@ describe('RangeNode', function() {
return node instanceof ConstantNode && node.value == '2' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.start, start);
assert.deepEqual(f.end, end);
assert.deepEqual(f.step, e);
@ -119,7 +119,7 @@ describe('RangeNode', function() {
return node instanceof ConstantNode && node.value == '10' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.start, start);
assert.deepEqual(f.end, e);
});
@ -148,9 +148,9 @@ describe('RangeNode', function() {
assert.deepEqual(d, c);
assert.notStrictEqual(d, c);
assert.notStrictEqual(d.start, c.start);
assert.notStrictEqual(d.end, c.end);
assert.notStrictEqual(d.step, c.step);
assert.strictEqual(d.start, c.start);
assert.strictEqual(d.end, c.end);
assert.strictEqual(d.step, c.step);
});
it ('should clone a RangeNode without step', function () {
@ -163,8 +163,8 @@ describe('RangeNode', function() {
assert(d instanceof RangeNode);
assert.deepEqual(d, c);
assert.notStrictEqual(d, c);
assert.notStrictEqual(d.start, c.start);
assert.notStrictEqual(d.end, c.end);
assert.strictEqual(d.start, c.start);
assert.strictEqual(d.end, c.end);
assert.strictEqual(d.step, c.step);
assert.strictEqual(d.step, null);
});

View File

@ -164,7 +164,7 @@ describe('UpdateNode', function() {
return node instanceof SymbolNode && node.name == 'x' ? e : node;
});
assert.strictEqual(f, n);
assert.notStrictEqual(f, n);
assert.deepEqual(f.index.object, a);
assert.deepEqual(f.index.ranges[0], b);
assert.deepEqual(f.index.ranges[1], e);
@ -185,7 +185,7 @@ describe('UpdateNode', function() {
return node instanceof ConstantNode && node.value == '3' ? e : node;
});
assert.strictEqual(g, n);
assert.notStrictEqual(g, n);
assert.deepEqual(g.index, i);
assert.deepEqual(g.index.object, a);
assert.deepEqual(g.index.ranges[0], b);
@ -225,8 +225,8 @@ describe('UpdateNode', function() {
assert(e instanceof UpdateNode);
assert.deepEqual(e, d);
assert.notStrictEqual(e, d);
assert.notStrictEqual(e.index, d.index);
assert.notStrictEqual(e.expr, d.expr);
assert.strictEqual(e.index, d.index);
assert.strictEqual(e.expr, d.expr);
});
it ('should stringify an UpdateNode', function () {