diff --git a/lib/nodes.js b/lib/nodes.js index da3d18bc..4a8f3b6e 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -141,9 +141,12 @@ if (func(child) === false) { return false; } - return child instanceof Base && (crossScope || !(child instanceof Code)) ? child.traverseChildren(crossScope, func) : undefined; + return crossScope || !(child instanceof Code) ? child.traverseChildren(crossScope, func) : undefined; }); }; + Base.prototype.invert = function() { + return new Op('!', this); + }; Base.prototype.children = []; Base.prototype.unwrap = THIS; Base.prototype.isStatement = NO; @@ -1271,13 +1274,7 @@ While = (function() { return function While(condition, opts) { While.__super__.constructor.call(this); - if (((opts != null) ? opts.invert : undefined)) { - if (condition instanceof Op) { - condition = new Parens(condition); - } - condition = new Op('!', condition); - } - this.condition = condition; + this.condition = ((opts != null) ? opts.invert : undefined) ? condition.invert() : condition; this.guard = ((opts != null) ? opts.guard : undefined); return this; }; @@ -1362,10 +1359,6 @@ Op.prototype.isUnary = function() { return !this.second; }; - Op.prototype.isInvertible = function() { - var _ref2; - return ('===' === (_ref2 = this.operator) || '!==' === _ref2); - }; Op.prototype.isComplex = function() { return this.operator !== '!' || this.first.isComplex(); }; @@ -1377,7 +1370,11 @@ return include(this.CHAINABLE, this.operator); }; Op.prototype.invert = function() { - return (this.operator = this.INVERSIONS[this.operator]); + var _ref2; + if (('===' === (_ref2 = this.operator) || '!==' === _ref2)) { + this.operator = this.INVERSIONS[this.operator]; + return this; + } else return this.second ? new Parens(this).invert() : Op.__super__.invert.call(this); }; Op.prototype.toString = function(idt) { return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator); @@ -1780,22 +1777,10 @@ exports.If = (function() { If = (function() { return function If(condition, _arg, _arg2) { - var op; this.tags = _arg2; this.body = _arg; this.tags || (this.tags = {}); - if (this.tags.invert) { - op = condition instanceof Op; - if (op && condition.isInvertible()) { - condition.invert(); - } else { - if (op && !condition.isUnary()) { - condition = new Parens(condition); - } - condition = new Op('!', condition); - } - } - this.condition = condition; + this.condition = this.tags.invert ? condition.invert() : condition; this.elseBody = null; this.isChain = false; return this; diff --git a/src/nodes.coffee b/src/nodes.coffee index 363b48cc..e677828c 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -128,10 +128,11 @@ exports.Base = class Base traverseChildren: (crossScope, func) -> @eachChild (child) -> return false if func(child) is false - if child instanceof Base and - (crossScope or child not instanceof Code) + if crossScope or child not instanceof Code child.traverseChildren crossScope, func + invert: -> new Op '!', this + # Default implementations of the common node properties and methods. Nodes # will override these with custom logic, if needed. children: [] @@ -1103,10 +1104,7 @@ exports.While = class While extends Base constructor: (condition, opts) -> super() - if opts?.invert - condition = new Parens condition if condition instanceof Op - condition = new Op('!', condition) - @condition = condition + @condition = if opts?.invert then condition.invert() else condition @guard = opts?.guard addBody: (body) -> @@ -1184,9 +1182,6 @@ exports.Op = class Op extends Base isUnary: -> not @second - isInvertible: -> - @operator in ['===', '!=='] - isComplex: -> @operator isnt '!' or @first.isComplex() isMutator: -> @@ -1196,7 +1191,13 @@ exports.Op = class Op extends Base include(@CHAINABLE, @operator) invert: -> - @operator = @INVERSIONS[@operator] + if @operator in ['===', '!=='] + @operator = @INVERSIONS[@operator] + this + else if @second + new Parens(this).invert() + else + super() toString: (idt) -> super(idt, @constructor.name + ' ' + @operator) @@ -1517,14 +1518,7 @@ exports.If = class If extends Base constructor: (condition, @body, @tags) -> @tags or= {} - if @tags.invert - op = condition instanceof Op - if op and condition.isInvertible() - condition.invert() - else - condition = new Parens condition if op and not condition.isUnary() - condition = new Op '!', condition - @condition = condition + @condition = if @tags.invert then condition.invert() else condition @elseBody = null @isChain = false