Merge branch 'master' into newline-splat
Conflicts: lib/lexer.js lib/parser.js src/lexer.coffee
This commit is contained in:
commit
967fec2ae5
4
Rakefile
4
Rakefile
|
@ -2,7 +2,7 @@ require 'erb'
|
|||
require 'fileutils'
|
||||
require 'rake/testtask'
|
||||
require 'rubygems'
|
||||
require 'closure-compiler'
|
||||
require 'yui/compressor'
|
||||
|
||||
HEADER = <<-EOS
|
||||
/**
|
||||
|
@ -42,7 +42,7 @@ task :browser do
|
|||
}
|
||||
JS
|
||||
end
|
||||
code = Closure::Compiler.new.compress(<<-"JS")
|
||||
code = YUI::JavaScriptCompressor.new.compress(<<-"JS")
|
||||
this.CoffeeScript = function(){
|
||||
function require(path){ return require[path] }
|
||||
#{ code }
|
||||
|
|
|
@ -1309,7 +1309,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
|||
source = $('#repl_source').val()
|
||||
window.compiled_js = ''
|
||||
try
|
||||
window.compiled_js = CoffeeScript.compile source, noWrap: true
|
||||
window.compiled_js = CoffeeScript.compile source, wrap: false
|
||||
$('#repl_results').text window.compiled_js
|
||||
$('#error').hide()
|
||||
catch error
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2170,7 +2170,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
|||
source = $('#repl_source').val()
|
||||
window.compiled_js = ''
|
||||
try
|
||||
window.compiled_js = CoffeeScript.compile source, noWrap: true
|
||||
window.compiled_js = CoffeeScript.compile source, wrap: false
|
||||
$('#repl_results').text window.compiled_js
|
||||
$('#error').hide()
|
||||
catch error
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
o = {
|
||||
fileName: fileName
|
||||
};
|
||||
o.noWrap = opts['no-wrap'];
|
||||
o.wrap = !opts['no-wrap'];
|
||||
return o;
|
||||
};
|
||||
usage = function() {
|
||||
|
|
|
@ -64,12 +64,8 @@
|
|||
return new Literal($1);
|
||||
}), o("REGEX", function() {
|
||||
return new Literal($1);
|
||||
}), o("TRUE", function() {
|
||||
return new Literal(true);
|
||||
}), o("FALSE", function() {
|
||||
return new Literal(false);
|
||||
}), o("NULL", function() {
|
||||
return new Literal('null');
|
||||
}), o("BOOL", function() {
|
||||
return new Literal($1);
|
||||
})
|
||||
],
|
||||
Assign: [
|
||||
|
@ -130,7 +126,7 @@
|
|||
}), o("Param", function() {
|
||||
return [$1];
|
||||
}), o("ParamList , Param", function() {
|
||||
return $1.concat([$3]);
|
||||
return $1.concat($3);
|
||||
})
|
||||
],
|
||||
Param: [
|
||||
|
@ -209,9 +205,9 @@
|
|||
}), o("AssignObj", function() {
|
||||
return [$1];
|
||||
}), o("AssignList , AssignObj", function() {
|
||||
return $1.concat([$3]);
|
||||
return $1.concat($3);
|
||||
}), o("AssignList OptComma TERMINATOR AssignObj", function() {
|
||||
return $1.concat([$4]);
|
||||
return $1.concat($4);
|
||||
}), o("AssignList OptComma INDENT AssignList OptComma OUTDENT", function() {
|
||||
return $1.concat($4);
|
||||
})
|
||||
|
@ -329,9 +325,9 @@
|
|||
o("Arg", function() {
|
||||
return [$1];
|
||||
}), o("ArgList , Arg", function() {
|
||||
return $1.concat([$3]);
|
||||
return $1.concat($3);
|
||||
}), o("ArgList OptComma TERMINATOR Arg", function() {
|
||||
return $1.concat([$4]);
|
||||
return $1.concat($4);
|
||||
}), o("INDENT ArgList OptComma OUTDENT", function() {
|
||||
return $2;
|
||||
}), o("ArgList OptComma INDENT ArgList OptComma OUTDENT", function() {
|
||||
|
@ -341,7 +337,7 @@
|
|||
Arg: [o("Expression"), o("Splat")],
|
||||
SimpleArgs: [
|
||||
o("Expression"), o("SimpleArgs , Expression", function() {
|
||||
return $1 instanceof Array ? $1.concat([$3]) : [$1].concat([$3]);
|
||||
return [].concat($1, $3);
|
||||
})
|
||||
],
|
||||
Try: [
|
||||
|
|
68
lib/lexer.js
68
lib/lexer.js
|
@ -1,10 +1,11 @@
|
|||
(function() {
|
||||
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_SPACES, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NEXT_ELLIPSIS, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, _ref, compact, count, include, last, op, starts;
|
||||
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_SPACES, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NEXT_ELLIPSIS, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, _ref, compact, count, include, last, op, starts;
|
||||
Rewriter = require('./rewriter').Rewriter;
|
||||
_ref = require('./helpers'), include = _ref.include, count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
|
||||
exports.Lexer = (function() {
|
||||
Lexer = (function() {
|
||||
return function Lexer() {};
|
||||
function Lexer() {};
|
||||
return Lexer;
|
||||
})();
|
||||
Lexer.prototype.tokenize = function(code, options) {
|
||||
var o;
|
||||
|
@ -19,7 +20,7 @@
|
|||
this.seenFor = false;
|
||||
this.indents = [];
|
||||
this.tokens = [];
|
||||
while ((this.chunk = code.slice(this.i))) {
|
||||
while (this.chunk = code.slice(this.i)) {
|
||||
this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||
}
|
||||
this.closeIndentation();
|
||||
|
@ -29,17 +30,17 @@
|
|||
return (new Rewriter).rewrite(this.tokens);
|
||||
};
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var forcedIdentifier, id, match, tag;
|
||||
var _ref2, colon, forcedIdentifier, id, input, match, tag;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return false;
|
||||
}
|
||||
id = match[0];
|
||||
this.i += id.length;
|
||||
_ref2 = match, input = _ref2[0], id = _ref2[1], colon = _ref2[2];
|
||||
this.i += input.length;
|
||||
if (id === 'all' && this.tag() === 'FOR') {
|
||||
this.token('ALL', id);
|
||||
return true;
|
||||
}
|
||||
forcedIdentifier = this.tagAccessor() || ASSIGNED.test(this.chunk);
|
||||
forcedIdentifier = colon || this.tagAccessor();
|
||||
tag = 'IDENTIFIER';
|
||||
if (include(JS_KEYWORDS, id) || !forcedIdentifier && include(COFFEE_KEYWORDS, id)) {
|
||||
tag = id.toUpperCase();
|
||||
|
@ -79,9 +80,15 @@
|
|||
tag = 'UNARY';
|
||||
} else if (include(LOGIC, id)) {
|
||||
tag = 'LOGIC';
|
||||
} else if (include(BOOL, tag)) {
|
||||
id = tag.toLowerCase();
|
||||
tag = 'BOOL';
|
||||
}
|
||||
}
|
||||
this.token(tag, id);
|
||||
if (colon) {
|
||||
this.token(':', ':');
|
||||
}
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.numberToken = function() {
|
||||
|
@ -330,9 +337,9 @@
|
|||
if (!prev[1].reserved && include(JS_FORBIDDEN, prev[1])) {
|
||||
this.assignmentError();
|
||||
}
|
||||
if (('or' === (_ref2 = prev[1]) || 'and' === _ref2)) {
|
||||
if (('||' === (_ref2 = prev[1]) || '&&' === _ref2)) {
|
||||
prev[0] = 'COMPOUND_ASSIGN';
|
||||
prev[1] = COFFEE_ALIASES[prev[1]] + '=';
|
||||
prev[1] += '=';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -374,25 +381,23 @@
|
|||
return true;
|
||||
};
|
||||
Lexer.prototype.tagAccessor = function() {
|
||||
var accessor, prev;
|
||||
var prev;
|
||||
if (!(prev = last(this.tokens)) || prev.spaced) {
|
||||
return false;
|
||||
}
|
||||
accessor = (function() {
|
||||
if (prev[1] === '::') {
|
||||
return this.tag(0, 'PROTOTYPE_ACCESS');
|
||||
} else if (prev[1] === '.' && this.value(1) !== '.') {
|
||||
if (this.tag(1) === '?') {
|
||||
this.tag(0, 'SOAK_ACCESS');
|
||||
return this.tokens.splice(-2, 1);
|
||||
} else {
|
||||
return this.tag(0, 'PROPERTY_ACCESS');
|
||||
}
|
||||
if (prev[1] === '::') {
|
||||
this.tag(0, 'PROTOTYPE_ACCESS');
|
||||
} else if (prev[1] === '.' && this.value(1) !== '.') {
|
||||
if (this.tag(1) === '?') {
|
||||
this.tag(0, 'SOAK_ACCESS');
|
||||
this.tokens.splice(-2, 1);
|
||||
} else {
|
||||
return prev[0] === '@';
|
||||
this.tag(0, 'PROPERTY_ACCESS');
|
||||
}
|
||||
}).call(this);
|
||||
return accessor ? 'accessor' : false;
|
||||
} else {
|
||||
return prev[0] === '@';
|
||||
}
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
|
||||
var _ref2, _ref3, attempt, herecomment, indent, match;
|
||||
|
@ -422,10 +427,7 @@
|
|||
return;
|
||||
}
|
||||
i = this.tokens.length;
|
||||
while (true) {
|
||||
if (!(tok = this.tokens[--i])) {
|
||||
return;
|
||||
}
|
||||
while (tok = this.tokens[--i]) {
|
||||
switch (tok[0]) {
|
||||
case 'IDENTIFIER':
|
||||
tok[0] = 'PARAM';
|
||||
|
@ -435,7 +437,8 @@
|
|||
break;
|
||||
case '(':
|
||||
case 'CALL_START':
|
||||
return (tok[0] = 'PARAM_START');
|
||||
tok[0] = 'PARAM_START';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -444,10 +447,10 @@
|
|||
return this.outdentToken(this.indent);
|
||||
};
|
||||
Lexer.prototype.identifierError = function(word) {
|
||||
throw new Error("SyntaxError: Reserved word \"" + word + "\" on line " + (this.line + 1));
|
||||
throw 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 SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
|
||||
};
|
||||
Lexer.prototype.balancedString = function(str, delimited, options) {
|
||||
var _i, _len, _ref2, close, i, levels, open, pair, slen;
|
||||
|
@ -596,7 +599,7 @@
|
|||
COFFEE_ALIASES['==='] = '==';
|
||||
RESERVED = ['case', 'default', 'do', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice'];
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
|
||||
IDENTIFIER = /^[a-zA-Z_$][\w$]*/;
|
||||
IDENTIFIER = /^([$A-Za-z_][$\w]*)([^\n\S]*:(?!:))?/;
|
||||
NUMBER = /^0x[\da-f]+|^(?:\d+(\.\d+)?|\.\d+)(?:e[+-]?\d+)?/i;
|
||||
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[ \t]*)?\1/;
|
||||
OPERATOR = /^(?:-[-=>]?|\+[+=]?|\.\.\.?|[*&|\/%=<>^:!?]+)/;
|
||||
|
@ -624,7 +627,8 @@
|
|||
COMPARE = ['<=', '<', '>', '>='];
|
||||
MATH = ['*', '/', '%'];
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF'];
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']'];
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL'];
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
|
||||
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::'];
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
}).call(this);
|
||||
|
|
222
lib/nodes.js
222
lib/nodes.js
|
@ -1,5 +1,5 @@
|
|||
(function() {
|
||||
var Accessor, ArrayLiteral, Assign, Base, Call, Class, Closure, Code, Comment, Existence, Expressions, Extends, For, IDENTIFIER, IS_STRING, If, In, Index, Literal, NO, NUMBER, ObjectLiteral, Op, Param, Parens, Push, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, TRAILING_WHITESPACE, Throw, Try, UTILITIES, Value, While, YES, _ref, compact, del, ends, flatten, include, indexOf, last, merge, starts, utility;
|
||||
var Accessor, ArrayLiteral, Assign, Base, Call, Class, Closure, Code, Comment, Existence, Expressions, Extends, For, IDENTIFIER, IS_STRING, If, In, Index, Literal, NO, NUMBER, ObjectLiteral, Op, Param, Parens, Push, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, TRAILING_WHITESPACE, Throw, Try, UTILITIES, Value, While, YES, _ref, compact, del, ends, flatten, include, last, merge, starts, utility;
|
||||
var __extends = function(child, parent) {
|
||||
var ctor = function() {};
|
||||
ctor.prototype = parent.prototype;
|
||||
|
@ -9,7 +9,7 @@
|
|||
child.__super__ = parent.prototype;
|
||||
};
|
||||
Scope = require('./scope').Scope;
|
||||
_ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, merge = _ref.merge, del = _ref.del, include = _ref.include, indexOf = _ref.indexOf, starts = _ref.starts, ends = _ref.ends, last = _ref.last;
|
||||
_ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, merge = _ref.merge, del = _ref.del, include = _ref.include, starts = _ref.starts, ends = _ref.ends, last = _ref.last;
|
||||
YES = function() {
|
||||
return true;
|
||||
};
|
||||
|
@ -21,10 +21,11 @@
|
|||
};
|
||||
exports.Base = (function() {
|
||||
Base = (function() {
|
||||
return function Base() {
|
||||
function Base() {
|
||||
this.tags = {};
|
||||
return this;
|
||||
};
|
||||
return Base;
|
||||
})();
|
||||
Base.prototype.compile = function(o) {
|
||||
var closure, code, top;
|
||||
|
@ -141,9 +142,12 @@
|
|||
if (func(child) === false) {
|
||||
return false;
|
||||
}
|
||||
return child instanceof Base && (crossScope || !(child instanceof Code)) ? child.traverseChildren(crossScope, func) : undefined;
|
||||
return crossScope || !(child instanceof Code) ? child.traverseChildren(crossScope, func) : undefined;
|
||||
});
|
||||
};
|
||||
Base.prototype.invert = function() {
|
||||
return new Op('!', this);
|
||||
};
|
||||
Base.prototype.children = [];
|
||||
Base.prototype.unwrap = THIS;
|
||||
Base.prototype.isStatement = NO;
|
||||
|
@ -154,11 +158,12 @@
|
|||
})();
|
||||
exports.Expressions = (function() {
|
||||
Expressions = (function() {
|
||||
return function Expressions(nodes) {
|
||||
function Expressions(nodes) {
|
||||
Expressions.__super__.constructor.call(this);
|
||||
this.expressions = compact(flatten(nodes || []));
|
||||
return this;
|
||||
};
|
||||
return Expressions;
|
||||
})();
|
||||
__extends(Expressions, Base);
|
||||
Expressions.prototype.children = ['expressions'];
|
||||
|
@ -204,12 +209,13 @@
|
|||
}).call(this).join("\n");
|
||||
};
|
||||
Expressions.prototype.compileRoot = function(o) {
|
||||
var code;
|
||||
o.indent = (this.tab = o.noWrap ? '' : TAB);
|
||||
var code, wrap;
|
||||
wrap = (o.wrap != null) ? o.wrap : true;
|
||||
o.indent = (this.tab = wrap ? TAB : '');
|
||||
o.scope = new Scope(null, this, null);
|
||||
code = this.compileWithDeclarations(o);
|
||||
code = code.replace(TRAILING_WHITESPACE, '');
|
||||
return o.noWrap ? code : ("(function() {\n" + code + "\n}).call(this);\n");
|
||||
return wrap ? ("(function() {\n" + code + "\n}).call(this);\n") : code;
|
||||
};
|
||||
Expressions.prototype.compileWithDeclarations = function(o) {
|
||||
var code;
|
||||
|
@ -240,11 +246,12 @@
|
|||
};
|
||||
exports.Literal = (function() {
|
||||
Literal = (function() {
|
||||
return function Literal(_arg) {
|
||||
function Literal(_arg) {
|
||||
this.value = _arg;
|
||||
Literal.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Literal;
|
||||
})();
|
||||
__extends(Literal, Base);
|
||||
Literal.prototype.makeReturn = function() {
|
||||
|
@ -273,11 +280,12 @@
|
|||
})();
|
||||
exports.Return = (function() {
|
||||
Return = (function() {
|
||||
return function Return(_arg) {
|
||||
function Return(_arg) {
|
||||
this.expression = _arg;
|
||||
Return.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Return;
|
||||
})();
|
||||
__extends(Return, Base);
|
||||
Return.prototype.isStatement = YES;
|
||||
|
@ -307,7 +315,7 @@
|
|||
})();
|
||||
exports.Value = (function() {
|
||||
Value = (function() {
|
||||
return function Value(_arg, _arg2, tag) {
|
||||
function Value(_arg, _arg2, tag) {
|
||||
this.properties = _arg2;
|
||||
this.base = _arg;
|
||||
Value.__super__.constructor.call(this);
|
||||
|
@ -317,6 +325,7 @@
|
|||
}
|
||||
return this;
|
||||
};
|
||||
return Value;
|
||||
})();
|
||||
__extends(Value, Base);
|
||||
Value.prototype.children = ['base', 'properties'];
|
||||
|
@ -439,11 +448,12 @@
|
|||
}).call(this);
|
||||
exports.Comment = (function() {
|
||||
Comment = (function() {
|
||||
return function Comment(_arg) {
|
||||
function Comment(_arg) {
|
||||
this.comment = _arg;
|
||||
Comment.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Comment;
|
||||
})();
|
||||
__extends(Comment, Base);
|
||||
Comment.prototype.isStatement = YES;
|
||||
|
@ -455,7 +465,7 @@
|
|||
})();
|
||||
exports.Call = (function() {
|
||||
Call = (function() {
|
||||
return function Call(variable, _arg, _arg2) {
|
||||
function Call(variable, _arg, _arg2) {
|
||||
this.exist = _arg2;
|
||||
this.args = _arg;
|
||||
Call.__super__.constructor.call(this);
|
||||
|
@ -465,6 +475,7 @@
|
|||
this.args || (this.args = []);
|
||||
return this;
|
||||
};
|
||||
return Call;
|
||||
})();
|
||||
__extends(Call, Base);
|
||||
Call.prototype.children = ['variable', 'args'];
|
||||
|
@ -602,12 +613,13 @@
|
|||
})();
|
||||
exports.Extends = (function() {
|
||||
Extends = (function() {
|
||||
return function Extends(_arg, _arg2) {
|
||||
function Extends(_arg, _arg2) {
|
||||
this.parent = _arg2;
|
||||
this.child = _arg;
|
||||
Extends.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Extends;
|
||||
})();
|
||||
__extends(Extends, Base);
|
||||
Extends.prototype.children = ['child', 'parent'];
|
||||
|
@ -620,13 +632,14 @@
|
|||
})();
|
||||
exports.Accessor = (function() {
|
||||
Accessor = (function() {
|
||||
return function Accessor(_arg, tag) {
|
||||
function Accessor(_arg, tag) {
|
||||
this.name = _arg;
|
||||
Accessor.__super__.constructor.call(this);
|
||||
this.prototype = tag === 'prototype' ? '.prototype' : '';
|
||||
this.soakNode = tag === 'soak';
|
||||
return this;
|
||||
};
|
||||
return Accessor;
|
||||
})();
|
||||
__extends(Accessor, Base);
|
||||
Accessor.prototype.children = ['name'];
|
||||
|
@ -641,11 +654,12 @@
|
|||
})();
|
||||
exports.Index = (function() {
|
||||
Index = (function() {
|
||||
return function Index(_arg) {
|
||||
function Index(_arg) {
|
||||
this.index = _arg;
|
||||
Index.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Index;
|
||||
})();
|
||||
__extends(Index, Base);
|
||||
Index.prototype.children = ['index'];
|
||||
|
@ -662,7 +676,7 @@
|
|||
})();
|
||||
exports.Range = (function() {
|
||||
Range = (function() {
|
||||
return function Range(_arg, _arg2, tag) {
|
||||
function Range(_arg, _arg2, tag) {
|
||||
this.to = _arg2;
|
||||
this.from = _arg;
|
||||
Range.__super__.constructor.call(this);
|
||||
|
@ -670,6 +684,7 @@
|
|||
this.equals = this.exclusive ? '' : '=';
|
||||
return this;
|
||||
};
|
||||
return Range;
|
||||
})();
|
||||
__extends(Range, Base);
|
||||
Range.prototype.children = ['from', 'to'];
|
||||
|
@ -749,11 +764,12 @@
|
|||
})();
|
||||
exports.Slice = (function() {
|
||||
Slice = (function() {
|
||||
return function Slice(_arg) {
|
||||
function Slice(_arg) {
|
||||
this.range = _arg;
|
||||
Slice.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Slice;
|
||||
})();
|
||||
__extends(Slice, Base);
|
||||
Slice.prototype.children = ['range'];
|
||||
|
@ -771,11 +787,12 @@
|
|||
})();
|
||||
exports.ObjectLiteral = (function() {
|
||||
ObjectLiteral = (function() {
|
||||
return function ObjectLiteral(props) {
|
||||
function ObjectLiteral(props) {
|
||||
ObjectLiteral.__super__.constructor.call(this);
|
||||
this.objects = (this.properties = props || []);
|
||||
return this;
|
||||
};
|
||||
return ObjectLiteral;
|
||||
})();
|
||||
__extends(ObjectLiteral, Base);
|
||||
ObjectLiteral.prototype.children = ['properties'];
|
||||
|
@ -826,12 +843,13 @@
|
|||
})();
|
||||
exports.ArrayLiteral = (function() {
|
||||
ArrayLiteral = (function() {
|
||||
return function ArrayLiteral(_arg) {
|
||||
function ArrayLiteral(_arg) {
|
||||
this.objects = _arg;
|
||||
ArrayLiteral.__super__.constructor.call(this);
|
||||
this.objects || (this.objects = []);
|
||||
return this;
|
||||
};
|
||||
return ArrayLiteral;
|
||||
})();
|
||||
__extends(ArrayLiteral, Base);
|
||||
ArrayLiteral.prototype.children = ['objects'];
|
||||
|
@ -839,30 +857,28 @@
|
|||
return Splat.compileSplattedArray(this.objects, o);
|
||||
};
|
||||
ArrayLiteral.prototype.compileNode = function(o) {
|
||||
var _len, _ref2, code, i, obj, objects;
|
||||
var _i, _len, _len2, _ref2, _ref3, code, i, obj, objects;
|
||||
o.indent = this.idt(1);
|
||||
objects = [];
|
||||
for (i = 0, _len = (_ref2 = this.objects).length; i < _len; i++) {
|
||||
obj = _ref2[i];
|
||||
code = obj.compile(o);
|
||||
for (_i = 0, _len = (_ref2 = this.objects).length; _i < _len; _i++) {
|
||||
obj = _ref2[_i];
|
||||
if (obj instanceof Splat) {
|
||||
return this.compileSplatLiteral(o);
|
||||
} else if (obj instanceof Comment) {
|
||||
objects.push("\n" + code + "\n" + (o.indent));
|
||||
} else if (i === this.objects.length - 1) {
|
||||
objects.push(code);
|
||||
} else {
|
||||
objects.push("" + code + ", ");
|
||||
}
|
||||
}
|
||||
objects = [];
|
||||
for (i = 0, _len2 = (_ref3 = this.objects).length; i < _len2; i++) {
|
||||
obj = _ref3[i];
|
||||
code = obj.compile(o);
|
||||
objects.push(obj instanceof Comment ? ("\n" + code + "\n" + (o.indent)) : (i === this.objects.length - 1 ? code : code + ', '));
|
||||
}
|
||||
objects = objects.join('');
|
||||
return indexOf(objects, '\n') >= 0 ? ("[\n" + (this.idt(1)) + objects + "\n" + (this.tab) + "]") : ("[" + objects + "]");
|
||||
return 0 < objects.indexOf('\n') ? ("[\n" + (o.indent) + objects + "\n" + (this.tab) + "]") : ("[" + objects + "]");
|
||||
};
|
||||
return ArrayLiteral;
|
||||
})();
|
||||
exports.Class = (function() {
|
||||
Class = (function() {
|
||||
return function Class(variable, _arg, _arg2) {
|
||||
function Class(variable, _arg, _arg2) {
|
||||
this.properties = _arg2;
|
||||
this.parent = _arg;
|
||||
Class.__super__.constructor.call(this);
|
||||
|
@ -871,6 +887,7 @@
|
|||
this.returns = false;
|
||||
return this;
|
||||
};
|
||||
return Class;
|
||||
})();
|
||||
__extends(Class, Base);
|
||||
Class.prototype.children = ['variable', 'parent', 'properties'];
|
||||
|
@ -915,7 +932,7 @@
|
|||
func.name = className;
|
||||
func.body.push(new Return(new Literal('this')));
|
||||
variable = new Value(variable);
|
||||
variable.namespaced = include(func.name, '.');
|
||||
variable.namespaced = 0 < className.indexOf('.');
|
||||
constructor = func;
|
||||
continue;
|
||||
}
|
||||
|
@ -956,13 +973,14 @@
|
|||
})();
|
||||
exports.Assign = (function() {
|
||||
Assign = (function() {
|
||||
return function Assign(_arg, _arg2, _arg3) {
|
||||
function Assign(_arg, _arg2, _arg3) {
|
||||
this.context = _arg3;
|
||||
this.value = _arg2;
|
||||
this.variable = _arg;
|
||||
Assign.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Assign;
|
||||
})();
|
||||
__extends(Assign, Base);
|
||||
Assign.prototype.METHOD_DEF = /^(?:(\S+)\.prototype\.)?([$A-Za-z_][$\w]*)$/;
|
||||
|
@ -972,7 +990,7 @@
|
|||
return this.variable instanceof Value;
|
||||
};
|
||||
Assign.prototype.compileNode = function(o) {
|
||||
var isValue, match, name, node, stmt, top, val;
|
||||
var ifn, isValue, match, name, stmt, top, val;
|
||||
if (isValue = this.isValue()) {
|
||||
if (this.variable.isArray() || this.variable.isObject()) {
|
||||
return this.compilePatternMatch(o);
|
||||
|
@ -980,8 +998,9 @@
|
|||
if (this.variable.isSplice()) {
|
||||
return this.compileSplice(o);
|
||||
}
|
||||
if (node = Value.unfoldSoak(o, this, 'variable')) {
|
||||
return node.compile(o);
|
||||
if (ifn = Value.unfoldSoak(o, this, 'variable')) {
|
||||
delete o.top;
|
||||
return ifn.compile(o);
|
||||
}
|
||||
}
|
||||
top = del(o, 'top');
|
||||
|
@ -1080,7 +1099,7 @@
|
|||
})();
|
||||
exports.Code = (function() {
|
||||
Code = (function() {
|
||||
return function Code(_arg, _arg2, tag) {
|
||||
function Code(_arg, _arg2, tag) {
|
||||
this.body = _arg2;
|
||||
this.params = _arg;
|
||||
Code.__super__.constructor.call(this);
|
||||
|
@ -1092,6 +1111,7 @@
|
|||
}
|
||||
return this;
|
||||
};
|
||||
return Code;
|
||||
})();
|
||||
__extends(Code, Base);
|
||||
Code.prototype.children = ['params', 'body'];
|
||||
|
@ -1103,7 +1123,7 @@
|
|||
o.top = true;
|
||||
o.indent = this.idt(1);
|
||||
empty = this.body.expressions.length === 0;
|
||||
del(o, 'noWrap');
|
||||
del(o, 'wrap');
|
||||
del(o, 'globals');
|
||||
splat = undefined;
|
||||
params = [];
|
||||
|
@ -1152,8 +1172,8 @@
|
|||
o.indent = this.idt(2);
|
||||
}
|
||||
code = this.body.expressions.length ? ("\n" + (this.body.compileWithDeclarations(o)) + "\n") : '';
|
||||
open = this.className ? ("(function() {\n" + (this.idt(1)) + "return function " + (this.className) + "(") : "function(";
|
||||
close = this.className ? ("" + (code && this.idt(1)) + "};\n" + (this.tab) + "})()") : ("" + (code && this.tab) + "}");
|
||||
open = this.className ? ("(function() {\n" + (this.idt(1)) + "function " + (this.className) + "(") : "function(";
|
||||
close = this.className ? ("" + (code && this.idt(1)) + "};\n" + (this.idt(1)) + "return " + (this.className) + ";\n" + (this.tab) + "})()") : ("" + (code && this.tab) + "}");
|
||||
func = ("" + open + (params.join(', ')) + ") {" + code + close);
|
||||
o.scope.endLevel();
|
||||
if (this.bound) {
|
||||
|
@ -1169,7 +1189,7 @@
|
|||
})();
|
||||
exports.Param = (function() {
|
||||
Param = (function() {
|
||||
return function Param(_arg, _arg2, _arg3) {
|
||||
function Param(_arg, _arg2, _arg3) {
|
||||
this.splat = _arg3;
|
||||
this.attach = _arg2;
|
||||
this.name = _arg;
|
||||
|
@ -1177,6 +1197,7 @@
|
|||
this.value = new Literal(this.name);
|
||||
return this;
|
||||
};
|
||||
return Param;
|
||||
})();
|
||||
__extends(Param, Base);
|
||||
Param.prototype.children = ['name'];
|
||||
|
@ -1198,7 +1219,7 @@
|
|||
})();
|
||||
exports.Splat = (function() {
|
||||
Splat = (function() {
|
||||
return function Splat(name) {
|
||||
function Splat(name) {
|
||||
Splat.__super__.constructor.call(this);
|
||||
if (!name.compile) {
|
||||
name = new Literal(name);
|
||||
|
@ -1206,6 +1227,7 @@
|
|||
this.name = name;
|
||||
return this;
|
||||
};
|
||||
return Splat;
|
||||
})();
|
||||
__extends(Splat, Base);
|
||||
Splat.prototype.children = ['name'];
|
||||
|
@ -1268,18 +1290,13 @@
|
|||
}).call(this);
|
||||
exports.While = (function() {
|
||||
While = (function() {
|
||||
return function While(condition, opts) {
|
||||
function While(condition, opts) {
|
||||
While.__super__.constructor.call(this);
|
||||
if (((opts != null) ? opts.invert : undefined)) {
|
||||
if (condition instanceof Op) {
|
||||
condition = new Parens(condition);
|
||||
}
|
||||
condition = new Op('!', condition);
|
||||
}
|
||||
this.condition = condition;
|
||||
this.condition = ((opts != null) ? opts.invert : undefined) ? condition.invert() : condition;
|
||||
this.guard = ((opts != null) ? opts.guard : undefined);
|
||||
return this;
|
||||
};
|
||||
return While;
|
||||
})();
|
||||
__extends(While, Base);
|
||||
While.prototype.children = ['condition', 'guard', 'body'];
|
||||
|
@ -1297,9 +1314,9 @@
|
|||
var cond, post, pre, rvar, set, top;
|
||||
top = del(o, 'top') && !this.returns;
|
||||
o.indent = this.idt(1);
|
||||
o.top = true;
|
||||
this.condition.parenthetical = true;
|
||||
cond = this.condition.compile(o);
|
||||
o.top = true;
|
||||
set = '';
|
||||
if (!top) {
|
||||
rvar = o.scope.freeVariable('result');
|
||||
|
@ -1325,7 +1342,7 @@
|
|||
})();
|
||||
exports.Op = (function() {
|
||||
Op = (function() {
|
||||
return function Op(_arg, _arg2, _arg3, flip) {
|
||||
function Op(_arg, _arg2, _arg3, flip) {
|
||||
this.second = _arg3;
|
||||
this.first = _arg2;
|
||||
this.operator = _arg;
|
||||
|
@ -1343,6 +1360,7 @@
|
|||
}
|
||||
return this;
|
||||
};
|
||||
return Op;
|
||||
})();
|
||||
__extends(Op, Base);
|
||||
Op.prototype.CONVERSIONS = {
|
||||
|
@ -1361,10 +1379,6 @@
|
|||
Op.prototype.isUnary = function() {
|
||||
return !this.second;
|
||||
};
|
||||
Op.prototype.isInvertible = function() {
|
||||
var _ref2;
|
||||
return ('===' === (_ref2 = this.operator) || '!==' === _ref2);
|
||||
};
|
||||
Op.prototype.isComplex = function() {
|
||||
return this.operator !== '!' || this.first.isComplex();
|
||||
};
|
||||
|
@ -1376,7 +1390,11 @@
|
|||
return include(this.CHAINABLE, this.operator);
|
||||
};
|
||||
Op.prototype.invert = function() {
|
||||
return (this.operator = this.INVERSIONS[this.operator]);
|
||||
var _ref2;
|
||||
if (('===' === (_ref2 = this.operator) || '!==' === _ref2)) {
|
||||
this.operator = this.INVERSIONS[this.operator];
|
||||
return this;
|
||||
} else return this.second ? new Parens(this).invert() : Op.__super__.invert.call(this);
|
||||
};
|
||||
Op.prototype.toString = function(idt) {
|
||||
return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator);
|
||||
|
@ -1385,7 +1403,7 @@
|
|||
if (this.isChainable() && this.first.unwrap() instanceof Op && this.first.unwrap().isChainable()) {
|
||||
return this.compileChain(o);
|
||||
}
|
||||
if (indexOf(this.ASSIGNMENT, this.operator) >= 0) {
|
||||
if (include(this.ASSIGNMENT, this.operator)) {
|
||||
return this.compileAssignment(o);
|
||||
}
|
||||
if (this.isUnary()) {
|
||||
|
@ -1428,23 +1446,21 @@
|
|||
};
|
||||
Op.prototype.compileUnary = function(o) {
|
||||
var parts, space;
|
||||
space = indexOf(this.PREFIX_OPERATORS, this.operator) >= 0 ? ' ' : '';
|
||||
space = include(this.PREFIX_OPERATORS, this.operator) ? ' ' : '';
|
||||
parts = [this.operator, space, this.first.compile(o)];
|
||||
if (this.flip) {
|
||||
parts = parts.reverse();
|
||||
}
|
||||
return parts.join('');
|
||||
return (this.flip ? parts.reverse() : parts).join('');
|
||||
};
|
||||
return Op;
|
||||
})();
|
||||
exports.In = (function() {
|
||||
In = (function() {
|
||||
return function In(_arg, _arg2) {
|
||||
function In(_arg, _arg2) {
|
||||
this.array = _arg2;
|
||||
this.object = _arg;
|
||||
In.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return In;
|
||||
})();
|
||||
__extends(In, Base);
|
||||
In.prototype.children = ['object', 'array'];
|
||||
|
@ -1483,7 +1499,7 @@
|
|||
})();
|
||||
exports.Try = (function() {
|
||||
Try = (function() {
|
||||
return function Try(_arg, _arg2, _arg3, _arg4) {
|
||||
function Try(_arg, _arg2, _arg3, _arg4) {
|
||||
this.ensure = _arg4;
|
||||
this.recovery = _arg3;
|
||||
this.error = _arg2;
|
||||
|
@ -1491,6 +1507,7 @@
|
|||
Try.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Try;
|
||||
})();
|
||||
__extends(Try, Base);
|
||||
Try.prototype.children = ['attempt', 'recovery', 'ensure'];
|
||||
|
@ -1518,11 +1535,12 @@
|
|||
})();
|
||||
exports.Throw = (function() {
|
||||
Throw = (function() {
|
||||
return function Throw(_arg) {
|
||||
function Throw(_arg) {
|
||||
this.expression = _arg;
|
||||
Throw.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Throw;
|
||||
})();
|
||||
__extends(Throw, Base);
|
||||
Throw.prototype.children = ['expression'];
|
||||
|
@ -1535,11 +1553,12 @@
|
|||
})();
|
||||
exports.Existence = (function() {
|
||||
Existence = (function() {
|
||||
return function Existence(_arg) {
|
||||
function Existence(_arg) {
|
||||
this.expression = _arg;
|
||||
Existence.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Existence;
|
||||
})();
|
||||
__extends(Existence, Base);
|
||||
Existence.prototype.children = ['expression'];
|
||||
|
@ -1553,11 +1572,12 @@
|
|||
})();
|
||||
exports.Parens = (function() {
|
||||
Parens = (function() {
|
||||
return function Parens(_arg) {
|
||||
function Parens(_arg) {
|
||||
this.expression = _arg;
|
||||
Parens.__super__.constructor.call(this);
|
||||
return this;
|
||||
};
|
||||
return Parens;
|
||||
})();
|
||||
__extends(Parens, Base);
|
||||
Parens.prototype.children = ['expression'];
|
||||
|
@ -1588,7 +1608,7 @@
|
|||
})();
|
||||
exports.For = (function() {
|
||||
For = (function() {
|
||||
return function For(_arg, source, _arg2, _arg3) {
|
||||
function For(_arg, source, _arg2, _arg3) {
|
||||
var _ref2, _ref3;
|
||||
this.index = _arg3;
|
||||
this.name = _arg2;
|
||||
|
@ -1607,6 +1627,7 @@
|
|||
this.returns = false;
|
||||
return this;
|
||||
};
|
||||
return For;
|
||||
})();
|
||||
__extends(For, Base);
|
||||
For.prototype.children = ['body', 'source', 'guard'];
|
||||
|
@ -1723,7 +1744,7 @@
|
|||
})();
|
||||
exports.Switch = (function() {
|
||||
Switch = (function() {
|
||||
return function Switch(_arg, _arg2, _arg3) {
|
||||
function Switch(_arg, _arg2, _arg3) {
|
||||
this.otherwise = _arg3;
|
||||
this.cases = _arg2;
|
||||
this.subject = _arg;
|
||||
|
@ -1732,6 +1753,7 @@
|
|||
this.subject || (this.subject = new Literal('true'));
|
||||
return this;
|
||||
};
|
||||
return Switch;
|
||||
})();
|
||||
__extends(Switch, Base);
|
||||
Switch.prototype.children = ['subject', 'cases', 'otherwise'];
|
||||
|
@ -1778,27 +1800,16 @@
|
|||
})();
|
||||
exports.If = (function() {
|
||||
If = (function() {
|
||||
return function If(condition, _arg, _arg2) {
|
||||
var op;
|
||||
function If(condition, _arg, _arg2) {
|
||||
this.tags = _arg2;
|
||||
this.body = _arg;
|
||||
this.tags || (this.tags = {});
|
||||
if (this.tags.invert) {
|
||||
op = condition instanceof Op;
|
||||
if (op && condition.isInvertible()) {
|
||||
condition.invert();
|
||||
} else {
|
||||
if (op && !condition.isUnary()) {
|
||||
condition = new Parens(condition);
|
||||
}
|
||||
condition = new Op('!', condition);
|
||||
}
|
||||
}
|
||||
this.condition = condition;
|
||||
this.condition = this.tags.invert ? condition.invert() : condition;
|
||||
this.elseBody = null;
|
||||
this.isChain = false;
|
||||
return this;
|
||||
};
|
||||
return If;
|
||||
})();
|
||||
__extends(If, Base);
|
||||
If.prototype.children = ['condition', 'body', 'elseBody', 'assigner'];
|
||||
|
@ -1811,9 +1822,9 @@
|
|||
var _ref2;
|
||||
return (((_ref2 = this.elseBody) != null) ? _ref2.unwrap() : undefined);
|
||||
};
|
||||
If.prototype.addElse = function(elseBody, statement) {
|
||||
If.prototype.addElse = function(elseBody) {
|
||||
if (this.isChain) {
|
||||
this.elseBodyNode().addElse(elseBody, statement);
|
||||
this.elseBodyNode().addElse(elseBody);
|
||||
} else {
|
||||
this.isChain = elseBody instanceof If;
|
||||
this.elseBody = this.ensureExpressions(elseBody);
|
||||
|
@ -1821,22 +1832,12 @@
|
|||
return this;
|
||||
};
|
||||
If.prototype.isStatement = function(o) {
|
||||
return this.statement || (this.statement = !!((o && o.top) || this.bodyNode().isStatement(o) || (this.elseBody && this.elseBodyNode().isStatement(o))));
|
||||
var _ref2;
|
||||
return this.statement || (this.statement = ((o != null) ? o.top : undefined) || this.bodyNode().isStatement(o) || (((_ref2 = this.elseBodyNode()) != null) ? _ref2.isStatement(o) : undefined));
|
||||
};
|
||||
If.prototype.compileCondition = function(o) {
|
||||
var _i, _len, _result, cond, conditions;
|
||||
conditions = flatten([this.condition]);
|
||||
if (conditions.length === 1) {
|
||||
conditions[0].parenthetical = true;
|
||||
}
|
||||
return (function() {
|
||||
_result = [];
|
||||
for (_i = 0, _len = conditions.length; _i < _len; _i++) {
|
||||
cond = conditions[_i];
|
||||
_result.push(cond.compile(o));
|
||||
}
|
||||
return _result;
|
||||
})().join(' || ');
|
||||
this.condition.parenthetical = true;
|
||||
return this.condition.compile(o);
|
||||
};
|
||||
If.prototype.compileNode = function(o) {
|
||||
return this.isStatement(o) ? this.compileStatement(o) : this.compileExpression(o);
|
||||
|
@ -1854,24 +1855,23 @@
|
|||
return node instanceof Expressions ? node : new Expressions([node]);
|
||||
};
|
||||
If.prototype.compileStatement = function(o) {
|
||||
var body, child, comDent, condO, elsePart, ifDent, ifPart, top;
|
||||
var child, condO, ifPart, top;
|
||||
top = del(o, 'top');
|
||||
child = del(o, 'chainChild');
|
||||
condO = merge(o);
|
||||
o.indent = this.idt(1);
|
||||
o.top = true;
|
||||
ifDent = child || (top && !this.isStatement(o)) ? '' : this.idt();
|
||||
comDent = child ? this.idt() : '';
|
||||
body = this.body.compile(o);
|
||||
ifPart = ("" + ifDent + "if (" + (this.compileCondition(condO)) + ") {\n" + body + "\n" + (this.tab) + "}");
|
||||
ifPart = ("if (" + (this.compileCondition(condO)) + ") {\n" + (this.body.compile(o)) + "\n" + (this.tab) + "}");
|
||||
if (!child) {
|
||||
ifPart = this.tab + ifPart;
|
||||
}
|
||||
if (!this.elseBody) {
|
||||
return ifPart;
|
||||
}
|
||||
elsePart = this.isChain ? ' else ' + this.elseBodyNode().compile(merge(o, {
|
||||
indent: this.idt(),
|
||||
return ifPart + (this.isChain ? ' else ' + this.elseBodyNode().compile(merge(o, {
|
||||
indent: this.tab,
|
||||
chainChild: true
|
||||
})) : (" else {\n" + (this.elseBody.compile(o)) + "\n" + (this.tab) + "}");
|
||||
return "" + ifPart + elsePart;
|
||||
})) : (" else {\n" + (this.elseBody.compile(o)) + "\n" + (this.tab) + "}"));
|
||||
};
|
||||
If.prototype.compileExpression = function(o) {
|
||||
var code, elsePart, ifPart;
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
|
||||
exports.OptionParser = (function() {
|
||||
OptionParser = (function() {
|
||||
return function OptionParser(rules, banner) {
|
||||
function OptionParser(rules, banner) {
|
||||
this.banner = banner;
|
||||
this.rules = buildRules(rules);
|
||||
return this;
|
||||
};
|
||||
return OptionParser;
|
||||
})();
|
||||
OptionParser.prototype.parse = function(args) {
|
||||
var _i, _len, _len2, _ref, arg, i, isOption, matchedRule, options, rule, value;
|
||||
|
|
364
lib/parser.js
364
lib/parser.js
File diff suppressed because one or more lines are too long
|
@ -13,7 +13,7 @@
|
|||
var val;
|
||||
try {
|
||||
val = CoffeeScript.eval(buffer.toString(), {
|
||||
noWrap: true,
|
||||
wrap: false,
|
||||
globals: true,
|
||||
fileName: 'repl'
|
||||
});
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, _i, _len, _ref, include, left, rite;
|
||||
include = require('./helpers').include;
|
||||
exports.Rewriter = (function() {
|
||||
return function Rewriter() {};
|
||||
function Rewriter() {};
|
||||
return Rewriter;
|
||||
})();
|
||||
exports.Rewriter.prototype.rewrite = function(_arg) {
|
||||
this.tokens = _arg;
|
||||
|
@ -365,7 +366,7 @@
|
|||
}
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY', 'TRUE', 'FALSE', '@', '->', '=>', '[', '(', '{'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', '@', '->', '=>', '[', '(', '{'];
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT'];
|
||||
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
_ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
|
||||
exports.Scope = (function() {
|
||||
Scope = (function() {
|
||||
return function Scope(_arg, _arg2, _arg3) {
|
||||
function Scope(_arg, _arg2, _arg3) {
|
||||
this.method = _arg3;
|
||||
this.expressions = _arg2;
|
||||
this.parent = _arg;
|
||||
|
@ -19,6 +19,7 @@
|
|||
}
|
||||
return this;
|
||||
};
|
||||
return Scope;
|
||||
})();
|
||||
Scope.root = null;
|
||||
Scope.prototype.startLevel = function() {
|
||||
|
|
|
@ -185,7 +185,7 @@ parseOptions = ->
|
|||
# The compile-time options to pass to the CoffeeScript compiler.
|
||||
compileOptions = (fileName) ->
|
||||
o = {fileName}
|
||||
o.noWrap = opts['no-wrap']
|
||||
o.wrap = !opts['no-wrap']
|
||||
o
|
||||
|
||||
# Print the `--help` usage message and exit.
|
||||
|
|
|
@ -130,9 +130,7 @@ grammar =
|
|||
o "AlphaNumeric"
|
||||
o "JS", -> new Literal $1
|
||||
o "REGEX", -> new Literal $1
|
||||
o "TRUE", -> new Literal true
|
||||
o "FALSE", -> new Literal false
|
||||
o "NULL", -> new Literal 'null'
|
||||
o "BOOL", -> new Literal $1
|
||||
]
|
||||
|
||||
# Assignment of a variable, property, or index to a value.
|
||||
|
@ -195,7 +193,7 @@ grammar =
|
|||
ParamList: [
|
||||
o "", -> []
|
||||
o "Param", -> [$1]
|
||||
o "ParamList , Param", -> $1.concat [$3]
|
||||
o "ParamList , Param", -> $1.concat $3
|
||||
]
|
||||
|
||||
# A single parameter in a function definition can be ordinary, or a splat
|
||||
|
@ -265,8 +263,8 @@ grammar =
|
|||
AssignList: [
|
||||
o "", -> []
|
||||
o "AssignObj", -> [$1]
|
||||
o "AssignList , AssignObj", -> $1.concat [$3]
|
||||
o "AssignList OptComma TERMINATOR AssignObj", -> $1.concat [$4]
|
||||
o "AssignList , AssignObj", -> $1.concat $3
|
||||
o "AssignList OptComma TERMINATOR AssignObj", -> $1.concat $4
|
||||
o "AssignList OptComma INDENT AssignList OptComma OUTDENT", -> $1.concat $4
|
||||
]
|
||||
|
||||
|
@ -363,8 +361,8 @@ grammar =
|
|||
# (i.e. comma-separated expressions). Newlines work as well.
|
||||
ArgList: [
|
||||
o "Arg", -> [$1]
|
||||
o "ArgList , Arg", -> $1.concat [$3]
|
||||
o "ArgList OptComma TERMINATOR Arg", -> $1.concat [$4]
|
||||
o "ArgList , Arg", -> $1.concat $3
|
||||
o "ArgList OptComma TERMINATOR Arg", -> $1.concat $4
|
||||
o "INDENT ArgList OptComma OUTDENT", -> $2
|
||||
o "ArgList OptComma INDENT ArgList OptComma OUTDENT", -> $1.concat $4
|
||||
]
|
||||
|
@ -380,8 +378,7 @@ grammar =
|
|||
# having the newlines wouldn't make sense.
|
||||
SimpleArgs: [
|
||||
o "Expression"
|
||||
o "SimpleArgs , Expression", ->
|
||||
if $1 instanceof Array then $1.concat([$3]) else [$1].concat([$3])
|
||||
o "SimpleArgs , Expression", -> [].concat $1, $3
|
||||
]
|
||||
|
||||
# The variants of *try/catch/finally* exception handling blocks.
|
||||
|
@ -527,8 +524,8 @@ grammar =
|
|||
# rules are necessary.
|
||||
Operation: [
|
||||
o "UNARY Expression", -> new Op $1, $2
|
||||
o("- Expression", (-> new Op('-', $2)), {prec: 'UNARY'})
|
||||
o("+ Expression", (-> new Op('+', $2)), {prec: 'UNARY'})
|
||||
o "- Expression", (-> new Op '-', $2), prec: 'UNARY'
|
||||
o "+ Expression", (-> new Op '+', $2), prec: 'UNARY'
|
||||
|
||||
o "-- Expression", -> new Op '--', $2
|
||||
o "++ Expression", -> new Op '++', $2
|
||||
|
|
|
@ -73,12 +73,12 @@ exports.Lexer = class Lexer
|
|||
# though `is` means `===` otherwise.
|
||||
identifierToken: ->
|
||||
return false unless match = IDENTIFIER.exec @chunk
|
||||
id = match[0]
|
||||
@i += id.length
|
||||
[input, id, colon] = match
|
||||
@i += input.length
|
||||
if id is 'all' and @tag() is 'FOR'
|
||||
@token 'ALL', id
|
||||
return true
|
||||
forcedIdentifier = @tagAccessor() or ASSIGNED.test @chunk
|
||||
forcedIdentifier = colon or @tagAccessor()
|
||||
tag = 'IDENTIFIER'
|
||||
if include(JS_KEYWORDS, id) or
|
||||
not forcedIdentifier and include(COFFEE_KEYWORDS, id)
|
||||
|
@ -103,7 +103,7 @@ exports.Lexer = class Lexer
|
|||
tag = 'IDENTIFIER'
|
||||
id = new String id
|
||||
id.reserved = yes
|
||||
else if include(RESERVED, id)
|
||||
else if include RESERVED, id
|
||||
@identifierError id
|
||||
unless forcedIdentifier
|
||||
tag = id = COFFEE_ALIASES[id] if COFFEE_ALIASES.hasOwnProperty id
|
||||
|
@ -111,7 +111,11 @@ exports.Lexer = class Lexer
|
|||
tag = 'UNARY'
|
||||
else if include LOGIC, id
|
||||
tag = 'LOGIC'
|
||||
else if include BOOL, tag
|
||||
id = tag.toLowerCase()
|
||||
tag = 'BOOL'
|
||||
@token tag, id
|
||||
@token ':', ':' if colon
|
||||
true
|
||||
|
||||
# Matches numbers, including decimals, hex, and exponential notation.
|
||||
|
@ -311,9 +315,9 @@ exports.Lexer = class Lexer
|
|||
prev = last @tokens
|
||||
if value is '='
|
||||
@assignmentError() if not prev[1].reserved and include JS_FORBIDDEN, prev[1]
|
||||
if prev[1] in ['or', 'and']
|
||||
if prev[1] in ['||', '&&']
|
||||
prev[0] = 'COMPOUND_ASSIGN'
|
||||
prev[1] = COFFEE_ALIASES[prev[1]] + '='
|
||||
prev[1] += '='
|
||||
return true
|
||||
if ';' is value then tag = 'TERMINATOR'
|
||||
else if include LOGIC , value then tag = 'LOGIC'
|
||||
|
@ -343,17 +347,17 @@ exports.Lexer = class Lexer
|
|||
# is the previous token.
|
||||
tagAccessor: ->
|
||||
return false if not (prev = last @tokens) or prev.spaced
|
||||
accessor = if prev[1] is '::'
|
||||
if prev[1] is '::'
|
||||
@tag 0, 'PROTOTYPE_ACCESS'
|
||||
else if prev[1] is '.' and @value(1) isnt '.'
|
||||
if @tag(1) is '?'
|
||||
@tag(0, 'SOAK_ACCESS')
|
||||
@tag 0, 'SOAK_ACCESS'
|
||||
@tokens.splice(-2, 1)
|
||||
else
|
||||
@tag 0, 'PROPERTY_ACCESS'
|
||||
else
|
||||
prev[0] is '@'
|
||||
if accessor then 'accessor' else false
|
||||
return prev[0] is '@'
|
||||
true
|
||||
|
||||
# Sanitize a heredoc or herecomment by
|
||||
# erasing all external indentation on the left-hand side.
|
||||
|
@ -374,12 +378,11 @@ exports.Lexer = class Lexer
|
|||
tagParameters: ->
|
||||
return if @tag() isnt ')'
|
||||
i = @tokens.length
|
||||
loop
|
||||
return unless tok = @tokens[--i]
|
||||
while tok = @tokens[--i]
|
||||
switch tok[0]
|
||||
when 'IDENTIFIER' then tok[0] = 'PARAM'
|
||||
when ')' then tok[0] = 'PARAM_END'
|
||||
when '(', 'CALL_START' then return tok[0] = 'PARAM_START'
|
||||
when '(', 'CALL_START' then tok[0] = 'PARAM_START'; return true
|
||||
true
|
||||
|
||||
# Close up all remaining open blocks at the end of the file.
|
||||
|
@ -389,12 +392,12 @@ exports.Lexer = class Lexer
|
|||
# The error for when you try to use a forbidden word in JavaScript as
|
||||
# an identifier.
|
||||
identifierError: (word) ->
|
||||
throw new Error "SyntaxError: Reserved word \"#{word}\" on line #{@line + 1}"
|
||||
throw SyntaxError "Reserved word \"#{word}\" on line #{@line + 1}"
|
||||
|
||||
# The error for when you try to assign to a reserved word in JavaScript,
|
||||
# like "function" or "default".
|
||||
assignmentError: ->
|
||||
throw new Error "SyntaxError: Reserved word \"#{@value()}\" on line #{@line + 1} can't be assigned"
|
||||
throw SyntaxError "Reserved word \"#{@value()}\" on line #{@line + 1} can't be assigned"
|
||||
|
||||
# Matches a balanced group such as a single or double-quoted string. Pass in
|
||||
# a series of delimiters, all of which must be nested correctly within the
|
||||
|
@ -545,7 +548,10 @@ RESERVED = [
|
|||
JS_FORBIDDEN = JS_KEYWORDS.concat RESERVED
|
||||
|
||||
# Token matching regexes.
|
||||
IDENTIFIER = /^[a-zA-Z_$][\w$]*/
|
||||
IDENTIFIER = /// ^
|
||||
( [$A-Za-z_][$\w]* )
|
||||
( [^\n\S]* : (?!:) )? # Is this a property name?
|
||||
///
|
||||
NUMBER = /^0x[\da-f]+|^(?:\d+(\.\d+)?|\.\d+)(?:e[+-]?\d+)?/i
|
||||
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[ \t]*)?\1/
|
||||
OPERATOR = /// ^ (?: -[-=>]? | \+[+=]? | \.\.\.? | [*&|/%=<>^:!?]+ ) ///
|
||||
|
@ -606,13 +612,16 @@ MATH = ['*', '/', '%']
|
|||
# Relational tokens that are negatable with `not` prefix.
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF']
|
||||
|
||||
# Boolean tokens.
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL']
|
||||
|
||||
# Tokens which a regular expression will never immediately follow, but which
|
||||
# a division operator might.
|
||||
#
|
||||
# See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
|
||||
#
|
||||
# Our list is shorter, due to sans-parentheses method calls.
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']']
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']']
|
||||
|
||||
# Tokens which could legitimately be invoked or indexed. A opening
|
||||
# parentheses or bracket following these tokens will be recorded as the start
|
||||
|
|
115
src/nodes.coffee
115
src/nodes.coffee
|
@ -6,7 +6,7 @@
|
|||
{Scope} = require './scope'
|
||||
|
||||
# Import the helpers we plan to use.
|
||||
{compact, flatten, merge, del, include, indexOf, starts, ends, last} = require './helpers'
|
||||
{compact, flatten, merge, del, include, starts, ends, last} = require './helpers'
|
||||
|
||||
# Constant functions for nodes that don't need customization.
|
||||
YES = -> yes
|
||||
|
@ -128,10 +128,11 @@ exports.Base = class Base
|
|||
traverseChildren: (crossScope, func) ->
|
||||
@eachChild (child) ->
|
||||
return false if func(child) is false
|
||||
if child instanceof Base and
|
||||
(crossScope or child not instanceof Code)
|
||||
if crossScope or child not instanceof Code
|
||||
child.traverseChildren crossScope, func
|
||||
|
||||
invert: -> new Op '!', this
|
||||
|
||||
# Default implementations of the common node properties and methods. Nodes
|
||||
# will override these with custom logic, if needed.
|
||||
children: []
|
||||
|
@ -197,24 +198,21 @@ exports.Expressions = class Expressions extends Base
|
|||
# It would be better not to generate them in the first place, but for now,
|
||||
# clean up obvious double-parentheses.
|
||||
compileRoot: (o) ->
|
||||
o.indent = @tab = if o.noWrap then '' else TAB
|
||||
wrap = if o.wrap? then o.wrap else true
|
||||
o.indent = @tab = if wrap then TAB else ''
|
||||
o.scope = new Scope(null, this, null)
|
||||
code = @compileWithDeclarations(o)
|
||||
code = code.replace(TRAILING_WHITESPACE, '')
|
||||
if o.noWrap then code else "(function() {\n#{code}\n}).call(this);\n"
|
||||
if wrap then "(function() {\n#{code}\n}).call(this);\n" else code
|
||||
|
||||
# Compile the expressions body for the contents of a function, with
|
||||
# declarations of all inner variables pushed up to the top.
|
||||
compileWithDeclarations: (o) ->
|
||||
code = @compileNode(o)
|
||||
code = """
|
||||
#{@tab}var #{ o.scope.compiledAssignments().replace /\n/g, '$&' + @tab };
|
||||
#{code}
|
||||
""" if o.scope.hasAssignments this
|
||||
code = """
|
||||
#{@tab}var #{o.scope.compiledDeclarations()};
|
||||
#{code}
|
||||
""" if not o.globals and o.scope.hasDeclarations this
|
||||
if o.scope.hasAssignments this
|
||||
code = "#{@tab}var #{ o.scope.compiledAssignments().replace /\n/g, '$&' + @tab };\n#{code}"
|
||||
if not o.globals and o.scope.hasDeclarations this
|
||||
code = "#{@tab}var #{o.scope.compiledDeclarations()};\n#{code}"
|
||||
code
|
||||
|
||||
# Compiles a single expression within the expressions body. If we need to
|
||||
|
@ -736,20 +734,21 @@ exports.ArrayLiteral = class ArrayLiteral extends Base
|
|||
|
||||
compileNode: (o) ->
|
||||
o.indent = @idt 1
|
||||
for obj in @objects when obj instanceof Splat
|
||||
return @compileSplatLiteral o
|
||||
objects = []
|
||||
for obj, i in @objects
|
||||
code = obj.compile(o)
|
||||
if obj instanceof Splat
|
||||
return @compileSplatLiteral o
|
||||
else if obj instanceof Comment
|
||||
objects.push "\n#{code}\n#{o.indent}"
|
||||
code = obj.compile o
|
||||
objects.push (if obj instanceof Comment
|
||||
"\n#{code}\n#{o.indent}"
|
||||
else if i is @objects.length - 1
|
||||
objects.push code
|
||||
code
|
||||
else
|
||||
objects.push "#{code}, "
|
||||
objects = objects.join('')
|
||||
if indexOf(objects, '\n') >= 0
|
||||
"[\n#{@idt(1)}#{objects}\n#{@tab}]"
|
||||
code + ', '
|
||||
)
|
||||
objects = objects.join ''
|
||||
if 0 < objects.indexOf '\n'
|
||||
"[\n#{o.indent}#{objects}\n#{@tab}]"
|
||||
else
|
||||
"[#{objects}]"
|
||||
|
||||
|
@ -806,7 +805,7 @@ exports.Class = class Class extends Base
|
|||
func.name = className
|
||||
func.body.push new Return new Literal 'this'
|
||||
variable = new Value variable
|
||||
variable.namespaced = include func.name, '.'
|
||||
variable.namespaced = 0 < className.indexOf '.'
|
||||
constructor = func
|
||||
continue
|
||||
if func instanceof Code and func.bound
|
||||
|
@ -860,7 +859,9 @@ exports.Assign = class Assign extends Base
|
|||
if isValue = @isValue()
|
||||
return @compilePatternMatch(o) if @variable.isArray() or @variable.isObject()
|
||||
return @compileSplice(o) if @variable.isSplice()
|
||||
return node.compile o if node = Value.unfoldSoak o, this, 'variable'
|
||||
if ifn = Value.unfoldSoak o, this, 'variable'
|
||||
delete o.top
|
||||
return ifn.compile o
|
||||
top = del o, 'top'
|
||||
stmt = del o, 'asStatement'
|
||||
name = @variable.compile(o)
|
||||
|
@ -964,7 +965,7 @@ exports.Code = class Code extends Base
|
|||
o.top = true
|
||||
o.indent = @idt(1)
|
||||
empty = @body.expressions.length is 0
|
||||
del o, 'noWrap'
|
||||
del o, 'wrap'
|
||||
del o, 'globals'
|
||||
splat = undefined
|
||||
params = []
|
||||
|
@ -993,8 +994,8 @@ exports.Code = class Code extends Base
|
|||
(o.scope.parameter(param)) for param in params
|
||||
o.indent = @idt 2 if @className
|
||||
code = if @body.expressions.length then "\n#{ @body.compileWithDeclarations(o) }\n" else ''
|
||||
open = if @className then "(function() {\n#{@idt(1)}return function #{@className}(" else "function("
|
||||
close = if @className then "#{code and @idt(1)}};\n#{@tab}})()" else "#{code and @tab}}"
|
||||
open = if @className then "(function() {\n#{@idt(1)}function #{@className}(" else "function("
|
||||
close = if @className then "#{code and @idt(1)}};\n#{@idt(1)}return #{@className};\n#{@tab}})()" else "#{code and @tab}}"
|
||||
func = "#{open}#{ params.join(', ') }) {#{code}#{close}"
|
||||
o.scope.endLevel()
|
||||
return "#{utility 'bind'}(#{func}, #{@context})" if @bound
|
||||
|
@ -1102,10 +1103,7 @@ exports.While = class While extends Base
|
|||
|
||||
constructor: (condition, opts) ->
|
||||
super()
|
||||
if opts?.invert
|
||||
condition = new Parens condition if condition instanceof Op
|
||||
condition = new Op('!', condition)
|
||||
@condition = condition
|
||||
@condition = if opts?.invert then condition.invert() else condition
|
||||
@guard = opts?.guard
|
||||
|
||||
addBody: (body) ->
|
||||
|
@ -1124,9 +1122,9 @@ exports.While = class While extends Base
|
|||
compileNode: (o) ->
|
||||
top = del(o, 'top') and not @returns
|
||||
o.indent = @idt 1
|
||||
o.top = true
|
||||
@condition.parenthetical = yes
|
||||
cond = @condition.compile(o)
|
||||
o.top = true
|
||||
set = ''
|
||||
unless top
|
||||
rvar = o.scope.freeVariable 'result'
|
||||
|
@ -1183,9 +1181,6 @@ exports.Op = class Op extends Base
|
|||
isUnary: ->
|
||||
not @second
|
||||
|
||||
isInvertible: ->
|
||||
@operator in ['===', '!==']
|
||||
|
||||
isComplex: -> @operator isnt '!' or @first.isComplex()
|
||||
|
||||
isMutator: ->
|
||||
|
@ -1195,14 +1190,20 @@ exports.Op = class Op extends Base
|
|||
include(@CHAINABLE, @operator)
|
||||
|
||||
invert: ->
|
||||
@operator = @INVERSIONS[@operator]
|
||||
if @operator in ['===', '!==']
|
||||
@operator = @INVERSIONS[@operator]
|
||||
this
|
||||
else if @second
|
||||
new Parens(this).invert()
|
||||
else
|
||||
super()
|
||||
|
||||
toString: (idt) ->
|
||||
super(idt, @constructor.name + ' ' + @operator)
|
||||
|
||||
compileNode: (o) ->
|
||||
return @compileChain(o) if @isChainable() and @first.unwrap() instanceof Op and @first.unwrap().isChainable()
|
||||
return @compileAssignment(o) if indexOf(@ASSIGNMENT, @operator) >= 0
|
||||
return @compileAssignment(o) if include @ASSIGNMENT, @operator
|
||||
return @compileUnary(o) if @isUnary()
|
||||
return @compileExistence(o) if @operator is '?'
|
||||
@first = new Parens @first if @first instanceof Op and @first.isMutator()
|
||||
|
@ -1239,10 +1240,9 @@ exports.Op = class Op extends Base
|
|||
|
||||
# Compile a unary **Op**.
|
||||
compileUnary: (o) ->
|
||||
space = if indexOf(@PREFIX_OPERATORS, @operator) >= 0 then ' ' else ''
|
||||
space = if include @PREFIX_OPERATORS, @operator then ' ' else ''
|
||||
parts = [@operator, space, @first.compile(o)]
|
||||
parts = parts.reverse() if @flip
|
||||
parts.join('')
|
||||
(if @flip then parts.reverse() else parts).join ''
|
||||
|
||||
#### In
|
||||
exports.In = class In extends Base
|
||||
|
@ -1516,14 +1516,7 @@ exports.If = class If extends Base
|
|||
|
||||
constructor: (condition, @body, @tags) ->
|
||||
@tags or= {}
|
||||
if @tags.invert
|
||||
op = condition instanceof Op
|
||||
if op and condition.isInvertible()
|
||||
condition.invert()
|
||||
else
|
||||
condition = new Parens condition if op and not condition.isUnary()
|
||||
condition = new Op '!', condition
|
||||
@condition = condition
|
||||
@condition = if @tags.invert then condition.invert() else condition
|
||||
@elseBody = null
|
||||
@isChain = false
|
||||
|
||||
|
@ -1531,23 +1524,22 @@ exports.If = class If extends Base
|
|||
elseBodyNode: -> @elseBody?.unwrap()
|
||||
|
||||
# Rewrite a chain of **Ifs** to add a default case as the final *else*.
|
||||
addElse: (elseBody, statement) ->
|
||||
addElse: (elseBody) ->
|
||||
if @isChain
|
||||
@elseBodyNode().addElse elseBody, statement
|
||||
@elseBodyNode().addElse elseBody
|
||||
else
|
||||
@isChain = elseBody instanceof If
|
||||
@isChain = elseBody instanceof If
|
||||
@elseBody = @ensureExpressions elseBody
|
||||
this
|
||||
|
||||
# The **If** only compiles into a statement if either of its bodies needs
|
||||
# to be a statement. Otherwise a conditional operator is safe.
|
||||
isStatement: (o) ->
|
||||
@statement or= !!((o and o.top) or @bodyNode().isStatement(o) or (@elseBody and @elseBodyNode().isStatement(o)))
|
||||
@statement or= o?.top or @bodyNode().isStatement(o) or @elseBodyNode()?.isStatement(o)
|
||||
|
||||
compileCondition: (o) ->
|
||||
conditions = flatten [@condition]
|
||||
conditions[0].parenthetical = yes if conditions.length is 1
|
||||
(cond.compile(o) for cond in conditions).join(' || ')
|
||||
@condition.parenthetical = yes
|
||||
@condition.compile o
|
||||
|
||||
compileNode: (o) ->
|
||||
if @isStatement o then @compileStatement o else @compileExpression o
|
||||
|
@ -1571,16 +1563,13 @@ exports.If = class If extends Base
|
|||
condO = merge o
|
||||
o.indent = @idt 1
|
||||
o.top = true
|
||||
ifDent = if child or (top and not @isStatement(o)) then '' else @idt()
|
||||
comDent = if child then @idt() else ''
|
||||
body = @body.compile(o)
|
||||
ifPart = "#{ifDent}if (#{ @compileCondition(condO) }) {\n#{body}\n#{@tab}}"
|
||||
ifPart = "if (#{ @compileCondition condO }) {\n#{ @body.compile o }\n#{@tab}}"
|
||||
ifPart = @tab + ifPart unless child
|
||||
return ifPart unless @elseBody
|
||||
elsePart = if @isChain
|
||||
' else ' + @elseBodyNode().compile(merge(o, {indent: @idt(), chainChild: true}))
|
||||
ifPart + if @isChain
|
||||
' else ' + @elseBodyNode().compile merge o, indent: @tab, chainChild: true
|
||||
else
|
||||
" else {\n#{ @elseBody.compile(o) }\n#{@tab}}"
|
||||
"#{ifPart}#{elsePart}"
|
||||
|
||||
# Compile the If as a conditional operator.
|
||||
compileExpression: (o) ->
|
||||
|
|
|
@ -20,7 +20,7 @@ helpers.extend global, quit: -> process.exit(0)
|
|||
# of exiting.
|
||||
run = (buffer) ->
|
||||
try
|
||||
val = CoffeeScript.eval buffer.toString(), noWrap: true, globals: true, fileName: 'repl'
|
||||
val = CoffeeScript.eval buffer.toString(), wrap: false, globals: true, fileName: 'repl'
|
||||
puts inspect val if val isnt undefined
|
||||
catch err
|
||||
puts err.stack or err.toString()
|
||||
|
|
|
@ -328,7 +328,7 @@ IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@
|
|||
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||
IMPLICIT_CALL = [
|
||||
'IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS'
|
||||
'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY', 'TRUE', 'FALSE'
|
||||
'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY',
|
||||
'@', '->', '=>', '[', '(', '{'
|
||||
]
|
||||
|
||||
|
|
|
@ -26,4 +26,8 @@ tester = ->
|
|||
@example = -> 'example function'
|
||||
this
|
||||
|
||||
ok tester().example() is 'example function'
|
||||
ok tester().example() is 'example function'
|
||||
|
||||
|
||||
try throw CoffeeScript.tokens 'in = 1'
|
||||
catch e then eq e.message, 'Reserved word "in" on line 1 can\'t be assigned'
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
CoffeeScript = require('./../lib/coffee-script')
|
||||
Lexer = require('./../lib/lexer')
|
||||
|
||||
js = CoffeeScript.compile("one\r\ntwo", {noWrap: on})
|
||||
js = CoffeeScript.compile("one\r\ntwo", {wrap: off})
|
||||
|
||||
ok js is "one;\ntwo;"
|
||||
|
||||
|
||||
global.resultArray = []
|
||||
CoffeeScript.run("resultArray.push i for i of global", {noWrap: on, globals: on, fileName: 'tests'})
|
||||
CoffeeScript.run("resultArray.push i for i of global", {wrap: off, globals: on, fileName: 'tests'})
|
||||
|
||||
ok 'setInterval' in global.resultArray
|
||||
|
||||
ok 'passed' is CoffeeScript.eval '"passed"', noWrap: on, globals: on, fileName: 'tests'
|
||||
ok 'passed' is CoffeeScript.eval '"passed"', wrap: off, globals: on, fileName: 'tests'
|
||||
|
||||
#750
|
||||
try
|
||||
|
|
|
@ -47,3 +47,7 @@ loop
|
|||
list.push i * 2
|
||||
|
||||
ok list.join(' ') is '8 6 4 2'
|
||||
|
||||
|
||||
#759: `if` within `while` condition
|
||||
2 while if 1 then 0
|
||||
|
|
Loading…
Reference in New Issue