Improving double-parentheses suppression. Issue #587

This commit is contained in:
Jeremy Ashkenas 2010-08-14 17:25:29 -04:00
parent 129e950c59
commit 9894eeb8e9
10 changed files with 76 additions and 66 deletions

View File

@ -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);
};
})();

View File

@ -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);
};
})();

View File

@ -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);

View File

@ -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;
});

View File

@ -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);
}

View File

@ -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;

View File

@ -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++) {

View File

@ -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() {

View File

@ -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;

View File

@ -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