diff --git a/lib/cake.js b/lib/cake.js index 9fb7fa10..2fbf2d88 100755 --- a/lib/cake.js +++ b/lib/cake.js @@ -37,7 +37,7 @@ return path.exists('Cakefile', function(exists) { var _a, _b, _c, _d, arg, args; if (!(exists)) { - throw new Error(("Cakefile not found in " + (process.cwd()))); + throw new Error("Cakefile not found in " + (process.cwd())); } args = process.argv.slice(2, process.argv.length); CoffeeScript.run(fs.readFileSync('Cakefile').toString(), { @@ -71,14 +71,14 @@ return _b; })().join('') : ''; desc = task.description ? ("# " + (task.description)) : ''; - puts(("cake " + (name) + (spaces) + " " + (desc))); + puts("cake " + (name) + (spaces) + " " + (desc)); } if (switches.length) { return puts(oparse.help()); } }; missingTask = function(task) { - puts(("No such task: \"" + (task) + "\"")); + puts("No such task: \"" + (task) + "\""); return process.exit(1); }; })(); diff --git a/lib/command.js b/lib/command.js index df7311ca..c646c36c 100644 --- a/lib/command.js +++ b/lib/command.js @@ -64,7 +64,7 @@ compile = function(source, topLevel) { return path.exists(source, function(exists) { if (!(exists)) { - throw new Error(("File not found: " + (source))); + throw new Error("File not found: " + (source)); } return fs.stat(source, function(err, stats) { if (stats.isDirectory()) { @@ -179,12 +179,12 @@ } return fs.writeFile(jsPath, js, function(err) { if (options.compile && options.watch) { - return puts(("Compiled " + (source))); + return puts("Compiled " + (source)); } }); }; return path.exists(dir, function(exists) { - return exists ? compile() : exec(("mkdir -p " + (dir)), compile); + return exists ? compile() : exec("mkdir -p " + (dir), compile); }); }; lint = function(js) { @@ -238,7 +238,7 @@ return process.exit(0); }; version = function() { - puts(("CoffeeScript version " + (CoffeeScript.VERSION))); + puts("CoffeeScript version " + (CoffeeScript.VERSION)); return process.exit(0); }; })(); diff --git a/lib/grammar.js b/lib/grammar.js index e7fde415..516aa549 100644 --- a/lib/grammar.js +++ b/lib/grammar.js @@ -539,13 +539,13 @@ Operation: [ o("UNARY Expression", function() { return new OpNode($1, $2); - }), o("- Expression", (function() { + }), o("- Expression", function() { return new OpNode('-', $2); - }), { + }, { prec: 'UNARY' - }), o("+ Expression", (function() { + }), o("+ Expression", function() { return new OpNode('+', $2); - }), { + }, { prec: 'UNARY' }), o("-- Expression", function() { return new OpNode('--', $2); diff --git a/lib/helpers.js b/lib/helpers.js index 4a1b9da6..20c44842 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -1,6 +1,6 @@ (function() { var compact, count, del, ends, extend, flatten, helpers, include, indexOf, merge, starts; - if (!((typeof process !== "undefined" && process !== null))) { + if (!(typeof process !== "undefined" && process !== null)) { this.exports = this; } helpers = (exports.helpers = {}); @@ -72,7 +72,7 @@ _a = []; _b = properties; for (key in _b) { val = _b[key]; - _a.push((object[key] = val)); + _a.push(object[key] = val); } return _a; }); diff --git a/lib/lexer.js b/lib/lexer.js index 499d0703..034b4e19 100644 --- a/lib/lexer.js +++ b/lib/lexer.js @@ -216,7 +216,7 @@ return '\\' + escaped; }); this.tokens = this.tokens.concat([['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]); - this.interpolateString(("\"" + (str) + "\""), { + this.interpolateString("\"" + (str) + "\"", { escapeQuotes: true }); if (flags) { @@ -400,7 +400,7 @@ if (options.herecomment) { return doc; } - return doc.replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), ("\\" + (options.quote))); + return doc.replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), "\\" + (options.quote)); }; Lexer.prototype.tagParameters = function() { var _d, i, tok; @@ -428,10 +428,10 @@ return this.outdentToken(this.indent); }; Lexer.prototype.identifierError = function(word) { - throw new Error(("SyntaxError: Reserved word \"" + (word) + "\" on line " + (this.line + 1))); + throw new Error("SyntaxError: Reserved word \"" + (word) + "\" on line " + (this.line + 1)); }; Lexer.prototype.assignmentError = function() { - throw new Error(("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned")); + throw new Error("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned"); }; Lexer.prototype.balancedString = function(str, delimited, options) { var _d, _e, _f, _g, close, i, levels, open, pair, slash; @@ -472,7 +472,7 @@ if (slash) { return false; } - throw new Error(("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1))); + throw new Error("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1)); } return !i ? false : str.substring(0, i); }; @@ -500,7 +500,7 @@ if (options.heredoc) { inner = inner.replace(new RegExp('\\\\' + quote, 'g'), quote); } - nested = lexer.tokenize(("(" + (inner) + ")"), { + nested = lexer.tokenize("(" + (inner) + ")", { line: this.line }); _e = nested; @@ -540,7 +540,7 @@ this.tokens = this.tokens.concat(value); } else if (tag === 'STRING' && options.escapeQuotes) { escaped = value.substring(1, value.length - 1).replace(/"/g, '\\"'); - this.token(tag, ("\"" + (escaped) + "\"")); + this.token(tag, "\"" + (escaped) + "\""); } else { this.token(tag, value); } diff --git a/lib/nodes.js b/lib/nodes.js index d9dedf01..0f108abe 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -383,6 +383,9 @@ op = del(o, 'operation'); props = only ? this.properties.slice(0, this.properties.length - 1) : this.properties; o.chainRoot = o.chainRoot || this; + if (this.parenthetical && !props.length) { + this.base.parenthetical = true; + } baseline = this.base.compile(o); if (this.hasProperties() && (this.base instanceof ObjectNode || this.isNumber())) { baseline = ("(" + (baseline) + ")"); @@ -483,18 +486,21 @@ compilation = this.compileSplat(o); } } - if (!(compilation)) { + if (!compilation) { args = (function() { _e = []; _g = this.args; for (_f = 0, _h = _g.length; _f < _h; _f++) { arg = _g[_f]; - _e.push(arg.compile(o)); + _e.push((function() { + arg.parenthetical = true; + return arg.compile(o); + })()); } return _e; - }).call(this).join(', '); - compilation = this.isSuper ? this.compileSuper(args, o) : ("" + (this.prefix()) + (this.variable.compile(o)) + "(" + (args) + ")"); + }).call(this); + compilation = this.isSuper ? this.compileSuper(args.join(', '), o) : ("" + (this.prefix()) + (this.variable.compile(o)) + "(" + (args.join(', ')) + ")"); } - return o.operation && this.wrapped ? ("(" + (compilation) + ")") : compilation; + return compilation; }; CallNode.prototype.compileSuper = function(args, o) { return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + (args) + ")"; @@ -759,11 +765,11 @@ if (obj instanceof SplatNode) { return this.compileSplatLiteral(o); } else if (obj instanceof CommentNode) { - objects.push(("\n" + (code) + "\n" + (o.indent))); + objects.push("\n" + (code) + "\n" + (o.indent)); } else if (i === this.objects.length - 1) { objects.push(code); } else { - objects.push(("" + (code) + ", ")); + objects.push("" + (code) + ", "); } } objects = objects.join(''); @@ -832,7 +838,7 @@ if (constructor.body.empty()) { constructor.body.push(new ReturnNode(literal('this'))); } - constructor.body.unshift(literal(("this." + (pname) + " = function(){ return " + (className) + ".prototype." + (pname) + ".apply(" + (me) + ", arguments); }"))); + constructor.body.unshift(literal("this." + (pname) + " = function(){ return " + (className) + ".prototype." + (pname) + ".apply(" + (me) + ", arguments); }")); } if (pvar) { access = prop.context === 'this' ? pvar.base.properties[0] : new AccessorNode(pvar, 'prototype'); @@ -842,7 +848,7 @@ props.push(prop); } if (me) { - constructor.body.unshift(literal(("" + (me) + " = this"))); + constructor.body.unshift(literal("" + (me) + " = this")); } construct = this.idt() + (new AssignNode(this.variable, constructor)).compile(merge(o, { sharedScope: constScope @@ -915,7 +921,7 @@ if (stmt) { return ("" + (this.tab) + (val) + ";"); } - return top ? val : ("(" + (val) + ")"); + return top || this.parenthetical ? val : ("(" + (val) + ")"); }; AssignNode.prototype.compilePatternMatch = function(o) { var _b, _c, _d, accessClass, assigns, code, i, idx, isString, obj, oindex, olength, splat, val, valVar, value; @@ -944,7 +950,7 @@ isString = idx.value && idx.value.match(IS_STRING); accessClass = isString || this.variable.isArray() ? IndexNode : AccessorNode; if (obj instanceof SplatNode && !splat) { - val = literal(obj.compileValue(o, valVar, (oindex = indexOf(this.variable.base.objects, obj)), (olength = this.variable.base.objects.length) - oindex - 1)); + val = literal(obj.compileValue(o, valVar, oindex = indexOf(this.variable.base.objects, obj), (olength = this.variable.base.objects.length) - oindex - 1)); splat = true; } else { if (typeof idx !== 'object') { @@ -1125,7 +1131,7 @@ assign.value = trailing; } pos = this.trailings.length - idx; - o.scope.assign(trailing.compile(o), ("arguments[" + (variadic) + " ? " + (len) + " - " + (pos) + " : " + (this.index + idx) + "]")); + o.scope.assign(trailing.compile(o), "arguments[" + (variadic) + " ? " + (len) + " - " + (pos) + " : " + (this.index + idx) + "]"); } } return "" + (name) + " = " + (utility('slice')) + ".call(arguments, " + (this.index) + (end) + ")"; @@ -1354,7 +1360,7 @@ _b = []; _c = this.array.base.objects; for (i = 0, _d = _c.length; i < _d; i++) { item = _c[i]; - _b.push(("" + (item.compile(o)) + " === " + (i ? this.obj2 : this.obj1))); + _b.push("" + (item.compile(o)) + " === " + (i ? this.obj2 : this.obj1)); } return _b; }).call(this); @@ -1438,7 +1444,9 @@ ExistenceNode.prototype["class"] = 'ExistenceNode'; ExistenceNode.prototype.children = ['expression']; ExistenceNode.prototype.compileNode = function(o) { - return ExistenceNode.compileTest(o, this.expression)[0]; + var test; + test = ExistenceNode.compileTest(o, this.expression)[0]; + return this.parenthetical ? test.substring(1, test.length - 1) : test; }; ExistenceNode.compileTest = function(o, variable) { var _b, first, second; @@ -1469,17 +1477,14 @@ return true; }; ParentheticalNode.prototype.compileNode = function(o) { - var code, l, top; + var code, top; top = del(o, 'top'); + this.expression.parenthetical = true; code = this.expression.compile(o); - if (this.isStatement(o)) { - return (top ? this.tab + code + ';' : code); + if (this.parenthetical || this.isStatement(o)) { + return top ? this.tab + code + ';' : code; } - l = code.length; - if (code.substr(l - 1, 1) === ';') { - code = code.substr(o, l - 1); - } - return this.expression instanceof AssignNode ? code : ("(" + (code) + ")"); + return "(" + (code) + ")"; }; return ParentheticalNode; })(); @@ -1571,7 +1576,7 @@ svar = scope.freeVariable(); sourcePart = ("" + (svar) + " = " + (this.source.compile(o)) + ";"); if (this.pattern) { - namePart = new AssignNode(this.name, literal(("" + (svar) + "[" + (ivar) + "]"))).compile(merge(o, { + namePart = new AssignNode(this.name, literal("" + (svar) + "[" + (ivar) + "]")).compile(merge(o, { indent: this.idt(1), top: true })) + '\n'; @@ -1597,13 +1602,13 @@ } if (codeInBody) { if (range) { - body.unshift(literal(("var " + (name) + " = " + (ivar)))); + body.unshift(literal("var " + (name) + " = " + (ivar))); } if (namePart) { - body.unshift(literal(("var " + (namePart)))); + body.unshift(literal("var " + (namePart))); } if (index) { - body.unshift(literal(("var " + (index) + " = " + (ivar)))); + body.unshift(literal("var " + (index) + " = " + (ivar))); } body = ClosureNode.wrap(body, true); } else { @@ -1660,7 +1665,7 @@ IfNode.prototype.rewriteSwitch = function(o) { var _b, _c, _d, cond, i, variable; this.assigner = this.switchSubject; - if (!((this.switchSubject.unwrap() instanceof LiteralNode))) { + if (!(this.switchSubject.unwrap() instanceof LiteralNode)) { variable = literal(o.scope.freeVariable()); this.assigner = new AssignNode(variable, this.switchSubject); this.switchSubject = variable; @@ -1673,7 +1678,7 @@ if (cond instanceof OpNode) { cond = new ParentheticalNode(cond); } - return new OpNode('==', (i === 0 ? this.assigner : this.switchSubject), cond); + return new OpNode('==', i === 0 ? this.assigner : this.switchSubject, cond); }).call(this)); } return _b; diff --git a/lib/optparse.js b/lib/optparse.js index 138b9a19..8e640c86 100755 --- a/lib/optparse.js +++ b/lib/optparse.js @@ -28,7 +28,7 @@ } } if (isOption && !matchedRule) { - throw new Error(("unrecognized option: " + (arg))); + throw new Error("unrecognized option: " + (arg)); } if (!isOption) { options.arguments = args.slice(i, args.length); @@ -41,7 +41,7 @@ var _a, _b, _c, _d, i, letPart, lines, rule, spaces; lines = ['Available options:']; if (this.banner) { - lines.unshift(("" + (this.banner) + "\n")); + lines.unshift("" + (this.banner) + "\n"); } _b = this.rules; for (_a = 0, _c = _b.length; _a < _c; _a++) { diff --git a/lib/rewriter.js b/lib/rewriter.js index c228c82a..15dfa10c 100644 --- a/lib/rewriter.js +++ b/lib/rewriter.js @@ -275,7 +275,7 @@ levels[open] -= 1; } if (levels[open] < 0) { - throw new Error(("too many " + (token[1]) + " on line " + (token[2] + 1))); + throw new Error("too many " + (token[1]) + " on line " + (token[2] + 1)); } } return 1; @@ -294,7 +294,7 @@ if (unclosed.length) { open = unclosed[0]; line = openLine[open] + 1; - throw new Error(("unclosed " + (open) + " on line " + (line))); + throw new Error("unclosed " + (open) + " on line " + (line)); } }; Rewriter.prototype.rewriteClosingParens = function() { diff --git a/lib/scope.js b/lib/scope.js index 0e13ca3b..6fce7a65 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -1,7 +1,7 @@ (function() { var Scope; var __hasProp = Object.prototype.hasOwnProperty; - if (!((typeof process !== "undefined" && process !== null))) { + if (!(typeof process !== "undefined" && process !== null)) { this.exports = this; } exports.Scope = (function() { @@ -95,7 +95,7 @@ if (!__hasProp.call(_b, key)) continue; val = _b[key]; if (val.assigned) { - _a.push(("" + (key) + " = " + (val.value))); + _a.push("" + (key) + " = " + (val.value)); } } return _a; diff --git a/src/nodes.coffee b/src/nodes.coffee index c252ce91..e3abf783 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -354,6 +354,7 @@ exports.ValueNode = class ValueNode extends BaseNode op = del o, 'operation' props = if only then @properties[0...@properties.length - 1] else @properties o.chainRoot or= this + @base.parenthetical = yes if @parenthetical and not props.length baseline = @base.compile o baseline = "(#{baseline})" if @hasProperties() and (@base instanceof ObjectNode or @isNumber()) complete = @last = baseline @@ -434,11 +435,15 @@ exports.CallNode = class CallNode extends BaseNode o.chainRoot = this unless o.chainRoot for arg in @args when arg instanceof SplatNode compilation = @compileSplat(o) - unless compilation - args = (arg.compile(o) for arg in @args).join(', ') - compilation = if @isSuper then @compileSuper(args, o) - else "#{@prefix()}#{@variable.compile(o)}(#{args})" - if o.operation and @wrapped then "(#{compilation})" else compilation + if not compilation + args = for arg in @args + arg.parenthetical = true + arg.compile o + compilation = if @isSuper + @compileSuper(args.join(', '), o) + else + "#{@prefix()}#{@variable.compile(o)}(#{ args.join(', ') })" + compilation # `super()` is converted into a call against the superclass's implementation # of the current function. @@ -790,7 +795,7 @@ exports.AssignNode = class AssignNode extends BaseNode o.scope.find name unless @isValue() and (@variable.hasProperties() or @variable.namespaced) val = "#{name} = #{val}" return "#{@tab}#{val};" if stmt - if top then val else "(#{val})" + if top or @parenthetical then val else "(#{val})" # Brief implementation of recursive pattern matching, when assigning array or # object literals to a value. Peeks at their properties to assign inner names. @@ -1214,7 +1219,8 @@ exports.ExistenceNode = class ExistenceNode extends BaseNode constructor: (@expression) -> compileNode: (o) -> - ExistenceNode.compileTest(o, @expression)[0] + test = ExistenceNode.compileTest(o, @expression)[0] + if @parenthetical then test.substring(1, test.length - 1) else test # The meat of the **ExistenceNode** is in this static `compileTest` method # because other nodes like to check the existence of their variables as well. @@ -1248,12 +1254,11 @@ exports.ParentheticalNode = class ParentheticalNode extends BaseNode compileNode: (o) -> top = del o, 'top' + @expression.parenthetical = true code = @expression.compile(o) - if @isStatement(o) - return (if top then @tab + code + ';' else code) - l = code.length - code = code.substr(o, l-1) if code.substr(l-1, 1) is ';' - if @expression instanceof AssignNode then code else "(#{code})" + if @parenthetical or @isStatement o + return if top then @tab + code + ';' else code + "(#{code})" #### ForNode