Merge branch 'master' of github.com:jashkenas/coffee-script

This commit is contained in:
Jeremy Ashkenas 2011-08-08 10:04:31 -04:00
commit f6d3953bc6
18 changed files with 394 additions and 944 deletions

View File

@ -6,22 +6,16 @@
return eval(CoffeeScript.compile(code, options));
};
CoffeeScript.run = function(code, options) {
if (options == null) {
options = {};
}
if (options == null) options = {};
options.bare = true;
return Function(CoffeeScript.compile(code, options))();
};
if (typeof window === "undefined" || window === null) {
return;
}
if (typeof window === "undefined" || window === null) return;
CoffeeScript.load = function(url, callback) {
var xhr;
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) {
xhr.overrideMimeType('text/plain');
}
if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain');
xhr.onreadystatechange = function() {
var _ref;
if (xhr.readyState === 4) {
@ -30,9 +24,7 @@
} else {
throw new Error("Could not load " + url);
}
if (callback) {
return callback();
}
if (callback) return callback();
}
};
return xhr.send(null);
@ -45,9 +37,7 @@
_results = [];
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
s = scripts[_i];
if (s.type === 'text/coffeescript') {
_results.push(s);
}
if (s.type === 'text/coffeescript') _results.push(s);
}
return _results;
})();

View File

