diff --git a/lib/browser.js b/lib/browser.js index e95f39f5..f493c0b2 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -6,7 +6,7 @@ return eval(CoffeeScript.compile(code, options)); }; CoffeeScript.run = function(code, options) { - ((options != null) ? options.bare = true : undefined); + (options != null) ? options.bare = true : undefined; return Function(CoffeeScript.compile(code, options))(); }; if (!(typeof window !== "undefined" && window !== null)) { diff --git a/lib/nodes.js b/lib/nodes.js index ba57a013..a56df961 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -56,7 +56,7 @@ return [compiled, reference]; } }).call(this); - if (((options != null) ? options.precompile : undefined)) { + if ((options != null) ? options.precompile : undefined) { for (i = 0, _len = pair.length; i < _len; i++) { node = pair[i]; (pair[i] = node.compile(o)); @@ -301,7 +301,7 @@ Return.prototype.makeReturn = THIS; Return.prototype.compile = function(o) { var _ref2, expr; - expr = (((_ref2 = this.expression) != null) ? _ref2.makeReturn() : undefined); + expr = ((_ref2 = this.expression) != null) ? _ref2.makeReturn() : undefined; if (expr && !(expr instanceof Return)) { return expr.compile(o); } @@ -430,16 +430,19 @@ fst = new Parens(new Assign(ref, fst)); snd.base = ref; } - ifn = new If(new Existence(fst), snd, { - soak: true + return new If(new Existence(fst), snd, { + soak: true, + operation: this.tags.operation }); - return ifn; } } return null; }; + Value.wrap = function(node) { + return node instanceof Value ? node : new Value(node); + }; return Value; - })(); + }).call(this); exports.Comment = (function() { Comment = (function() { function Comment(_arg) { @@ -496,13 +499,13 @@ return method.klass ? "" + (method.klass) + ".__super__." + name : "" + name + ".__super__.constructor"; }; Call.prototype.unfoldSoak = function(o) { - var _i, _len, _ref2, _ref3, call, ifn, left, list, rite, val; + var _i, _len, _ref2, _ref3, call, ifn, left, list, rite; if (this.soakNode) { - if (val = this.variable) { - if (!(val instanceof Value)) { - val = new Value(val); + if (this.variable) { + if (ifn = If.unfoldSoak(o, this, 'variable')) { + return ifn; } - _ref2 = val.cacheReference(o), left = _ref2[0], rite = _ref2[1]; + _ref2 = Value.wrap(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1]; } else { left = new Literal(this.superReference(o)); rite = new Value(left); @@ -510,10 +513,10 @@ rite = new Call(rite, this.args); rite.isNew = this.isNew; left = new Literal("typeof " + (left.compile(o)) + " === \"function\""); - ifn = new If(left, new Value(rite), { - soak: true + return new If(left, new Value(rite), { + soak: true, + operation: this.tags.operation }); - return ifn; } call = this; list = []; @@ -549,7 +552,7 @@ if (ifn = this.unfoldSoak(o)) { return ifn.compile(o); } - (((_ref2 = this.variable) != null) ? _ref2.tags.front = this.tags.front : undefined); + ((_ref2 = this.variable) != null) ? _ref2.tags.front = this.tags.front : undefined; for (_i = 0, _len = (_ref3 = this.args).length; _i < _len; _i++) { arg = _ref3[_i]; if (arg instanceof Splat) { @@ -576,9 +579,7 @@ return ("" + (this.superReference(o)) + ".apply(this, " + splatargs + ")"); } if (!this.isNew) { - if (!((base = this.variable) instanceof Value)) { - base = new Value(base); - } + base = Value.wrap(this.variable); if ((name = base.properties.pop()) && base.isComplex()) { ref = o.scope.freeVariable('this'); fun = "(" + ref + " = " + (base.compile(o)) + ")" + (name.compile(o)); @@ -1032,11 +1033,8 @@ } else { idx = isObject ? obj.tags["this"] ? obj.properties[0].name : obj : new Literal(0); } - if (!(value instanceof Value)) { - value = new Value(value); - } accessClass = IDENTIFIER.test(idx.value) ? Accessor : Index; - value.properties.push(new accessClass(idx)); + (value = Value.wrap(value)).properties.push(new accessClass(idx)); return new Assign(obj, value).compile(o); } top = del(o, 'top'); @@ -1298,7 +1296,7 @@ function While(condition, opts) { While.__super__.constructor.call(this); this.condition = ((opts != null) ? opts.invert : undefined) ? condition.invert() : condition; - this.guard = ((opts != null) ? opts.guard : undefined); + this.guard = (opts != null) ? opts.guard : undefined; return this; }; return While; @@ -1826,11 +1824,11 @@ If.prototype.topSensitive = YES; If.prototype.bodyNode = function() { var _ref2; - return (((_ref2 = this.body) != null) ? _ref2.unwrap() : undefined); + return ((_ref2 = this.body) != null) ? _ref2.unwrap() : undefined; }; If.prototype.elseBodyNode = function() { var _ref2; - return (((_ref2 = this.elseBody) != null) ? _ref2.unwrap() : undefined); + return ((_ref2 = this.elseBody) != null) ? _ref2.unwrap() : undefined; }; If.prototype.addElse = function(elseBody) { if (this.isChain) { @@ -1881,8 +1879,9 @@ }; If.prototype.compileExpression = function(o) { var _ref2, code; + this.condition.tags.operation = true; code = this.condition.compile(o) + ' ? ' + this.bodyNode().compileBare(o) + ' : ' + (((_ref2 = this.elseBodyNode()) != null) ? _ref2.compileBare(o) : undefined); - return this.tags.operation || this.soakNode ? "(" + code + ")" : code; + return this.tags.operation ? "(" + code + ")" : code; }; If.prototype.unfoldSoak = function() { return this.soakNode && this; @@ -1894,6 +1893,9 @@ } parent[name] = ifn.body; ifn.body = new Value(parent); + if (parent.tags.operation) { + ifn.tags.operation = true; + } return ifn; }; return If; diff --git a/lib/rewriter.js b/lib/rewriter.js index 9c64dd18..a96067ef 100644 --- a/lib/rewriter.js +++ b/lib/rewriter.js @@ -147,7 +147,7 @@ } _ref = this.tokens.slice(i + 1, i + 4), one = _ref[0], two = _ref[1], three = _ref[2]; tag = token[0]; - return (tag === 'TERMINATOR' || tag === 'OUTDENT') && !(((two != null) ? two[0] : undefined) === ':' || ((one != null) ? one[0] : undefined) === '@' && ((three != null) ? three[0] : undefined) === ':') || tag === ',' && !((_ref2 = ((one != null) ? one[0] : undefined)) === 'IDENTIFIER' || _ref2 === 'NUMBER' || _ref2 === 'STRING' || _ref2 === '@' || _ref2 === 'TERMINATOR' || _ref2 === 'OUTDENT'); + return (tag === 'TERMINATOR' || tag === 'OUTDENT') && !(((two != null) ? two[0] : undefined) === ':' || ((one != null) ? one[0] : undefined) === '@' && ((three != null) ? three[0] : undefined) === ':') || tag === ',' && !((_ref2 = (one != null) ? one[0] : undefined) === 'IDENTIFIER' || _ref2 === 'NUMBER' || _ref2 === 'STRING' || _ref2 === '@' || _ref2 === 'TERMINATOR' || _ref2 === 'OUTDENT'); }; action = function(token, i) { return this.tokens.splice(i, 0, ['}', '}', token[2]]); @@ -360,7 +360,7 @@ }; exports.Rewriter.prototype.tag = function(i) { var _ref; - return (((_ref = this.tokens[i]) != null) ? _ref[0] : undefined); + return ((_ref = this.tokens[i]) != null) ? _ref[0] : undefined; }; BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']]; INVERSES = {}; diff --git a/lib/scope.js b/lib/scope.js index de4bdc7f..6287bd16 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -98,7 +98,7 @@ index++; } this.setVar(temp, 'var'); - (((_ref2 = last(this.garbage)) != null) ? _ref2.push(temp) : undefined); + ((_ref2 = last(this.garbage)) != null) ? _ref2.push(temp) : undefined; return temp; }; Scope.prototype.assign = function(name, value) { diff --git a/src/nodes.coffee b/src/nodes.coffee index 96bde7f2..0805638b 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -403,10 +403,11 @@ exports.Value = class Value extends Base ref = new Literal o.scope.freeVariable 'ref' fst = new Parens new Assign ref, fst snd.base = ref - ifn = new If new Existence(fst), snd, soak: yes - return ifn + return new If new Existence(fst), snd, soak: on, operation: @tags.operation null + @wrap: (node) -> if node instanceof Value then node else new Value node + #### Comment # CoffeeScript passes through block comments as JavaScript block comments @@ -463,17 +464,16 @@ exports.Call = class Call extends Base # Soaked chained invocations unfold into if/else ternary structures. unfoldSoak: (o) -> if @soakNode - if val = @variable - val = new Value val unless val instanceof Value - [left, rite] = val.cacheReference o + if @variable + return ifn if ifn = If.unfoldSoak o, this, 'variable' + [left, rite] = Value.wrap(@variable).cacheReference o else left = new Literal @superReference o rite = new Value left rite = new Call rite, @args rite.isNew = @isNew left = new Literal "typeof #{ left.compile o } === \"function\"" - ifn = new If left, new Value(rite), soak: yes - return ifn + return new If left, new Value(rite), soak: yes, operation: @tags.operation call = this list = [] loop @@ -518,7 +518,7 @@ exports.Call = class Call extends Base splatargs = @compileSplatArguments o return "#{ @superReference o }.apply(this, #{splatargs})" if @isSuper unless @isNew - base = new Value base unless (base = @variable) instanceof Value + base = Value.wrap @variable if (name = base.properties.pop()) and base.isComplex() ref = o.scope.freeVariable 'this' fun = "(#{ref} = #{ base.compile o })#{ name.compile o }" @@ -893,9 +893,8 @@ exports.Assign = class Assign extends Base idx = if isObject if obj.tags.this then obj.properties[0].name else obj else new Literal 0 - value = new Value value unless value instanceof Value accessClass = if IDENTIFIER.test idx.value then Accessor else Index - value.properties.push new accessClass idx + (value = Value.wrap value).properties.push new accessClass idx return new Assign(obj, value).compile o top = del o, 'top' otop = merge o, top: yes @@ -1581,10 +1580,11 @@ exports.If = class If extends Base # Compile the If as a conditional operator. compileExpression: (o) -> + @condition.tags.operation = on code = @condition.compile(o) + ' ? ' + @bodyNode().compileBare(o) + ' : ' + @elseBodyNode()?.compileBare o - if @tags.operation or @soakNode then "(#{code})" else code + if @tags.operation then "(#{code})" else code unfoldSoak: -> @soakNode and this @@ -1593,6 +1593,7 @@ exports.If = class If extends Base return unless ifn = parent[name].unfoldSoak o parent[name] = ifn.body ifn.body = new Value parent + ifn.tags.operation = on if parent.tags.operation ifn # Faux-Nodes