1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

[CS2] Destructuring (#4478)

* Output simple array destructuring assignments to ES2015

* Output simple object destructured assignments to ES2015

* Compile shorthand object properties to ES2015 shorthand properties

This dramatically improves the appearance of destructured imports.

* Compile default values in destructured assignment to ES2015

* Rename `wrapInBraces` to `wrapInParentheses`, and `compilePatternMatch` to `compileDestructuring`, for clarity; style improvements (no `==` or `!=`, etc.)

* Don’t confuse the syntax highlighter

* Comment Assign::compilePatternMatch a bit

* Assignment expressions in conditionals are a bad practice

* Optional check for existence that only checks `!== undefined`, not `!= null`, to follow ES convention that default values only apply when a variable is undefined, not falsy

* Add comments; remove unnecessary array splats in function tests

* The fallback destructuring code should apply default values only if `undefined`, not falsy, to follow ES spec

* Support destructuring in function parameters (first pass); catch destructured reserved words

* Destructured variables in function parameter lists shouldn’t be added to the function body with `var` declarations; treat splat array function parameters the legacy way to avoid rethinking #4005

* Remove redundancy in undefined-only check for existence; fix passing option to check

* Fix undefined redundancy

* Simplify getting the variable name

* Reimplement “check for existence if not undefined” without creating a new operator

* `Obj::isAssignable` should not mutate; pass `lhs` property in from `Assign` or `Code` to child arrays and objects so that those child nodes are set as allowable for destructuring

* Revert changes to tests

* Restore revised test for empty destructuring assignment
This commit is contained in:
Geoffrey Booth 2017-04-06 10:06:45 -07:00 committed by GitHub
parent 5e1d978946
commit b192e215a5
17 changed files with 953 additions and 646 deletions

View file

@ -24,15 +24,10 @@
helpers.extend(global, {
task: function(name, description, action) {
var ref;
if (!action) {
ref = [description, action], action = ref[0], description = ref[1];
[action, description] = [description, action];
}
return tasks[name] = {
name: name,
description: description,
action: action
};
return tasks[name] = {name, description, action};
},
option: function(letter, flag, description) {
return switches.push([letter, flag, description]);

View file

@ -9,9 +9,9 @@
path = require('path');
Lexer = require('./lexer').Lexer;
({Lexer} = require('./lexer'));
parser = require('./parser').parser;
({parser} = require('./parser'));
helpers = require('./helpers');
@ -59,7 +59,7 @@
exports.compile = compile = withPrettyErrors(function(code, options) {
var currentColumn, currentLine, encoded, extend, filename, fragment, fragments, generateSourceMap, header, i, j, js, len, len1, map, merge, newLines, ref, ref1, sourceMapDataURI, sourceURL, token, tokens, v3SourceMap;
merge = helpers.merge, extend = helpers.extend;
({merge, extend} = helpers);
options = extend({}, options);
generateSourceMap = options.sourceMap || options.inlineMap || (options.filename == null);
filename = options.filename || '<anonymous>';
@ -132,7 +132,7 @@
}
if (options.sourceMap) {
return {
js: js,
js,
sourceMap: map,
v3SourceMap: JSON.stringify(v3SourceMap, null, 2)
};
@ -254,9 +254,9 @@
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
try {
answer = compile(stripped, {
filename: filename,
sourceMap: sourceMap,
inlineMap: inlineMap,
filename,
sourceMap,
inlineMap,
sourceFiles: [filename],
literate: helpers.isLiterate(filename)
});
@ -274,7 +274,7 @@
var tag, token;
token = parser.tokens[this.pos++];
if (token) {
tag = token[0], this.yytext = token[1], this.yylloc = token[2];
[tag, this.yytext, this.yylloc] = token;
parser.errorToken = token.origin || token;
this.yylineno = this.yylloc.first_line;
} else {
@ -293,11 +293,10 @@
parser.yy = require('./nodes');
parser.yy.parseError = function(message, arg) {
var errorLoc, errorTag, errorText, errorToken, token, tokens;
token = arg.token;
errorToken = parser.errorToken, tokens = parser.tokens;
errorTag = errorToken[0], errorText = errorToken[1], errorLoc = errorToken[2];
parser.yy.parseError = function(message, {token}) {
var errorLoc, errorTag, errorText, errorToken, tokens;
({errorToken, tokens} = parser);
[errorTag, errorText, errorLoc] = errorToken;
errorText = (function() {
switch (false) {
case errorToken !== tokens[tokens.length - 1]:

View file

@ -1,6 +1,6 @@
// Generated by CoffeeScript 2.0.0-alpha1
(function() {
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, makePrelude, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, ref, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs,
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, makePrelude, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
fs = require('fs');
@ -13,9 +13,9 @@
CoffeeScript = require('./coffeescript');
ref = require('child_process'), spawn = ref.spawn, exec = ref.exec;
({spawn, exec} = require('child_process'));
EventEmitter = require('events').EventEmitter;
({EventEmitter} = require('events'));
useWinPathSep = path.sep === '\\';
@ -50,7 +50,7 @@
optionParser = null;
exports.run = function() {
var i, len, literals, ref1, replCliOpts, results, source;
var i, len, literals, ref, replCliOpts, results, source;
parseOptions();
replCliOpts = {
useGlobal: true
@ -90,10 +90,10 @@
opts.join = path.resolve(opts.join);
console.error('\nThe --join option is deprecated and will be removed in a future version.\n\nIf for some reason it\'s necessary to share local variables between files,\nreplace...\n\n $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee\n\nwith...\n\n $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js\n');
}
ref1 = opts["arguments"];
ref = opts["arguments"];
results = [];
for (i = 0, len = ref1.length; i < len; i++) {
source = ref1[i];
for (i = 0, len = ref.length; i < len; i++) {
source = ref[i];
source = path.resolve(source);
results.push(compilePath(source, true, source));
}
@ -104,7 +104,7 @@
return requires.map(function(module) {
var _, match, name;
if (match = module.match(/^(.*)=(.*)$/)) {
_ = match[0], name = match[1], module = match[2];
[_, name, module] = match;
}
name || (name = helpers.baseFileName(module, true, useWinPathSep));
return `${name} = require('${module}')`;
@ -178,10 +178,10 @@
};
findDirectoryIndex = function(source) {
var err, ext, i, index, len, ref1;
ref1 = CoffeeScript.FILE_EXTENSIONS;
for (i = 0, len = ref1.length; i < len; i++) {
ext = ref1[i];
var err, ext, i, index, len, ref;
ref = CoffeeScript.FILE_EXTENSIONS;
for (i = 0, len = ref.length; i < len; i++) {
ext = ref[i];
index = path.join(source, `index${ext}`);
try {
if ((fs.statSync(index)).isFile()) {
@ -203,11 +203,7 @@
o = opts;
options = compileOptions(file, base);
try {
t = task = {
file: file,
input: input,
options: options
};
t = task = {file, input, options};
CoffeeScript.emit('compile', task);
if (o.tokens) {
return printTokens(CoffeeScript.tokens(t.input, t.options));
@ -425,12 +421,12 @@
};
silentUnlink = function(path) {
var err, ref1;
var err, ref;
try {
return fs.unlinkSync(path);
} catch (error) {
err = error;
if ((ref1 = err.code) !== 'ENOENT' && ref1 !== 'EPERM') {
if ((ref = err.code) !== 'ENOENT' && ref !== 'EPERM') {
throw err;
}
}
@ -546,7 +542,7 @@
compileOptions = function(filename, base) {
var answer, cwd, jsDir, jsPath;
answer = {
filename: filename,
filename,
literate: opts.literate || helpers.isLiterate(filename),
bare: opts.bare,
header: opts.compile && !opts['no-header'],
@ -559,7 +555,7 @@
jsPath = outputPath(filename, base);
jsDir = path.dirname(jsPath);
answer = helpers.merge(answer, {
jsPath: jsPath,
jsPath,
sourceRoot: path.relative(jsDir, cwd),
sourceFiles: [path.relative(cwd, filename)],
generatedFile: helpers.baseFileName(jsPath, false, useWinPathSep)

View file

@ -2,7 +2,7 @@
(function() {
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
Parser = require('jison').Parser;
({Parser} = require('jison'));
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;

View file

@ -196,11 +196,11 @@
};
syntaxErrorToString = function() {
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, ref4, start;
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, start;
if (!(this.code && this.location)) {
return Error.prototype.toString.call(this);
}
ref1 = this.location, first_line = ref1.first_line, first_column = ref1.first_column, last_line = ref1.last_line, last_column = ref1.last_column;
({first_line, first_column, last_line, last_column} = this.location);
if (last_line == null) {
last_line = first_line;
}
@ -213,9 +213,9 @@
end = first_line === last_line ? last_column + 1 : codeLine.length;
marker = codeLine.slice(0, start).replace(/[^\s]/g, ' ') + repeat('^', end - start);
if (typeof process !== "undefined" && process !== null) {
colorsEnabled = ((ref2 = process.stdout) != null ? ref2.isTTY : void 0) && !((ref3 = process.env) != null ? ref3.NODE_DISABLE_COLORS : void 0);
colorsEnabled = ((ref1 = process.stdout) != null ? ref1.isTTY : void 0) && !((ref2 = process.env) != null ? ref2.NODE_DISABLE_COLORS : void 0);
}
if ((ref4 = this.colorful) != null ? ref4 : colorsEnabled) {
if ((ref3 = this.colorful) != null ? ref3 : colorsEnabled) {
colorize = function(str) {
return `\x1B[1;31m${str}\x1B[0m`;
};

View file

@ -1,15 +1,15 @@
// Generated by CoffeeScript 2.0.0-alpha1
(function() {
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVALID_ESCAPE, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, ref, ref1, repeat, starts, throwSyntaxError,
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVALID_ESCAPE, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, repeat, starts, throwSyntaxError,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
ref = require('./rewriter'), Rewriter = ref.Rewriter, INVERSES = ref.INVERSES;
({Rewriter, INVERSES} = require('./rewriter'));
ref1 = require('./helpers'), count = ref1.count, starts = ref1.starts, compact = ref1.compact, repeat = ref1.repeat, invertLiterate = ref1.invertLiterate, locationDataToString = ref1.locationDataToString, throwSyntaxError = ref1.throwSyntaxError;
({count, starts, compact, repeat, invertLiterate, locationDataToString, throwSyntaxError} = require('./helpers'));
exports.Lexer = Lexer = class Lexer {
tokenize(code, opts = {}) {
var consumed, end, i, ref2;
var consumed, end, i;
this.literate = opts.literate;
this.indent = 0;
this.baseIndent = 0;
@ -29,7 +29,7 @@
i = 0;
while (this.chunk = code.slice(i)) {
consumed = this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
ref2 = this.getLineAndColumnFromChunk(consumed), this.chunkLine = ref2[0], this.chunkColumn = ref2[1];
[this.chunkLine, this.chunkColumn] = this.getLineAndColumnFromChunk(consumed);
i += consumed;
if (opts.untilBalanced && this.ends.length === 0) {
return {
@ -64,11 +64,11 @@
}
identifierToken() {
var alias, colon, colonOffset, id, idLength, input, match, poppedToken, prev, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, tag, tagToken;
var alias, colon, colonOffset, id, idLength, input, match, poppedToken, prev, ref, ref1, ref2, ref3, ref4, ref5, ref6, tag, tagToken;
if (!(match = IDENTIFIER.exec(this.chunk))) {
return 0;
}
input = match[0], id = match[1], colon = match[2];
[input, id, colon] = match;
idLength = id.length;
poppedToken = void 0;
if (id === 'own' && this.tag() === 'FOR') {
@ -82,27 +82,27 @@
if (id === 'as' && this.seenImport) {
if (this.value() === '*') {
this.tokens[this.tokens.length - 1][0] = 'IMPORT_ALL';
} else if (ref2 = this.value(), indexOf.call(COFFEE_KEYWORDS, ref2) >= 0) {
} else if (ref = this.value(), indexOf.call(COFFEE_KEYWORDS, ref) >= 0) {
this.tokens[this.tokens.length - 1][0] = 'IDENTIFIER';
}
if ((ref3 = this.tag()) === 'DEFAULT' || ref3 === 'IMPORT_ALL' || ref3 === 'IDENTIFIER') {
if ((ref1 = this.tag()) === 'DEFAULT' || ref1 === 'IMPORT_ALL' || ref1 === 'IDENTIFIER') {
this.token('AS', id);
return id.length;
}
}
if (id === 'as' && this.seenExport && ((ref4 = this.tag()) === 'IDENTIFIER' || ref4 === 'DEFAULT')) {
if (id === 'as' && this.seenExport && ((ref2 = this.tag()) === 'IDENTIFIER' || ref2 === 'DEFAULT')) {
this.token('AS', id);
return id.length;
}
if (id === 'default' && this.seenExport && ((ref5 = this.tag()) === 'EXPORT' || ref5 === 'AS')) {
if (id === 'default' && this.seenExport && ((ref3 = this.tag()) === 'EXPORT' || ref3 === 'AS')) {
this.token('DEFAULT', id);
return id.length;
}
ref6 = this.tokens, prev = ref6[ref6.length - 1];
tag = colon || (prev != null) && (((ref7 = prev[0]) === '.' || ref7 === '?.' || ref7 === '::' || ref7 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
ref4 = this.tokens, prev = ref4[ref4.length - 1];
tag = colon || (prev != null) && (((ref5 = prev[0]) === '.' || ref5 === '?.' || ref5 === '::' || ref5 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
if (tag === 'IDENTIFIER' && (indexOf.call(JS_KEYWORDS, id) >= 0 || indexOf.call(COFFEE_KEYWORDS, id) >= 0) && !(this.exportSpecifierList && indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
tag = id.toUpperCase();
if (tag === 'WHEN' && (ref8 = this.tag(), indexOf.call(LINE_BREAK, ref8) >= 0)) {
if (tag === 'WHEN' && (ref6 = this.tag(), indexOf.call(LINE_BREAK, ref6) >= 0)) {
tag = 'LEADING_WHEN';
} else if (tag === 'FOR') {
this.seenFor = true;
@ -167,7 +167,7 @@
tagToken.origin = [tag, alias, tagToken[2]];
}
if (poppedToken) {
ref9 = [poppedToken[2].first_line, poppedToken[2].first_column], tagToken[2].first_line = ref9[0], tagToken[2].first_column = ref9[1];
[tagToken[2].first_line, tagToken[2].first_column] = [poppedToken[2].first_line, poppedToken[2].first_column];
}
if (colon) {
colonOffset = input.lastIndexOf(':');
@ -223,8 +223,8 @@
}
stringToken() {
var $, attempt, delimiter, doc, end, heredoc, i, indent, indentRegex, match, quote, ref2, ref3, regex, token, tokens;
quote = (STRING_START.exec(this.chunk) || [])[0];
var $, attempt, delimiter, doc, end, heredoc, i, indent, indentRegex, match, quote, ref, regex, token, tokens;
[quote] = STRING_START.exec(this.chunk) || [];
if (!quote) {
return 0;
}
@ -244,7 +244,10 @@
}
})();
heredoc = quote.length === 3;
ref2 = this.matchWithInterpolations(regex, quote), tokens = ref2.tokens, end = ref2.index;
({
tokens,
index: end
} = this.matchWithInterpolations(regex, quote));
$ = tokens.length - 1;
delimiter = quote.charAt(0);
if (heredoc) {
@ -262,16 +265,14 @@
})()).join('#{}');
while (match = HEREDOC_INDENT.exec(doc)) {
attempt = match[1];
if (indent === null || (0 < (ref3 = attempt.length) && ref3 < indent.length)) {
if (indent === null || (0 < (ref = attempt.length) && ref < indent.length)) {
indent = attempt;
}
}
if (indent) {
indentRegex = RegExp(`\\n${indent}`, "g");
}
this.mergeInterpolationTokens(tokens, {
delimiter: delimiter
}, (value, i) => {
this.mergeInterpolationTokens(tokens, {delimiter}, (value, i) => {
value = this.formatString(value);
if (indentRegex) {
value = value.replace(indentRegex, '\n');
@ -285,9 +286,7 @@
return value;
});
} else {
this.mergeInterpolationTokens(tokens, {
delimiter: delimiter
}, (value, i) => {
this.mergeInterpolationTokens(tokens, {delimiter}, (value, i) => {
value = this.formatString(value);
value = value.replace(SIMPLE_STRING_OMIT, function(match, offset) {
if ((i === 0 && offset === 0) || (i === $ && offset + match.length === value.length)) {
@ -307,7 +306,7 @@
if (!(match = this.chunk.match(COMMENT))) {
return 0;
}
comment = match[0], here = match[1];
[comment, here] = match;
if (here) {
if (match = HERECOMMENT_ILLEGAL.exec(comment)) {
this.error(`block comments cannot contain ${match[0]}`, {
@ -336,7 +335,7 @@
}
regexToken() {
var body, closed, end, flags, index, match, origin, prev, ref2, ref3, ref4, regex, tokens;
var body, closed, end, flags, index, match, origin, prev, ref, ref1, ref2, regex, tokens;
switch (false) {
case !(match = REGEX_ILLEGAL.exec(this.chunk)):
this.error(`regular expressions cannot begin with ${match[2]}`, {
@ -344,22 +343,22 @@
});
break;
case !(match = this.matchWithInterpolations(HEREGEX, '///')):
tokens = match.tokens, index = match.index;
({tokens, index} = match);
break;
case !(match = REGEX.exec(this.chunk)):
regex = match[0], body = match[1], closed = match[2];
[regex, body, closed] = match;
this.validateEscapes(body, {
isRegex: true,
offsetInChunk: 1
});
index = regex.length;
ref2 = this.tokens, prev = ref2[ref2.length - 1];
ref = this.tokens, prev = ref[ref.length - 1];
if (prev) {
if (prev.spaced && (ref3 = prev[0], indexOf.call(CALLABLE, ref3) >= 0)) {
if (prev.spaced && (ref1 = prev[0], indexOf.call(CALLABLE, ref1) >= 0)) {
if (!closed || POSSIBLY_DIVISION.test(regex)) {
return 0;
}
} else if (ref4 = prev[0], indexOf.call(NOT_REGEX, ref4) >= 0) {
} else if (ref2 = prev[0], indexOf.call(NOT_REGEX, ref2) >= 0) {
return 0;
}
}
@ -370,7 +369,7 @@
default:
return 0;
}
flags = REGEX_FLAGS.exec(this.chunk.slice(index))[0];
[flags] = REGEX_FLAGS.exec(this.chunk.slice(index));
end = index + flags.length;
origin = this.makeToken('REGEX', null, 0, end);
switch (false) {
@ -469,7 +468,7 @@
}
outdentToken(moveOut, noNewlines, outdentLength) {
var decreasedIndent, dent, lastIndent, ref2;
var decreasedIndent, dent, lastIndent, ref;
decreasedIndent = this.indent - moveOut;
while (moveOut > 0) {
lastIndent = this.indents[this.indents.length - 1];
@ -483,7 +482,7 @@
moveOut -= lastIndent;
} else {
dent = this.indents.pop() + this.outdebt;
if (outdentLength && (ref2 = this.chunk[outdentLength], indexOf.call(INDENTABLE_CLOSERS, ref2) >= 0)) {
if (outdentLength && (ref = this.chunk[outdentLength], indexOf.call(INDENTABLE_CLOSERS, ref) >= 0)) {
decreasedIndent -= dent - moveOut;
moveOut = dent;
}
@ -508,11 +507,11 @@
}
whitespaceToken() {
var match, nline, prev, ref2;
var match, nline, prev, ref;
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
return 0;
}
ref2 = this.tokens, prev = ref2[ref2.length - 1];
ref = this.tokens, prev = ref[ref.length - 1];
if (prev) {
prev[match ? 'spaced' : 'newLine'] = true;
}
@ -541,9 +540,9 @@
}
literalToken() {
var match, message, origin, prev, ref2, ref3, ref4, ref5, ref6, skipToken, tag, token, value;
var match, message, origin, prev, ref, ref1, ref2, ref3, ref4, skipToken, tag, token, value;
if (match = OPERATOR.exec(this.chunk)) {
value = match[0];
[value] = match;
if (CODE.test(value)) {
this.tagParameters();
}
@ -551,17 +550,17 @@
value = this.chunk.charAt(0);
}
tag = value;
ref2 = this.tokens, prev = ref2[ref2.length - 1];
ref = this.tokens, prev = ref[ref.length - 1];
if (prev && indexOf.call(['=', ...COMPOUND_ASSIGN], value) >= 0) {
skipToken = false;
if (value === '=' && ((ref3 = prev[1]) === '||' || ref3 === '&&') && !prev.spaced) {
if (value === '=' && ((ref1 = prev[1]) === '||' || ref1 === '&&') && !prev.spaced) {
prev[0] = 'COMPOUND_ASSIGN';
prev[1] += '=';
prev = this.tokens[this.tokens.length - 2];
skipToken = true;
}
if (prev && prev[0] !== 'PROPERTY') {
origin = (ref4 = prev.origin) != null ? ref4 : prev;
origin = (ref2 = prev.origin) != null ? ref2 : prev;
message = isUnassignable(prev[1], origin[1]);
if (message) {
this.error(message, origin[2]);
@ -596,12 +595,12 @@
} else if (value === '?' && (prev != null ? prev.spaced : void 0)) {
tag = 'BIN?';
} else if (prev && !prev.spaced) {
if (value === '(' && (ref5 = prev[0], indexOf.call(CALLABLE, ref5) >= 0)) {
if (value === '(' && (ref3 = prev[0], indexOf.call(CALLABLE, ref3) >= 0)) {
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}
tag = 'CALL_START';
} else if (value === '[' && (ref6 = prev[0], indexOf.call(INDEXABLE, ref6) >= 0)) {
} else if (value === '[' && (ref4 = prev[0], indexOf.call(INDEXABLE, ref4) >= 0)) {
tag = 'INDEX_START';
switch (prev[0]) {
case '?':
@ -634,7 +633,7 @@
return this;
}
stack = [];
tokens = this.tokens;
({tokens} = this);
i = tokens.length;
tokens[--i][0] = 'PARAM_END';
while (tok = tokens[--i]) {
@ -662,7 +661,7 @@
}
matchWithInterpolations(regex, delimiter) {
var close, column, firstToken, index, lastToken, line, nested, offsetInChunk, open, ref2, ref3, ref4, str, strPart, tokens;
var close, column, firstToken, index, lastToken, line, nested, offsetInChunk, open, ref, str, strPart, tokens;
tokens = [];
offsetInChunk = delimiter.length;
if (this.chunk.slice(0, offsetInChunk) !== delimiter) {
@ -670,10 +669,10 @@
}
str = this.chunk.slice(offsetInChunk);
while (true) {
strPart = regex.exec(str)[0];
[strPart] = regex.exec(str);
this.validateEscapes(strPart, {
isRegex: delimiter.charAt(0) === '/',
offsetInChunk: offsetInChunk
offsetInChunk
});
tokens.push(this.makeToken('NEOSTRING', strPart, offsetInChunk));
str = str.slice(strPart.length);
@ -681,18 +680,21 @@
if (str.slice(0, 2) !== '#{') {
break;
}
ref2 = this.getLineAndColumnFromChunk(offsetInChunk + 1), line = ref2[0], column = ref2[1];
ref3 = new Lexer().tokenize(str.slice(1), {
[line, column] = this.getLineAndColumnFromChunk(offsetInChunk + 1);
({
tokens: nested,
index
} = new Lexer().tokenize(str.slice(1), {
line: line,
column: column,
untilBalanced: true
}), nested = ref3.tokens, index = ref3.index;
}));
index += 1;
open = nested[0], close = nested[nested.length - 1];
open[0] = open[1] = '(';
close[0] = close[1] = ')';
close.origin = ['', 'end of interpolation', close[2]];
if (((ref4 = nested[1]) != null ? ref4[0] : void 0) === 'TERMINATOR') {
if (((ref = nested[1]) != null ? ref[0] : void 0) === 'TERMINATOR') {
nested.splice(1, 1);
}
tokens.push(['TOKENS', nested]);
@ -716,7 +718,7 @@
lastToken[2].last_column -= 1;
}
return {
tokens: tokens,
tokens,
index: offsetInChunk + delimiter.length
};
}
@ -729,7 +731,7 @@
firstIndex = this.tokens.length;
for (i = j = 0, len = tokens.length; j < len; i = ++j) {
token = tokens[i];
tag = token[0], value = token[1];
[tag, value] = token;
switch (tag) {
case 'TOKENS':
if (value.length === 2) {
@ -787,13 +789,13 @@
}
pair(tag) {
var lastIndent, prev, ref2, ref3, wanted;
ref2 = this.ends, prev = ref2[ref2.length - 1];
var lastIndent, prev, ref, ref1, wanted;
ref = this.ends, prev = ref[ref.length - 1];
if (tag !== (wanted = prev != null ? prev.tag : void 0)) {
if ('OUTDENT' !== wanted) {
this.error(`unmatched ${tag}`);
}
ref3 = this.indents, lastIndent = ref3[ref3.length - 1];
ref1 = this.indents, lastIndent = ref1[ref1.length - 1];
this.outdentToken(lastIndent, true);
return this.pair(tag);
}
@ -801,7 +803,7 @@
}
getLineAndColumnFromChunk(offset) {
var column, lastLine, lineCount, ref2, string;
var column, lastLine, lineCount, ref, string;
if (offset === 0) {
return [this.chunkLine, this.chunkColumn];
}
@ -813,7 +815,7 @@
lineCount = count(string, '\n');
column = this.chunkColumn;
if (lineCount > 0) {
ref2 = string.split('\n'), lastLine = ref2[ref2.length - 1];
ref = string.split('\n'), lastLine = ref[ref.length - 1];
column = lastLine.length;
} else {
column += string.length;
@ -822,11 +824,11 @@
}
makeToken(tag, value, offsetInChunk = 0, length = value.length) {
var lastCharacter, locationData, ref2, ref3, token;
var lastCharacter, locationData, token;
locationData = {};
ref2 = this.getLineAndColumnFromChunk(offsetInChunk), locationData.first_line = ref2[0], locationData.first_column = ref2[1];
[locationData.first_line, locationData.first_column] = this.getLineAndColumnFromChunk(offsetInChunk);
lastCharacter = length > 0 ? length - 1 : 0;
ref3 = this.getLineAndColumnFromChunk(offsetInChunk + lastCharacter), locationData.last_line = ref3[0], locationData.last_column = ref3[1];
[locationData.last_line, locationData.last_column] = this.getLineAndColumnFromChunk(offsetInChunk + lastCharacter);
token = [tag, value, locationData];
return token;
}
@ -842,20 +844,20 @@
}
tag() {
var ref2, token;
ref2 = this.tokens, token = ref2[ref2.length - 1];
var ref, token;
ref = this.tokens, token = ref[ref.length - 1];
return token != null ? token[0] : void 0;
}
value() {
var ref2, token;
ref2 = this.tokens, token = ref2[ref2.length - 1];
var ref, token;
ref = this.tokens, token = ref[ref.length - 1];
return token != null ? token[1] : void 0;
}
unfinished() {
var ref2;
return LINE_CONTINUER.test(this.chunk) || ((ref2 = this.tag()) === '\\' || ref2 === '.' || ref2 === '?.' || ref2 === '?::' || ref2 === 'UNARY' || ref2 === 'MATH' || ref2 === 'UNARY_MATH' || ref2 === '+' || ref2 === '-' || ref2 === '**' || ref2 === 'SHIFT' || ref2 === 'RELATION' || ref2 === 'COMPARE' || ref2 === '&' || ref2 === '^' || ref2 === '|' || ref2 === '&&' || ref2 === '||' || ref2 === 'BIN?' || ref2 === 'THROW' || ref2 === 'EXTENDS');
var ref;
return LINE_CONTINUER.test(this.chunk) || ((ref = this.tag()) === '\\' || ref === '.' || ref === '?.' || ref === '?::' || ref === 'UNARY' || ref === 'MATH' || ref === 'UNARY_MATH' || ref === '+' || ref === '-' || ref === '**' || ref === 'SHIFT' || ref === 'RELATION' || ref === 'COMPARE' || ref === '&' || ref === '^' || ref === '|' || ref === '&&' || ref === '||' || ref === 'BIN?' || ref === 'THROW' || ref === 'EXTENDS');
}
formatString(str) {
@ -867,7 +869,7 @@
}
validateEscapes(str, options = {}) {
var before, hex, invalidEscape, match, message, octal, ref2, unicode;
var before, hex, invalidEscape, match, message, octal, ref, unicode;
match = INVALID_ESCAPE.exec(str);
if (!match) {
return;
@ -879,7 +881,7 @@
message = octal ? "octal escape sequences are not allowed" : "invalid escape sequence";
invalidEscape = `\\${octal || hex || unicode}`;
return this.error(`${message} ${invalidEscape}`, {
offset: ((ref2 = options.offsetInChunk) != null ? ref2 : 0) + match.index + before.length,
offset: ((ref = options.offsetInChunk) != null ? ref : 0) + match.index + before.length,
length: invalidEscape.length
});
}
@ -922,11 +924,11 @@
}
error(message, options = {}) {
var first_column, first_line, location, ref2, ref3, ref4;
location = 'first_line' in options ? options : ((ref3 = this.getLineAndColumnFromChunk((ref2 = options.offset) != null ? ref2 : 0), first_line = ref3[0], first_column = ref3[1], ref3), {
first_line: first_line,
first_column: first_column,
last_column: first_column + ((ref4 = options.length) != null ? ref4 : 1) - 1
var first_column, first_line, location, ref, ref1;
location = 'first_line' in options ? options : ([first_line, first_column] = this.getLineAndColumnFromChunk((ref = options.offset) != null ? ref : 0), {
first_line,
first_column,
last_column: first_column + ((ref1 = options.length) != null ? ref1 : 1) - 1
});
return throwSyntaxError(message, location);
}
@ -949,7 +951,7 @@
exports.isUnassignable = isUnassignable;
isForFrom = function(prev) {
var ref2;
var ref;
if (prev[0] === 'IDENTIFIER') {
if (prev[1] === 'from') {
prev[1][0] = 'IDENTIFIER';
@ -958,7 +960,7 @@
return true;
} else if (prev[0] === 'FOR') {
return false;
} else if ((ref2 = prev[1]) === '{' || ref2 === '[' || ref2 === ',' || ref2 === ':') {
} else if ((ref = prev[1]) === '{' || ref === '[' || ref === ',' || ref === ':') {
return false;
} else {
return true;

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat;
repeat = require('./helpers').repeat;
({repeat} = require('./helpers'));
exports.OptionParser = OptionParser = class OptionParser {
constructor(rules, banner) {

View file

@ -48,7 +48,7 @@
}
if (child_process) {
fork = child_process.fork;
({fork} = child_process);
binary = require.resolve('../../bin/coffee');
child_process.fork = function(path, args, options) {
if (helpers.isCoffee(path)) {

View file

@ -1,6 +1,6 @@
// Generated by CoffeeScript 2.0.0-alpha1
(function() {
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, ref, replDefaults, runInContext, updateSyntaxError, vm;
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, updateSyntaxError, vm;
fs = require('fs');
@ -12,18 +12,18 @@
CoffeeScript = require('./coffeescript');
ref = require('./helpers'), merge = ref.merge, updateSyntaxError = ref.updateSyntaxError;
({merge, updateSyntaxError} = require('./helpers'));
replDefaults = {
prompt: 'coffee> ',
historyFile: process.env.HOME ? path.join(process.env.HOME, '.coffee_history') : void 0,
historyMaxInputSize: 10240,
"eval": function(input, context, filename, cb) {
var Assign, Block, Literal, Value, ast, err, js, ref1, referencedVars, token, tokens;
var Assign, Block, Literal, Value, ast, err, js, referencedVars, token, tokens;
input = input.replace(/\uFF00/g, '\n');
input = input.replace(/^\(([\s\S]*)\n\)$/m, '$1');
input = input.replace(/^\s*try\s*{([\s\S]*)}\s*catch.*$/m, '$1');
ref1 = require('./nodes'), Block = ref1.Block, Assign = ref1.Assign, Value = ref1.Value, Literal = ref1.Literal;
({Block, Assign, Value, Literal} = require('./nodes'));
try {
tokens = CoffeeScript.tokens(input);
referencedVars = (function() {
@ -42,7 +42,7 @@
js = ast.compile({
bare: true,
locals: Object.keys(context),
referencedVars: referencedVars
referencedVars
});
return cb(null, runInContext(js, context, filename));
} catch (error) {
@ -62,9 +62,9 @@
};
addMultilineHandler = function(repl) {
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref1, rli;
rli = repl.rli, inputStream = repl.inputStream, outputStream = repl.outputStream;
origPrompt = (ref1 = repl._prompt) != null ? ref1 : repl.prompt;
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref, rli;
({rli, inputStream, outputStream} = repl);
origPrompt = (ref = repl._prompt) != null ? ref : repl.prompt;
multiline = {
enabled: false,
initialPrompt: origPrompt.replace(/^[^> ]*/, function(x) {
@ -168,10 +168,10 @@
module.exports = {
start: function(opts = {}) {
var build, major, minor, ref1, repl;
ref1 = process.versions.node.split('.').map(function(n) {
var build, major, minor, repl;
[major, minor, build] = process.versions.node.split('.').map(function(n) {
return parseInt(n);
}), major = ref1[0], minor = ref1[1], build = ref1[2];
});
if (major < 6) {
console.warn("Node 6+ required for CoffeeScript REPL");
process.exit(1);

View file

@ -1,6 +1,6 @@
// Generated by CoffeeScript 2.0.0-alpha1
(function() {
var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, ref, rite,
var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, rite,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
generate = function(tag, value, origin) {
@ -30,7 +30,7 @@
scanTokens(block) {
var i, token, tokens;
tokens = this.tokens;
({tokens} = this);
i = 0;
while (token = tokens[i]) {
i += block.call(this, token, i, tokens);
@ -40,7 +40,7 @@
detectEnd(i, condition, action) {
var levels, ref, ref1, token, tokens;
tokens = this.tokens;
({tokens} = this);
levels = 0;
while (token = tokens[i]) {
if (levels === 0 && condition.call(this, token, i)) {
@ -63,7 +63,7 @@
var i, k, len, ref, tag;
ref = this.tokens;
for (i = k = 0, len = ref.length; k < len; i = ++k) {
tag = ref[i][0];
[tag] = ref[i];
if (tag !== 'TERMINATOR') {
break;
}
@ -168,10 +168,10 @@
stack = [];
start = null;
return this.scanTokens(function(token, i, tokens) {
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, newLine, nextTag, offset, prevTag, prevToken, ref, ref1, ref2, ref3, ref4, ref5, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
tag = token[0];
prevTag = (prevToken = i > 0 ? tokens[i - 1] : [])[0];
nextTag = (i < tokens.length - 1 ? tokens[i + 1] : [])[0];
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, newLine, nextTag, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
[tag] = token;
[prevTag] = prevToken = i > 0 ? tokens[i - 1] : [];
[nextTag] = i < tokens.length - 1 ? tokens[i + 1] : [];
stackTop = function() {
return stack[stack.length - 1];
};
@ -302,7 +302,7 @@
this.insideForDeclaration = nextTag === 'FOR';
startsLine = s === 0 || (ref2 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref2) >= 0) || tokens[s - 1].newLine;
if (stackTop()) {
ref3 = stackTop(), stackTag = ref3[0], stackIdx = ref3[1];
[stackTag, stackIdx] = stackTop();
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
return forward(1);
}
@ -316,7 +316,7 @@
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
if (indexOf.call(IMPLICIT_END, tag) >= 0 || indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) {
while (inImplicit()) {
ref4 = stackTop(), stackTag = ref4[0], stackIdx = ref4[1], (ref5 = ref4[2], sameLine = ref5.sameLine, startsLine = ref5.startsLine);
[stackTag, stackIdx, {sameLine, startsLine}] = stackTop();
if (inImplicitCall() && prevTag !== ',') {
endImplicitCall();
} else if (inImplicitObject() && !this.insideForDeclaration && sameLine && tag !== 'TERMINATOR' && prevTag !== ':') {
@ -351,9 +351,15 @@
return 1;
}
if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
line = nextLocation.first_line, column = nextLocation.first_column;
({
first_line: line,
first_column: column
} = nextLocation);
} else if (prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0) {
line = prevLocation.last_line, column = prevLocation.last_column;
({
last_line: line,
last_column: column
} = prevLocation);
} else {
line = column = 0;
}
@ -395,8 +401,8 @@
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
};
return this.scanTokens(function(token, i, tokens) {
var j, k, ref, ref1, ref2, tag;
tag = token[0];
var j, k, ref, ref1, tag;
[tag] = token;
if (tag === 'TERMINATOR') {
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
tokens.splice(i, 1, ...this.indentation());
@ -418,7 +424,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(tokens[i]), indent = ref2[0], outdent = ref2[1];
[indent, outdent] = this.indentation(tokens[i]);
if (starter === 'THEN') {
indent.fromThen = true;
}
@ -438,8 +444,8 @@
original = null;
condition = function(token, i) {
var prevTag, tag;
tag = token[0];
prevTag = this.tokens[i - 1][0];
[tag] = token;
[prevTag] = this.tokens[i - 1];
return tag === 'TERMINATOR' || (tag === 'INDENT' && indexOf.call(SINGLE_LINERS, prevTag) < 0);
};
action = function(token, i) {
@ -492,7 +498,7 @@
EXPRESSION_END = [];
for (k = 0, len = BALANCED_PAIRS.length; k < len; k++) {
ref = BALANCED_PAIRS[k], left = ref[0], rite = ref[1];
[left, rite] = BALANCED_PAIRS[k];
EXPRESSION_START.push(INVERSES[rite] = left);
EXPRESSION_END.push(INVERSES[left] = rite);
}

View file

@ -30,10 +30,7 @@
if (Object.prototype.hasOwnProperty.call(this.positions, name)) {
return this.variables[this.positions[name]].type = type;
} else {
return this.positions[name] = this.variables.push({
name: name,
type: type
}) - 1;
return this.positions[name] = this.variables.push({name, type}) - 1;
}
}
@ -110,7 +107,7 @@
assign(name, value) {
this.add(name, {
value: value,
value,
assigned: true
}, true);
return this.hasAssignments = true;

View file

@ -8,20 +8,15 @@
this.columns = [];
}
add(column, arg, options) {
var sourceColumn, sourceLine;
sourceLine = arg[0], sourceColumn = arg[1];
if (options === void 0) {
options = {};
}
add(column, [sourceLine, sourceColumn], options = {}) {
if (this.columns[column] && options.noReplace) {
return;
}
return this.columns[column] = {
line: this.line,
column: column,
sourceLine: sourceLine,
sourceColumn: sourceColumn
column,
sourceLine,
sourceColumn
};
}
@ -45,14 +40,13 @@
add(sourceLocation, generatedLocation, options = {}) {
var base, column, line, lineMap;
line = generatedLocation[0], column = generatedLocation[1];
[line, column] = generatedLocation;
lineMap = ((base = this.lines)[line] || (base[line] = new LineMap(line)));
return lineMap.add(column, sourceLocation, options);
}
sourceLocation(arg) {
var column, line, lineMap;
line = arg[0], column = arg[1];
sourceLocation([line, column]) {
var lineMap;
while (!((lineMap = this.lines[line]) || (line <= 0))) {
line--;
}