@ -12,9 +12,7 @@
helpers.extend(global, {
task: function(name, description, action) {
var _ref;
if (!action) {
_ref = [description, action], action = _ref[0], description = _ref[1];
}
if (!action) _ref = [description, action], action = _ref[0], description = _ref[1];
return tasks[name] = {
name: name,
description: description,
@ -25,26 +23,20 @@
return switches.push([letter, flag, description]);
},
invoke: function(name) {
if (!tasks[name]) {
missingTask(name);
}
if (!tasks[name]) missingTask(name);
return tasks[name].action(options);
}
});
exports.run = function() {
return path.exists('Cakefile', function(exists) {
var arg, args, _i, _len, _ref, _results;
if (!exists) {
throw new Error("Cakefile not found in " + (process.cwd()));
}
if (!exists) throw new Error("Cakefile not found in " + (process.cwd()));
args = process.argv.slice(2);
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
filename: 'Cakefile'
});
oparse = new optparse.OptionParser(switches);
if (!args.length) {
return printTasks();
}
if (!args.length) return printTasks();
options = oparse.parse(args);
_ref = options.arguments;
_results = [];
@ -65,9 +57,7 @@
desc = task.description ? "# " + task.description : '';
console.log("cake " + name + spaces + " " + desc);
}
if (switches.length) {
return console.log(oparse.help());
}
if (switches.length) return console.log(oparse.help());
};
missingTask = function(task) {
console.log("No such task: \"" + task + "\"");

View File

@ -22,15 +22,11 @@
exports.RESERVED = RESERVED;
exports.helpers = require('./helpers');
exports.compile = compile = function(code, options) {
if (options == null) {
options = {};
}
if (options == null) options = {};
try {
return (parser.parse(lexer.tokenize(code))).compile(options);
} catch (err) {
if (options.filename) {
err.message = "In " + options.filename + ", " + err.message;
}
if (options.filename) err.message = "In " + options.filename + ", " + err.message;
throw err;
}
};
@ -61,12 +57,8 @@
};
exports.eval = function(code, options) {
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _ref4, _require;
if (options == null) {
options = {};
}
if (!(code = code.trim())) {
return;
}
if (options == null) options = {};
if (!(code = code.trim())) return;
if (_ref2 = require('vm'), Script = _ref2.Script, _ref2) {
sandbox = Script.createContext();
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
@ -94,7 +86,7 @@
_ref4 = Object.getOwnPropertyNames(require);
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
r = _ref4[_i];
_require[r] = require[r];
if (r !== 'paths') _require[r] = require[r];
}
_require.paths = _module.paths = Module._nodeModulePaths(process.cwd());
_require.resolve = function(request) {

View File

@ -22,33 +22,15 @@
optionParser = null;
exports.run = function() {
parseOptions();
if (opts.nodejs) {
return forkNode();
}
if (opts.help) {
return usage();
}
if (opts.version) {
return version();
}
if (opts.require) {
loadRequires();
}
if (opts.interactive) {
return require('./repl');
}
if (opts.stdio) {
return compileStdio();
}
if (opts.eval) {
return compileScript(null, sources[0]);
}
if (!sources.length) {
return require('./repl');
}
if (opts.run) {
opts.literals = sources.splice(1).concat(opts.literals);
}
if (opts.nodejs) return forkNode();
if (opts.help) return usage();
if (opts.version) return version();
if (opts.require) loadRequires();
if (opts.interactive) return require('./repl');
if (opts.stdio) return compileStdio();
if (opts.eval) return compileScript(null, sources[0]);
if (!sources.length) return require('./repl');
if (opts.run) opts.literals = sources.splice(1).concat(opts.literals);
process.ARGV = process.argv = process.argv.slice(0, 2).concat(opts.literals);
process.argv[0] = 'coffee';
process.execPath = require.main.filename;
@ -77,22 +59,14 @@
return total;
};
return path.exists(source, function(exists) {
if (topLevel && !exists && source.slice(-7) !== '.coffee') {
return compile("" + source + ".coffee", sourceIndex, topLevel);
}
if (topLevel && !exists) {
throw new Error("File not found: " + source);
}
if (topLevel && !exists && source.slice(-7) !== '.coffee') return compile("" + source + ".coffee", sourceIndex, topLevel);
if (topLevel && !exists) throw new Error("File not found: " + source);
return fs.stat(source, function(err, stats) {
if (err) {
throw err;
}
if (err) throw err;
if (stats.isDirectory()) {
return fs.readdir(source, function(err, files) {
var file, _k, _len3;
if (err) {
throw err;
}
if (err) throw err;
unprocessed[sourceIndex] += files.length;
for (_k = 0, _len3 = files.length; _k < _len3; _k++) {
file = files[_k];
@ -102,22 +76,16 @@
});
} else if (topLevel || path.extname(source) === '.coffee') {
fs.readFile(source, function(err, code) {
if (err) {
throw err;
}
if (err) throw err;
unprocessed[sourceIndex] -= 1;
if (opts.join) {
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n');
if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
return compileJoin();
}
if (helpers.compact(contents).length > 0 && remaining_files() === 0) return compileJoin();
} else {
return compileScript(source, code.toString(), base);
}
});
if (opts.watch && !opts.join) {
return watch(source, base);
}
if (opts.watch && !opts.join) return watch(source, base);
} else {
return unprocessed[sourceIndex] -= 1;
}
@ -158,12 +126,8 @@
}
} catch (err) {
CoffeeScript.emit('failure', err, task);
if (CoffeeScript.listeners('failure').length) {
return;
}
if (o.watch) {
return printLine(err.message);
}
if (CoffeeScript.listeners('failure').length) return;
if (o.watch) return printLine(err.message);
printWarn(err.stack);
return process.exit(1);
}
@ -173,9 +137,7 @@
code = '';
stdin = process.openStdin();
stdin.on('data', function(buffer) {
if (buffer) {
return code += buffer.toString();
}
if (buffer) return code += buffer.toString();
});
return stdin.on('end', function() {
return compileScript(null, code);
@ -202,13 +164,9 @@
persistent: true,
interval: 500
}, function(curr, prev) {
if (curr.size === prev.size && curr.mtime.getTime() === prev.mtime.getTime()) {
return;
}
if (curr.size === prev.size && curr.mtime.getTime() === prev.mtime.getTime()) return;
return fs.readFile(source, function(err, code) {
if (err) {
throw err;
}
if (err) throw err;
return compileScript(source, code.toString(), base);
});
});
@ -221,9 +179,7 @@
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
jsPath = path.join(dir, filename);
compile = function() {
if (js.length <= 0) {
js = ' ';
}
if (js.length <= 0) js = ' ';
return fs.writeFile(jsPath, js, function(err) {
if (err) {
return printLine(err.message);

View File

@ -5,9 +5,7 @@
o = function(patternString, action, options) {
var match;
patternString = patternString.replace(/\s{2,}/g, ' ');
if (!action) {
return [patternString, '$$ = $1;', options];
}
if (!action) return [patternString, '$$ = $1;', options];
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
action = action.replace(/\bnew /g, '$&yy.');
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
@ -60,9 +58,7 @@
}), o('BOOL', function() {
var val;
val = new Literal($1);
if ($1 === 'undefined') {
val.isUndefined = true;
}
if ($1 === 'undefined') val.isUndefined = true;
return val;
})
],
@ -214,17 +210,17 @@
return new Class;
}), o('CLASS Block', function() {
return new Class(null, null, $2);
}), o('CLASS EXTENDS Value', function() {
}), o('CLASS EXTENDS Expression', function() {
return new Class(null, $3);
}), o('CLASS EXTENDS Value Block', function() {
}), o('CLASS EXTENDS Expression Block', function() {
return new Class(null, $3, $4);
}), o('CLASS SimpleAssignable', function() {
return new Class($2);
}), o('CLASS SimpleAssignable Block', function() {
return new Class($2, null, $3);
}), o('CLASS SimpleAssignable EXTENDS Value', function() {
}), o('CLASS SimpleAssignable EXTENDS Expression', function() {
return new Class($2, $4);
}), o('CLASS SimpleAssignable EXTENDS Value Block', function() {
}), o('CLASS SimpleAssignable EXTENDS Expression Block', function() {
return new Class($2, $4, $5);
})
],
@ -570,13 +566,9 @@
_ref = alt[0].split(' ');
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
token = _ref[_j];
if (!grammar[token]) {
tokens.push(token);
}
}
if (name === 'Root') {
alt[1] = "return " + alt[1];
if (!grammar[token]) tokens.push(token);
}
if (name === 'Root') alt[1] = "return " + alt[1];
_results.push(alt);
}
return _results;

View File

@ -13,18 +13,14 @@
_results = [];
for (_i = 0, _len = array.length; _i < _len; _i++) {
item = array[_i];
if (item) {
_results.push(item);
}
if (item) _results.push(item);
}
return _results;
};
exports.count = function(string, substr) {
var num, pos;
num = pos = 0;
if (!substr.length) {
return 1 / 0;
}
if (!substr.length) return 1 / 0;
while (pos = 1 + string.indexOf(substr, pos)) {
num++;
}

View File

@ -12,12 +12,8 @@
function Lexer() {}
Lexer.prototype.tokenize = function(code, opts) {
var i;
if (opts == null) {
opts = {};
}
if (WHITESPACE.test(code)) {
code = "\n" + code;
}
if (opts == null) opts = {};
if (WHITESPACE.test(code)) code = "\n" + code;
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
this.code = code;
this.line = opts.line || 0;
@ -31,16 +27,12 @@
i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
}
this.closeIndentation();
if (opts.rewrite === false) {
return this.tokens;
}
if (opts.rewrite === false) return this.tokens;
return (new Rewriter).rewrite(this.tokens);
};
Lexer.prototype.identifierToken = function() {
var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;
if (!(match = IDENTIFIER.exec(this.chunk))) {
return 0;
}
if (!(match = IDENTIFIER.exec(this.chunk))) return 0;
input = match[0], id = match[1], colon = match[2];
if (id === 'own' && this.tag() === 'FOR') {
this.token('OWN', id);
@ -81,9 +73,7 @@
}
}
if (!forcedIdentifier) {
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
id = COFFEE_ALIAS_MAP[id];
}
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) id = COFFEE_ALIAS_MAP[id];
tag = (function() {
switch (id) {
case '!':
@ -109,16 +99,12 @@
})();
}
this.token(tag, id);
if (colon) {
this.token(':', ':');
}
if (colon) this.token(':', ':');
return input.length;
};
Lexer.prototype.numberToken = function() {
var match, number;
if (!(match = NUMBER.exec(this.chunk))) {
return 0;
}
if (!(match = NUMBER.exec(this.chunk))) return 0;
number = match[0];
this.token('NUMBER', number);
return number.length;
@ -127,15 +113,11 @@
var match, string;
switch (this.chunk.charAt(0)) {
case "'":
if (!(match = SIMPLESTR.exec(this.chunk))) {
return 0;
}
if (!(match = SIMPLESTR.exec(this.chunk))) return 0;
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
break;
case '"':
if (!(string = this.balancedString(this.chunk, '"'))) {
return 0;
}
if (!(string = this.balancedString(this.chunk, '"'))) return 0;
if (0 < string.indexOf('#{', 1)) {
this.interpolateString(string.slice(1, -1));
} else {
@ -150,9 +132,7 @@
};
Lexer.prototype.heredocToken = function() {
var doc, heredoc, match, quote;
if (!(match = HEREDOC.exec(this.chunk))) {
return 0;
}
if (!(match = HEREDOC.exec(this.chunk))) return 0;
heredoc = match[0];
quote = heredoc.charAt(0);
doc = this.sanitizeHeredoc(match[2], {
@ -171,9 +151,7 @@
};
Lexer.prototype.commentToken = function() {
var comment, here, match;
if (!(match = this.chunk.match(COMMENT))) {
return 0;
}
if (!(match = this.chunk.match(COMMENT))) return 0;
comment = match[0], here = match[1];
if (here) {
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
@ -187,29 +165,21 @@
};
Lexer.prototype.jsToken = function() {
var match, script;
if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
return 0;
}
if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) return 0;
this.token('JS', (script = match[0]).slice(1, -1));
return script.length;
};
Lexer.prototype.regexToken = function() {
var length, match, prev, regex, _ref2;
if (this.chunk.charAt(0) !== '/') {
return 0;
}
if (this.chunk.charAt(0) !== '/') return 0;
if (match = HEREGEX.exec(this.chunk)) {
length = this.heregexToken(match);
this.line += count(match[0], '\n');
return length;
}
prev = last(this.tokens);
if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
return 0;
}
if (!(match = REGEX.exec(this.chunk))) {
return 0;
}
if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) return 0;
if (!(match = REGEX.exec(this.chunk))) return 0;
regex = match[0];
this.token('REGEX', regex === '//' ? '/(?:)/' : regex);
return regex.length;
@ -233,30 +203,22 @@
if (tag === 'TOKENS') {
tokens.push.apply(tokens, value);
} else {
if (!(value = value.replace(HEREGEX_OMIT, ''))) {
continue;
}
if (!(value = value.replace(HEREGEX_OMIT, ''))) continue;
value = value.replace(/\\/g, '\\\\');
tokens.push(['STRING', this.makeString(value, '"', true)]);
}
tokens.push(['+', '+']);
}
tokens.pop();
if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') {
this.tokens.push(['STRING', '""'], ['+', '+']);
}
if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') this.tokens.push(['STRING', '""'], ['+', '+']);
(_ref5 = this.tokens).push.apply(_ref5, tokens);
if (flags) {
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
}
if (flags) this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
this.token(')', ')');
return heregex.length;
};
Lexer.prototype.lineToken = function() {
var diff, indent, match, noNewlines, prev, size;
if (!(match = MULTI_DENT.exec(this.chunk))) {
return 0;
}
if (!(match = MULTI_DENT.exec(this.chunk))) return 0;
indent = match[0];
this.line += count(indent, '\n');
prev = last(this.tokens, 1);
@ -306,23 +268,15 @@
this.token('OUTDENT', dent);
}
}
if (dent) {
this.outdebt -= moveOut;
}
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
this.token('TERMINATOR', '\n');
}
if (dent) this.outdebt -= moveOut;
if (!(this.tag() === 'TERMINATOR' || noNewlines)) this.token('TERMINATOR', '\n');
return this;
};
Lexer.prototype.whitespaceToken = function() {
var match, nline, prev;
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
return 0;
}
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) return 0;
prev = last(this.tokens);
if (prev) {
prev[match ? 'spaced' : 'newLine'] = true;
}
if (prev) prev[match ? 'spaced' : 'newLine'] = true;
if (match) {
return match[0].length;
} else {
@ -330,33 +284,25 @@
}
};
Lexer.prototype.newlineToken = function() {
if (this.tag() !== 'TERMINATOR') {
this.token('TERMINATOR', '\n');
}
if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n');
return this;
};
Lexer.prototype.suppressNewlines = function() {
if (this.value() === '\\') {
this.tokens.pop();
}
if (this.value() === '\\') this.tokens.pop();
return this;
};
Lexer.prototype.literalToken = function() {
var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
if (match = OPERATOR.exec(this.chunk)) {
value = match[0];
if (CODE.test(value)) {
this.tagParameters();
}
if (CODE.test(value)) this.tagParameters();
} else {
value = this.chunk.charAt(0);
}
tag = value;
prev = last(this.tokens);
if (value === '=' && prev) {
if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
this.assignmentError();
}
if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) this.assignmentError();
if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
prev[0] = 'COMPOUND_ASSIGN';
prev[1] += '=';
@ -379,9 +325,7 @@
tag = 'LOGIC';
} else if (prev && !prev.spaced) {
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
tag = 'CALL_START';
} else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
tag = 'INDEX_START';
@ -401,33 +345,21 @@
var attempt, herecomment, indent, match, _ref2;
indent = options.indent, herecomment = options.herecomment;
if (herecomment) {
if (HEREDOC_ILLEGAL.test(doc)) {
throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
}
if (doc.indexOf('\n') <= 0) {
return doc;
}
if (HEREDOC_ILLEGAL.test(doc)) throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
if (doc.indexOf('\n') <= 0) return doc;
} else {
while (match = HEREDOC_INDENT.exec(doc)) {
attempt = match[1];
if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {
indent = attempt;
}
if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) indent = attempt;
}
}
if (indent) {
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
}
if (!herecomment) {
doc = doc.replace(/^\n/, '');
}
if (indent) doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
if (!herecomment) doc = doc.replace(/^\n/, '');
return doc;
};
Lexer.prototype.tagParameters = function() {
var i, stack, tok, tokens;
if (this.tag() !== ')') {
return this;
}
if (this.tag() !== ')') return this;
stack = [];
tokens = this.tokens;
i = tokens.length;
@ -470,9 +402,7 @@
continue;
case end:
stack.pop();
if (!stack.length) {
return str.slice(0, i + 1);
}
if (!stack.length) return str.slice(0, i + 1);
end = stack[stack.length - 1];
continue;
}
@ -491,9 +421,7 @@
};
Lexer.prototype.interpolateString = function(str, options) {
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref2, _ref3, _ref4;
if (options == null) {
options = {};
}
if (options == null) options = {};
heredoc = options.heredoc, regex = options.regex;
tokens = [];
pi = 0;
@ -503,12 +431,8 @@
i += 1;
continue;
}
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
continue;
}
if (pi < i) {
tokens.push(['NEOSTRING', str.slice(pi, i)]);
}
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) continue;
if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]);
inner = expr.slice(1, -1);
if (inner.length) {
nested = new Lexer().tokenize(inner, {
@ -516,9 +440,7 @@
rewrite: false
});
nested.pop();
if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') {
nested.shift();
}
if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') nested.shift();
if (len = nested.length) {
if (len > 1) {
nested.unshift(['(', '(']);
@ -530,35 +452,21 @@
i += expr.length;
pi = i + 1;
}
if ((i > pi && pi < str.length)) {
tokens.push(['NEOSTRING', str.slice(pi)]);
}
if (regex) {
return tokens;
}
if (!tokens.length) {
return this.token('STRING', '""');
}
if (tokens[0][0] !== 'NEOSTRING') {
tokens.unshift(['', '']);
}
if (interpolated = tokens.length > 1) {
this.token('(', '(');
}
if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]);
if (regex) return tokens;
if (!tokens.length) return this.token('STRING', '""');
if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']);
if (interpolated = tokens.length > 1) this.token('(', '(');
for (i = 0, _len = tokens.length; i < _len; i++) {
_ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
if (i) {
this.token('+', '+');
}
if (i) this.token('+', '+');
if (tag === 'TOKENS') {
(_ref4 = this.tokens).push.apply(_ref4, value);
} else {
this.token('STRING', this.makeString(value, '"', heredoc));
}
}
if (interpolated) {
this.token(')', ')');
}
if (interpolated) this.token(')', ')');
return tokens;
};
Lexer.prototype.token = function(tag, value) {
@ -580,9 +488,7 @@
return str.replace(MULTILINER, heredoc ? '\\n' : '');
};
Lexer.prototype.makeString = function(body, quote, heredoc) {
if (!body) {
return quote + quote;
}
if (!body) return quote + quote;
body = body.replace(/\\([\s\S])/g, function(match, contents) {
if (contents === '\n' || contents === quote) {
return contents;

File diff suppressed because it is too large Load Diff

View File

@ -30,9 +30,7 @@
break;
}
}
if (isOption && !matchedRule) {
throw new Error("unrecognized option: " + arg);
}
if (isOption && !matchedRule) throw new Error("unrecognized option: " + arg);
if (!isOption) {
options.arguments = args.slice(i);
break;
@ -43,9 +41,7 @@
OptionParser.prototype.help = function() {
var letPart, lines, rule, spaces, _i, _len, _ref;
lines = [];
if (this.banner) {
lines.unshift("" + this.banner + "\n");
}
if (this.banner) lines.unshift("" + this.banner + "\n");
_ref = this.rules;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
rule = _ref[_i];
@ -67,18 +63,14 @@
_results = [];
for (_i = 0, _len = rules.length; _i < _len; _i++) {
tuple = rules[_i];
if (tuple.length < 3) {
tuple.unshift(null);
}
if (tuple.length < 3) tuple.unshift(null);
_results.push(buildRule.apply(null, tuple));
}
return _results;
};
buildRule = function(shortFlag, longFlag, description, options) {
var match;
if (options == null) {
options = {};
}
if (options == null) options = {};
match = longFlag.match(OPTIONAL);
longFlag = longFlag.match(LONG_FLAG)[1];
return {

File diff suppressed because one or more lines are too long

View File

@ -8,9 +8,7 @@
REPL_PROMPT = 'coffee> ';
REPL_PROMPT_CONTINUATION = '......> ';
enableColours = false;
if (process.platform !== 'win32') {
enableColours = !process.env.NODE_DISABLE_COLORS;
}
if (process.platform !== 'win32') enableColours = !process.env.NODE_DISABLE_COLORS;
stdin = process.openStdin();
stdout = process.stdout;
error = function(err) {
@ -88,9 +86,7 @@
_results = [];
for (_j = 0, _len2 = candidates.length; _j < _len2; _j++) {
el = candidates[_j];
if (el.indexOf(prefix) === 0) {
_results.push(el);
}
if (el.indexOf(prefix) === 0) _results.push(el);
}
return _results;
};

View File

@ -36,12 +36,8 @@
tokens = this.tokens;
levels = 0;
while (token = tokens[i]) {
if (levels === 0 && condition.call(this, token, i)) {
return action.call(this, token, i);
}
if (!token || levels < 0) {
return action.call(this, token, i - 1);
}
if (levels === 0 && condition.call(this, token, i)) return action.call(this, token, i);
if (!token || levels < 0) return action.call(this, token, i - 1);
if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
levels += 1;
} else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
@ -56,20 +52,14 @@
_ref = this.tokens;
for (i = 0, _len = _ref.length; i < _len; i++) {
tag = _ref[i][0];
if (tag !== 'TERMINATOR') {
break;
}
}
if (i) {
return this.tokens.splice(0, i);
if (tag !== 'TERMINATOR') break;
}
if (i) return this.tokens.splice(0, i);
};
Rewriter.prototype.removeMidExpressionNewlines = function() {
return this.scanTokens(function(token, i, tokens) {
var _ref;
if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) {
return 1;
}
if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) return 1;
tokens.splice(i, 1);
return 0;
});
@ -84,9 +74,7 @@
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'CALL_START') {
this.detectEnd(i + 1, condition, action);
}
if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action);
return 1;
});
};
@ -100,9 +88,7 @@
return token[0] = 'INDEX_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'INDEX_START') {
this.detectEnd(i + 1, condition, action);
}
if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action);
return 1;
});
};
@ -114,9 +100,7 @@
condition = function(token, i) {
var one, tag, three, two, _ref, _ref2;
_ref = this.tokens.slice(i + 1, (i + 3 + 1) || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
return false;
}
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false;
tag = token[0];
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
};
@ -136,9 +120,7 @@
start = stack.pop();
return 1;
}
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
return 1;
}
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) return 1;
stack.push(['{']);
idx = ago === '@' ? i - 2 : i - 1;
while (this.tag(idx - 2) === 'HERECOMMENT') {
@ -164,46 +146,26 @@
return this.scanTokens(function(token, i, tokens) {
var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
tag = token[0];
if (tag === 'CLASS' || tag === 'IF') {
noCall = true;
}
if (tag === 'CLASS' || tag === 'IF') noCall = true;
_ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
seenSingle = false;
seenControl = false;
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
noCall = false;
}
if (prev && !prev.spaced && tag === '?') {
token.call = true;
}
if (token.fromThen) {
return 1;
}
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
return 1;
}
if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false;
if (prev && !prev.spaced && tag === '?') token.call = true;
if (token.fromThen) return 1;
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) return 1;
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
this.detectEnd(i + 1, function(token, i) {
var post, _ref4;
tag = token[0];
if (!seenSingle && token.fromThen) {
return true;
}
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
seenSingle = true;
}
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
seenControl = true;
}
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
return true;
}
if (!seenSingle && token.fromThen) return true;
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') seenSingle = true;
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') seenControl = true;
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') return true;
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
}, action);
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
return 2;
});
};
@ -226,9 +188,7 @@
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
starter = tag;
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
if (starter === 'THEN') {
indent.fromThen = true;
}
if (starter === 'THEN') indent.fromThen = true;
indent.generated = outdent.generated = true;
tokens.splice(i + 1, 0, indent);
condition = function(token, i) {
@ -239,9 +199,7 @@
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
};
this.detectEnd(i + 2, condition, action);
if (tag === 'THEN') {
tokens.splice(i, 1);
}
if (tag === 'THEN') tokens.splice(i, 1);
return 1;
}
return 1;
@ -255,14 +213,10 @@
};
return this.scanTokens(function(token, i) {
var original;
if (token[0] !== 'IF') {
return 1;
}
if (token[0] !== 'IF') return 1;
original = token;
this.detectEnd(i + 1, condition, function(token, i) {
if (token[0] !== 'INDENT') {
return original[0] = 'POST_' + original[0];
}
if (token[0] !== 'INDENT') return original[0] = 'POST_' + original[0];
});
return 1;
});
@ -279,9 +233,7 @@
_ref2 = pairs[_j], open = _ref2[0], close = _ref2[1];
levels[open] |= 0;
if (tag === open) {
if (levels[open]++ === 0) {
openLine[open] = token[2];
}
if (levels[open]++ === 0) openLine[open] = token[2];
} else if (tag === close && --levels[open] < 0) {
throw Error("too many " + token[1] + " on line " + (token[2] + 1));
}
@ -289,9 +241,7 @@
}
for (open in levels) {
level = levels[open];
if (level > 0) {
throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
}
if (level > 0) throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
}
return this;
};
@ -308,9 +258,7 @@
stack.push(token);
return 1;
}
if (__indexOf.call(EXPRESSION_END, tag) < 0) {
return 1;
}
if (__indexOf.call(EXPRESSION_END, tag) < 0) return 1;
if (debt[inv = INVERSES[tag]] > 0) {
debt[inv] -= 1;
tokens.splice(i, 1);
@ -319,9 +267,7 @@
match = stack.pop();
mtag = match[0];
oppos = INVERSES[mtag];
if (tag === oppos) {
return 1;
}
if (tag === oppos) return 1;
debt[mtag] += 1;
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
if (this.tag(i + 2) === mtag) {

View File

@ -14,15 +14,11 @@
}
];
this.positions = {};
if (!this.parent) {
Scope.root = this;
}
if (!this.parent) Scope.root = this;
}
Scope.prototype.add = function(name, type, immediate) {
var pos;
if (this.shared && !immediate) {
return this.parent.add(name, type, immediate);
}
if (this.shared && !immediate) return this.parent.add(name, type, immediate);
if (typeof (pos = this.positions[name]) === 'number') {
return this.variables[pos].type = type;
} else {
@ -33,24 +29,18 @@
}
};
Scope.prototype.find = function(name, options) {
if (this.check(name, options)) {
return true;
}
if (this.check(name, options)) return true;
this.add(name, 'var');
return false;
};
Scope.prototype.parameter = function(name) {
if (this.shared && this.parent.check(name, true)) {
return;
}
if (this.shared && this.parent.check(name, true)) return;
return this.add(name, 'param');
};
Scope.prototype.check = function(name, immediate) {
var found, _ref2;
found = !!this.type(name);
if (found || immediate) {
return found;
}
if (found || immediate) return found;
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
};
Scope.prototype.temporary = function(name, index) {
@ -65,9 +55,7 @@
_ref2 = this.variables;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.name === name) {
return v.type;
}
if (v.name === name) return v.type;
}
return null;
};
@ -97,9 +85,7 @@
_ref2 = this.variables;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.type === 'var') {
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
}
if (v.type === 'var') (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
}
return realVars.sort().concat(tempVars.sort());
};
@ -109,9 +95,7 @@
_results = [];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.type.assigned) {
_results.push("" + v.name + " = " + v.type.value);
}
if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value);
}
return _results;
};

View File

@ -93,7 +93,7 @@ exports.eval = (code, options = {}) ->
sandbox.module = _module = new Module(options.modulename || 'eval')
sandbox.require = _require = (path) -> Module._load path, _module
_module.filename = sandbox.__filename
_require[r] = require[r] for r in Object.getOwnPropertyNames require
_require[r] = require[r] for r in Object.getOwnPropertyNames require when r isnt 'paths'
# use the same hack node currently uses for their own REPL
_require.paths = _module.paths = Module._nodeModulePaths process.cwd()
_require.resolve = (request) -> Module._resolveFilename request, _module

View File

@ -279,14 +279,14 @@ grammar =
# Class definitions have optional bodies of prototype property assignments,
# and optional references to the superclass.
Class: [
o 'CLASS', -> new Class
o 'CLASS Block', -> new Class null, null, $2
o 'CLASS EXTENDS Value', -> new Class null, $3
o 'CLASS EXTENDS Value Block', -> new Class null, $3, $4
o 'CLASS SimpleAssignable', -> new Class $2
o 'CLASS SimpleAssignable Block', -> new Class $2, null, $3
o 'CLASS SimpleAssignable EXTENDS Value', -> new Class $2, $4
o 'CLASS SimpleAssignable EXTENDS Value Block', -> new Class $2, $4, $5
o 'CLASS', -> new Class
o 'CLASS Block', -> new Class null, null, $2
o 'CLASS EXTENDS Expression', -> new Class null, $3
o 'CLASS EXTENDS Expression Block', -> new Class null, $3, $4
o 'CLASS SimpleAssignable', -> new Class $2
o 'CLASS SimpleAssignable Block', -> new Class $2, null, $3
o 'CLASS SimpleAssignable EXTENDS Expression', -> new Class $2, $4
o 'CLASS SimpleAssignable EXTENDS Expression Block', -> new Class $2, $4, $5
]
# Ordinary function invocation, or a chained series of calls.

View File

@ -222,7 +222,7 @@ exports.Block = class Block extends Base
else if top
node.front = true
code = node.compile o
codes.push if node.isStatement o then code else @tab + code + ';'
codes.push if node.isStatement o then code else "#{@tab}#{code};"
else
codes.push node.compile o, LEVEL_LIST
return codes.join '\n' if top
@ -328,7 +328,7 @@ exports.Return = class Return extends Base
if expr and expr not instanceof Return then expr.compile o, level else super o, level
compileNode: (o) ->
@tab + "return#{ if @expression then ' ' + @expression.compile(o, LEVEL_PAREN) else '' };"
@tab + "return#{[" #{@expression.compile o, LEVEL_PAREN}" if @expression]};"
#### Value
@ -441,7 +441,7 @@ exports.Comment = class Comment extends Base
makeReturn: THIS
compileNode: (o, level) ->
code = '/*' + multident(@comment, @tab) + '*/'
code = '/*' + multident(@comment, @tab) + "\n#{@tab}*/\n"
code = o.indent + code if (level or o.level) is LEVEL_TOP
code
@ -659,14 +659,14 @@ exports.Range = class Range extends Base
[lt, gt] = ["#{idx} <#{@equals}", "#{idx} >#{@equals}"]
# Generate the condition.
if @stepNum
condPart = if +@stepNum > 0 then "#{lt} #{@toVar}" else "#{gt} #{@toVar}"
condPart = if @stepNum
if +@stepNum > 0 then "#{lt} #{@toVar}" else "#{gt} #{@toVar}"
else if known
[from, to] = [+@fromNum, +@toNum]
condPart = if from <= to then "#{lt} #{to}" else "#{gt} #{to}"
if from <= to then "#{lt} #{to}" else "#{gt} #{to}"
else
cond = "#{@fromVar} <= #{@toVar}"
condPart = "#{cond} ? #{lt} #{@toVar} : #{gt} #{@toVar}"
"#{cond} ? #{lt} #{@toVar} : #{gt} #{@toVar}"
# Generate the step.
stepPart = if @stepVar
@ -892,6 +892,7 @@ exports.Class = class Class extends Base
compileNode: (o) ->
decl = @determineName()
name = decl or @name or '_Class'
name = "_#{name}" if name.reserved
lname = new Literal name
@setContext name
@ -1225,7 +1226,11 @@ exports.While = class While extends Base
rvar = o.scope.freeVariable 'results'
set = "#{@tab}#{rvar} = [];\n"
body = Push.wrap rvar, body if body
body = Block.wrap [new If @guard, body] if @guard
if @guard
if body.expressions.length > 1
body.expressions.unshift new If (new Parens @guard).invert(), new Literal "continue"
else
body = Block.wrap [new If @guard, body] if @guard
body = "\n#{ body.compile o, LEVEL_TOP }\n#{@tab}"
code = set + @tab + "while (#{ @condition.compile o, LEVEL_PAREN }) {#{body}}"
if @returns
@ -1371,7 +1376,7 @@ exports.In = class In extends Base
[sub, ref] = @object.cache o, LEVEL_OP
[cmp, cnj] = if @negated then [' !== ', ' && '] else [' === ', ' || ']
tests = for item, i in @array.base.objects
(if i then ref else sub) + cmp + item.compile o, LEVEL_OP
(if i then ref else sub) + cmp + item.compile o, LEVEL_ACCESS
return 'false' if tests.length is 0
tests = tests.join cnj
if o.level < LEVEL_OP then tests else "(#{tests})"
@ -1560,7 +1565,10 @@ exports.For = class For extends Base
returnResult = "\n#{@tab}return #{rvar};"
body = Push.wrap rvar, body
if @guard
body = Block.wrap [new If @guard, body]
if body.expressions.length > 1
body.expressions.unshift new If (new Parens @guard).invert(), new Literal "continue"
else
body = Block.wrap [new If @guard, body] if @guard
if @pattern
body.expressions.unshift new Assign @name, new Literal "#{svar}[#{ivar}]"
defPart += @pluckDirectCall o, body
@ -1688,9 +1696,12 @@ exports.If = class If extends Base
cond = @condition.compile o, LEVEL_PAREN
o.indent += TAB
body = @ensureBlock(@body).compile o
body = "\n#{body}\n#{@tab}" if body
ifPart = "if (#{cond}) {#{body}}"
body = @ensureBlock(@body)
bodyc = body.compile o
if body.expressions.length is 1 and !@elseBody and !child and bodyc and -1 is bodyc.indexOf '\n'
return "#{@tab}if (#{cond}) #{bodyc.replace /^\s+/, ''}"
bodyc = "\n#{bodyc}\n#{@tab}" if bodyc
ifPart = "if (#{cond}) {#{bodyc}}"
ifPart = @tab + ifPart unless child
return ifPart unless @elseBody
ifPart + ' else ' + if @isChain
@ -1840,4 +1851,5 @@ utility = (name) ->
ref
multident = (code, tab) ->
code.replace /\n/g, '$&' + tab
code = code.replace /\n/g, '$&' + tab
code.replace /\s+$/, ''

View File

@ -500,3 +500,13 @@ test "#1464: bound class methods should keep context", ->
@boundStaticEqual= => new this(nonce2)
eq nonce, C.boundStaticColon().id
eq nonce2, C.boundStaticEqual().id
test "#1009: classes with reserved words as determined names", ->
eq 'function', typeof (-> class @for).call {}
test "#1482: classes can extend expressions", ->
id = (x) -> x
nonce = {}
class A then nonce: nonce
class B extends id A
eq nonce, (new B).nonce

View File

@ -187,11 +187,16 @@ test "#768: `in` should preserve evaluation order", ->
test "#1099: empty array after `in` should compile to `false`", ->
eq 1, [5 in []].length
eq false, do -> return 0 in []
test "#1354: optimized `in` checks should not happen when splats are present", ->
a = [6, 9]
eq 9 in [3, a...], true
test "#1100: precedence in or-test compilation of `in`", ->
ok 0 in [1 and 0]
ok 0 in [1, 1 and 0]
ok not (0 in [1, 0 or 1])
# Chained Comparison