mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Merge pull request #4220 from lydell/propertyliteral
Split out properties from identifiers
This commit is contained in:
commit
cbc72a29bf
13 changed files with 267 additions and 242 deletions
|
@ -67,7 +67,7 @@
|
|||
results = [];
|
||||
for (i = 0, len = tokens.length; i < len; i++) {
|
||||
token = tokens[i];
|
||||
if (token.variable) {
|
||||
if (token[0] === 'IDENTIFIER') {
|
||||
results.push(token[1]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,11 @@
|
|||
return new IdentifierLiteral($1);
|
||||
})
|
||||
],
|
||||
Property: [
|
||||
o('PROPERTY', function() {
|
||||
return new PropertyName($1);
|
||||
})
|
||||
],
|
||||
AlphaNumeric: [
|
||||
o('NUMBER', function() {
|
||||
return new NumberLiteral($1);
|
||||
|
@ -131,7 +136,7 @@
|
|||
});
|
||||
}), o('Comment')
|
||||
],
|
||||
SimpleObjAssignable: [o('Identifier'), o('ThisProperty')],
|
||||
SimpleObjAssignable: [o('Identifier'), o('Property'), o('ThisProperty')],
|
||||
ObjAssignable: [o('SimpleObjAssignable'), o('AlphaNumeric')],
|
||||
Return: [
|
||||
o('RETURN Expression', function() {
|
||||
|
@ -223,16 +228,16 @@
|
|||
}), o('This')
|
||||
],
|
||||
Accessor: [
|
||||
o('. Identifier', function() {
|
||||
o('. Property', function() {
|
||||
return new Access($2);
|
||||
}), o('?. Identifier', function() {
|
||||
}), o('?. Property', function() {
|
||||
return new Access($2, 'soak');
|
||||
}), o(':: Identifier', function() {
|
||||
return [LOC(1)(new Access(new IdentifierLiteral('prototype'))), LOC(2)(new Access($2))];
|
||||
}), o('?:: Identifier', function() {
|
||||
return [LOC(1)(new Access(new IdentifierLiteral('prototype'), 'soak')), LOC(2)(new Access($2))];
|
||||
}), o(':: Property', function() {
|
||||
return [LOC(1)(new Access(new PropertyName('prototype'))), LOC(2)(new Access($2))];
|
||||
}), o('?:: Property', function() {
|
||||
return [LOC(1)(new Access(new PropertyName('prototype'), 'soak')), LOC(2)(new Access($2))];
|
||||
}), o('::', function() {
|
||||
return new Access(new IdentifierLiteral('prototype'));
|
||||
return new Access(new PropertyName('prototype'));
|
||||
}), o('Index')
|
||||
],
|
||||
Index: [
|
||||
|
@ -324,7 +329,7 @@
|
|||
})
|
||||
],
|
||||
ThisProperty: [
|
||||
o('@ Identifier', function() {
|
||||
o('@ Property', function() {
|
||||
return new Value(LOC(1)(new ThisLiteral), [LOC(2)(new Access($2))], 'this');
|
||||
})
|
||||
],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Generated by CoffeeScript 1.10.0
|
||||
(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, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVALID_ESCAPE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, LOGIC, 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, 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, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVALID_ESCAPE, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, LOGIC, 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, isUnassignable, key, locationDataToString, ref, ref1, 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; },
|
||||
slice = [].slice;
|
||||
|
||||
|
@ -66,7 +66,7 @@
|
|||
};
|
||||
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var alias, colon, colonOffset, forcedIdentifier, id, idLength, input, match, poppedToken, prev, ref2, ref3, ref4, ref5, tag, tagToken;
|
||||
var alias, colon, colonOffset, id, idLength, input, match, poppedToken, prev, ref2, ref3, ref4, ref5, tag, tagToken;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -82,9 +82,8 @@
|
|||
return id.length;
|
||||
}
|
||||
ref2 = this.tokens, prev = ref2[ref2.length - 1];
|
||||
forcedIdentifier = colon || (prev != null) && (((ref3 = prev[0]) === '.' || ref3 === '?.' || ref3 === '::' || ref3 === '?::') || !prev.spaced && prev[0] === '@');
|
||||
tag = 'IDENTIFIER';
|
||||
if (!forcedIdentifier && (indexOf.call(JS_KEYWORDS, id) >= 0 || indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
tag = colon || (prev != null) && (((ref3 = prev[0]) === '.' || ref3 === '?.' || ref3 === '::' || ref3 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
|
||||
if (tag === 'IDENTIFIER' && (indexOf.call(JS_KEYWORDS, id) >= 0 || indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
tag = id.toUpperCase();
|
||||
if (tag === 'WHEN' && (ref4 = this.tag(), indexOf.call(LINE_BREAK, ref4) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
|
@ -107,16 +106,12 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
if (indexOf.call(JS_FORBIDDEN, id) >= 0) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'IDENTIFIER';
|
||||
} else if (indexOf.call(RESERVED, id) >= 0) {
|
||||
this.error("reserved word '" + id + "'", {
|
||||
length: id.length
|
||||
});
|
||||
}
|
||||
if (tag === 'IDENTIFIER' && indexOf.call(RESERVED, id) >= 0) {
|
||||
this.error("reserved word '" + id + "'", {
|
||||
length: id.length
|
||||
});
|
||||
}
|
||||
if (!forcedIdentifier) {
|
||||
if (tag !== 'PROPERTY') {
|
||||
if (indexOf.call(COFFEE_ALIASES, id) >= 0) {
|
||||
alias = id;
|
||||
id = COFFEE_ALIAS_MAP[id];
|
||||
|
@ -147,7 +142,6 @@
|
|||
if (alias) {
|
||||
tagToken.origin = [tag, alias, tagToken[2]];
|
||||
}
|
||||
tagToken.variable = !forcedIdentifier;
|
||||
if (poppedToken) {
|
||||
ref5 = [poppedToken[2].first_line, poppedToken[2].first_column], tagToken[2].first_line = ref5[0], tagToken[2].first_column = ref5[1];
|
||||
}
|
||||
|
@ -515,7 +509,7 @@
|
|||
prev = this.tokens[this.tokens.length - 2];
|
||||
skipToken = true;
|
||||
}
|
||||
if (prev && prev.variable) {
|
||||
if (prev && prev[0] !== 'PROPERTY') {
|
||||
origin = (ref4 = prev.origin) != null ? ref4 : prev;
|
||||
message = isUnassignable(prev[1], origin[1]);
|
||||
if (message) {
|
||||
|
@ -942,8 +936,6 @@
|
|||
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval'];
|
||||
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED);
|
||||
|
||||
exports.JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED);
|
||||
|
||||
BOM = 65279;
|
||||
|
@ -1024,7 +1016,7 @@
|
|||
|
||||
BOOL = ['TRUE', 'FALSE'];
|
||||
|
||||
CALLABLE = ['IDENTIFIER', ')', ']', '?', '@', 'THIS', 'SUPER'];
|
||||
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER'];
|
||||
|
||||
INDEXABLE = CALLABLE.concat(['NUMBER', 'INFINITY', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END', 'BOOL', 'NULL', 'UNDEFINED', '}', '::']);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Generated by CoffeeScript 1.10.0
|
||||
(function() {
|
||||
var Access, Arr, Assign, Base, Block, BooleanLiteral, Call, Class, Code, CodeFragment, Comment, Existence, Expansion, Extends, For, IdentifierLiteral, If, In, Index, InfinityLiteral, JS_FORBIDDEN, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, NEGATE, NO, NullLiteral, NumberLiteral, Obj, Op, Param, Parens, PassthroughLiteral, Range, RegexLiteral, RegexWithInterpolations, Return, SIMPLENUM, Scope, Slice, Splat, StatementLiteral, StringLiteral, StringWithInterpolations, SuperCall, Switch, TAB, THIS, ThisLiteral, Throw, Try, UTILITIES, UndefinedLiteral, Value, While, YES, YieldReturn, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, isComplexOrAssignable, isLiteralArguments, isLiteralThis, isUnassignable, locationDataToString, merge, multident, ref1, ref2, some, starts, throwSyntaxError, unfoldSoak, utility,
|
||||
var Access, Arr, Assign, Base, Block, BooleanLiteral, Call, Class, Code, CodeFragment, Comment, Existence, Expansion, Extends, For, IdentifierLiteral, If, In, Index, InfinityLiteral, JS_FORBIDDEN, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, NEGATE, NO, NullLiteral, NumberLiteral, Obj, Op, Param, Parens, PassthroughLiteral, PropertyName, Range, RegexLiteral, RegexWithInterpolations, Return, SIMPLENUM, Scope, Slice, Splat, StatementLiteral, StringLiteral, StringWithInterpolations, SuperCall, Switch, TAB, THIS, ThisLiteral, Throw, Try, UTILITIES, UndefinedLiteral, Value, While, YES, YieldReturn, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, isComplexOrAssignable, isLiteralArguments, isLiteralThis, isUnassignable, locationDataToString, merge, multident, ref1, ref2, some, starts, throwSyntaxError, unfoldSoak, utility,
|
||||
extend1 = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty,
|
||||
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; },
|
||||
|
@ -102,7 +102,7 @@
|
|||
} else {
|
||||
meth = 'call';
|
||||
}
|
||||
func = new Value(func, [new Access(new IdentifierLiteral(meth))]);
|
||||
func = new Value(func, [new Access(new PropertyName(meth))]);
|
||||
}
|
||||
parts = (new Call(func, args)).compileNode(o);
|
||||
if (func.isGenerator || ((ref3 = func.base) != null ? ref3.isGenerator : void 0)) {
|
||||
|
@ -614,6 +614,19 @@
|
|||
|
||||
})(Literal);
|
||||
|
||||
exports.PropertyName = PropertyName = (function(superClass1) {
|
||||
extend1(PropertyName, superClass1);
|
||||
|
||||
function PropertyName() {
|
||||
return PropertyName.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
PropertyName.prototype.isAssignable = YES;
|
||||
|
||||
return PropertyName;
|
||||
|
||||
})(Literal);
|
||||
|
||||
exports.StatementLiteral = StatementLiteral = (function(superClass1) {
|
||||
extend1(StatementLiteral, superClass1);
|
||||
|
||||
|
@ -1147,9 +1160,9 @@
|
|||
variable.properties.pop();
|
||||
variable.properties.push(name);
|
||||
}
|
||||
accesses = [new Access(new IdentifierLiteral('__super__'))];
|
||||
accesses = [new Access(new PropertyName('__super__'))];
|
||||
if (method["static"]) {
|
||||
accesses.push(new Access(new IdentifierLiteral('constructor')));
|
||||
accesses.push(new Access(new PropertyName('constructor')));
|
||||
}
|
||||
accesses.push(nref != null ? new Index(nref) : name);
|
||||
return (new Value(bref != null ? bref : klass, accesses)).compile(o);
|
||||
|
@ -1217,7 +1230,7 @@
|
|||
var name, node, ref3;
|
||||
name = this.name.compileToFragments(o);
|
||||
node = this.name.unwrap();
|
||||
if (node instanceof IdentifierLiteral) {
|
||||
if (node instanceof PropertyName) {
|
||||
if (ref3 = node.value, indexOf.call(JS_FORBIDDEN, ref3) >= 0) {
|
||||
return [this.makeCode('["')].concat(slice.call(name), [this.makeCode('"]')]);
|
||||
} else {
|
||||
|
@ -1583,7 +1596,7 @@
|
|||
}
|
||||
ref3 = this.variable.properties, tail = ref3[ref3.length - 1];
|
||||
node = tail ? tail instanceof Access && tail.name : this.variable.base;
|
||||
if (!(node instanceof IdentifierLiteral)) {
|
||||
if (!(node instanceof IdentifierLiteral || node instanceof PropertyName)) {
|
||||
return this.defaultClassVariableName;
|
||||
}
|
||||
name = node.value;
|
||||
|
@ -1646,7 +1659,7 @@
|
|||
if (func instanceof Code) {
|
||||
assign = this.ctor = func;
|
||||
} else {
|
||||
this.externalCtor = o.classScope.freeVariable('class');
|
||||
this.externalCtor = o.classScope.freeVariable('ctor');
|
||||
assign = new Assign(new IdentifierLiteral(this.externalCtor), func);
|
||||
}
|
||||
} else {
|
||||
|
@ -1654,7 +1667,7 @@
|
|||
func["static"] = true;
|
||||
} else {
|
||||
acc = base.isComplex() ? new Index(base) : new Access(base);
|
||||
assign.variable = new Value(new IdentifierLiteral(name), [new Access(new IdentifierLiteral('prototype')), acc]);
|
||||
assign.variable = new Value(new IdentifierLiteral(name), [new Access(new PropertyName('prototype')), acc]);
|
||||
if (func instanceof Code && func.bound) {
|
||||
this.boundFuncs.push(base);
|
||||
func.bound = false;
|
||||
|
@ -1882,9 +1895,9 @@
|
|||
defaultValue = obj.value;
|
||||
obj = obj.variable;
|
||||
}
|
||||
idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new NumberLiteral(0);
|
||||
idx = isObject ? obj["this"] ? obj.properties[0].name : new PropertyName(obj.unwrap().value) : new NumberLiteral(0);
|
||||
}
|
||||
acc = idx.unwrap() instanceof IdentifierLiteral;
|
||||
acc = idx.unwrap() instanceof PropertyName;
|
||||
value = new Value(value);
|
||||
value.properties.push(new (acc ? Access : Index)(idx));
|
||||
message = isUnassignable(obj.unwrap().value);
|
||||
|
@ -1954,10 +1967,10 @@
|
|||
defaultValue = obj.value;
|
||||
obj = obj.variable;
|
||||
}
|
||||
idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(expandedIdx || idx);
|
||||
idx = isObject ? obj["this"] ? obj.properties[0].name : new PropertyName(obj.unwrap().value) : new Literal(expandedIdx || idx);
|
||||
}
|
||||
name = obj.unwrap().value;
|
||||
acc = idx.unwrap() instanceof IdentifierLiteral;
|
||||
acc = idx.unwrap() instanceof PropertyName;
|
||||
val = new Value(new Literal(vvarText), [new (acc ? Access : Index)(idx)]);
|
||||
if (defaultValue) {
|
||||
val = new Op('?', val, defaultValue);
|
||||
|
@ -2735,13 +2748,13 @@
|
|||
|
||||
Op.prototype.compilePower = function(o) {
|
||||
var pow;
|
||||
pow = new Value(new IdentifierLiteral('Math'), [new Access(new IdentifierLiteral('pow'))]);
|
||||
pow = new Value(new IdentifierLiteral('Math'), [new Access(new PropertyName('pow'))]);
|
||||
return new Call(pow, [this.first, this.second]).compileToFragments(o);
|
||||
};
|
||||
|
||||
Op.prototype.compileFloorDivision = function(o) {
|
||||
var div, floor;
|
||||
floor = new Value(new IdentifierLiteral('Math'), [new Access(new IdentifierLiteral('floor'))]);
|
||||
floor = new Value(new IdentifierLiteral('Math'), [new Access(new PropertyName('floor'))]);
|
||||
div = new Op('/', this.first, this.second);
|
||||
return new Call(floor, [div]).compileToFragments(o);
|
||||
};
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -30,7 +30,7 @@
|
|||
results = [];
|
||||
for (i = 0, len = tokens.length; i < len; i++) {
|
||||
token = tokens[i];
|
||||
if (token.variable) {
|
||||
if (token[0] === 'IDENTIFIER') {
|
||||
results.push(token[1]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -485,9 +485,9 @@
|
|||
|
||||
EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'INFINITY', 'STRING', 'STRING_START', 'JS', 'REGEX', 'REGEX_START', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'PROPERTY', 'NUMBER', 'INFINITY', 'STRING', 'STRING_START', 'JS', 'REGEX', 'REGEX_START', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ exports.compile = compile = withPrettyErrors (code, options) ->
|
|||
# Pass a list of referenced variables, so that generated variables won't get
|
||||
# the same name.
|
||||
options.referencedVars = (
|
||||
token[1] for token in tokens when token.variable
|
||||
token[1] for token in tokens when token[0] is 'IDENTIFIER'
|
||||
)
|
||||
|
||||
fragments = parser.parse(tokens).compileToFragments options
|
||||
|
|
|
@ -133,11 +133,14 @@ grammar =
|
|||
o 'INDENT Body OUTDENT', -> $2
|
||||
]
|
||||
|
||||
# A literal identifier, a variable name or property.
|
||||
Identifier: [
|
||||
o 'IDENTIFIER', -> new IdentifierLiteral $1
|
||||
]
|
||||
|
||||
Property: [
|
||||
o 'PROPERTY', -> new PropertyName $1
|
||||
]
|
||||
|
||||
# Alphanumerics are separated from the other **Literal** matchers because
|
||||
# they can also serve as keys in object literals.
|
||||
AlphaNumeric: [
|
||||
|
@ -193,6 +196,7 @@ grammar =
|
|||
|
||||
SimpleObjAssignable: [
|
||||
o 'Identifier'
|
||||
o 'Property'
|
||||
o 'ThisProperty'
|
||||
]
|
||||
|
||||
|
@ -297,11 +301,11 @@ grammar =
|
|||
# The general group of accessors into an object, by property, by prototype
|
||||
# or by array index or slice.
|
||||
Accessor: [
|
||||
o '. Identifier', -> new Access $2
|
||||
o '?. Identifier', -> new Access $2, 'soak'
|
||||
o ':: Identifier', -> [LOC(1)(new Access new IdentifierLiteral('prototype')), LOC(2)(new Access $2)]
|
||||
o '?:: Identifier', -> [LOC(1)(new Access new IdentifierLiteral('prototype'), 'soak'), LOC(2)(new Access $2)]
|
||||
o '::', -> new Access new IdentifierLiteral 'prototype'
|
||||
o '. Property', -> new Access $2
|
||||
o '?. Property', -> new Access $2, 'soak'
|
||||
o ':: Property', -> [LOC(1)(new Access new PropertyName('prototype')), LOC(2)(new Access $2)]
|
||||
o '?:: Property', -> [LOC(1)(new Access new PropertyName('prototype'), 'soak'), LOC(2)(new Access $2)]
|
||||
o '::', -> new Access new PropertyName 'prototype'
|
||||
o 'Index'
|
||||
]
|
||||
|
||||
|
@ -376,7 +380,7 @@ grammar =
|
|||
|
||||
# A reference to a property on *this*.
|
||||
ThisProperty: [
|
||||
o '@ Identifier', -> new Value LOC(1)(new ThisLiteral), [LOC(2)(new Access($2))], 'this'
|
||||
o '@ Property', -> new Value LOC(1)(new ThisLiteral), [LOC(2)(new Access($2))], 'this'
|
||||
]
|
||||
|
||||
# The array literal.
|
||||
|
|
|
@ -114,12 +114,15 @@ exports.Lexer = class Lexer
|
|||
@token 'FROM', id
|
||||
return id.length
|
||||
[..., prev] = @tokens
|
||||
forcedIdentifier = colon or prev? and
|
||||
(prev[0] in ['.', '?.', '::', '?::'] or
|
||||
not prev.spaced and prev[0] is '@')
|
||||
tag = 'IDENTIFIER'
|
||||
tag =
|
||||
if colon or prev? and
|
||||
(prev[0] in ['.', '?.', '::', '?::'] or
|
||||
not prev.spaced and prev[0] is '@')
|
||||
'PROPERTY'
|
||||
else
|
||||
'IDENTIFIER'
|
||||
|
||||
if not forcedIdentifier and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS)
|
||||
if tag is 'IDENTIFIER' and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS)
|
||||
tag = id.toUpperCase()
|
||||
if tag is 'WHEN' and @tag() in LINE_BREAK
|
||||
tag = 'LEADING_WHEN'
|
||||
|
@ -139,13 +142,10 @@ exports.Lexer = class Lexer
|
|||
poppedToken = @tokens.pop()
|
||||
id = '!' + id
|
||||
|
||||
if id in JS_FORBIDDEN
|
||||
if forcedIdentifier
|
||||
tag = 'IDENTIFIER'
|
||||
else if id in RESERVED
|
||||
@error "reserved word '#{id}'", length: id.length
|
||||
if tag is 'IDENTIFIER' and id in RESERVED
|
||||
@error "reserved word '#{id}'", length: id.length
|
||||
|
||||
unless forcedIdentifier
|
||||
unless tag is 'PROPERTY'
|
||||
if id in COFFEE_ALIASES
|
||||
alias = id
|
||||
id = COFFEE_ALIAS_MAP[id]
|
||||
|
@ -160,7 +160,6 @@ exports.Lexer = class Lexer
|
|||
|
||||
tagToken = @token tag, id, 0, idLength
|
||||
tagToken.origin = [tag, alias, tagToken[2]] if alias
|
||||
tagToken.variable = not forcedIdentifier
|
||||
if poppedToken
|
||||
[tagToken[2].first_line, tagToken[2].first_column] =
|
||||
[poppedToken[2].first_line, poppedToken[2].first_column]
|
||||
|
@ -419,7 +418,7 @@ exports.Lexer = class Lexer
|
|||
prev[1] += '='
|
||||
prev = @tokens[@tokens.length - 2]
|
||||
skipToken = true
|
||||
if prev and prev.variable
|
||||
if prev and prev[0] isnt 'PROPERTY'
|
||||
origin = prev.origin ? prev
|
||||
message = isUnassignable prev[1], origin[1]
|
||||
@error message, origin[2] if message
|
||||
|
@ -807,7 +806,6 @@ STRICT_PROSCRIBED = ['arguments', 'eval']
|
|||
|
||||
# The superset of both JavaScript keywords and reserved words, none of which may
|
||||
# be used as identifiers or properties.
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED)
|
||||
exports.JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED)
|
||||
|
||||
# The character code of the nasty Microsoft madness otherwise known as the BOM.
|
||||
|
@ -939,7 +937,7 @@ BOOL = ['TRUE', 'FALSE']
|
|||
# Tokens which could legitimately be invoked or indexed. An opening
|
||||
# parentheses or bracket following these tokens will be recorded as the start
|
||||
# of a function invocation or indexing operation.
|
||||
CALLABLE = ['IDENTIFIER', ')', ']', '?', '@', 'THIS', 'SUPER']
|
||||
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER']
|
||||
INDEXABLE = CALLABLE.concat [
|
||||
'NUMBER', 'INFINITY', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END'
|
||||
'BOOL', 'NULL', 'UNDEFINED', '}', '::'
|
||||
|
|
|
@ -88,7 +88,7 @@ exports.Base = class Base
|
|||
args.push new IdentifierLiteral 'arguments'
|
||||
else
|
||||
meth = 'call'
|
||||
func = new Value func, [new Access new IdentifierLiteral meth]
|
||||
func = new Value func, [new Access new PropertyName meth]
|
||||
parts = (new Call func, args).compileNode o
|
||||
if func.isGenerator or func.base?.isGenerator
|
||||
parts.unshift @makeCode "(yield* "
|
||||
|
@ -413,6 +413,9 @@ exports.PassthroughLiteral = class PassthroughLiteral extends Literal
|
|||
exports.IdentifierLiteral = class IdentifierLiteral extends Literal
|
||||
isAssignable: YES
|
||||
|
||||
exports.PropertyName = class PropertyName extends Literal
|
||||
isAssignable: YES
|
||||
|
||||
exports.StatementLiteral = class StatementLiteral extends Literal
|
||||
isStatement: YES
|
||||
|
||||
|
@ -754,8 +757,8 @@ exports.SuperCall = class SuperCall extends Call
|
|||
name = new Index new Assign nref, name.index
|
||||
variable.properties.pop()
|
||||
variable.properties.push name
|
||||
accesses = [new Access new IdentifierLiteral '__super__']
|
||||
accesses.push new Access new IdentifierLiteral 'constructor' if method.static
|
||||
accesses = [new Access new PropertyName '__super__']
|
||||
accesses.push new Access new PropertyName 'constructor' if method.static
|
||||
accesses.push if nref? then new Index nref else name
|
||||
(new Value bref ? klass, accesses).compile o
|
||||
else if method?.ctor
|
||||
|
@ -804,7 +807,7 @@ exports.Access = class Access extends Base
|
|||
compileToFragments: (o) ->
|
||||
name = @name.compileToFragments o
|
||||
node = @name.unwrap()
|
||||
if node instanceof IdentifierLiteral
|
||||
if node instanceof PropertyName
|
||||
if node.value in JS_FORBIDDEN
|
||||
[@makeCode('["'), name..., @makeCode('"]')]
|
||||
else
|
||||
|
@ -1079,7 +1082,8 @@ exports.Class = class Class extends Base
|
|||
tail instanceof Access and tail.name
|
||||
else
|
||||
@variable.base
|
||||
return @defaultClassVariableName unless node instanceof IdentifierLiteral
|
||||
unless node instanceof IdentifierLiteral or node instanceof PropertyName
|
||||
return @defaultClassVariableName
|
||||
name = node.value
|
||||
unless tail
|
||||
message = isUnassignable name
|
||||
|
@ -1121,14 +1125,14 @@ exports.Class = class Class extends Base
|
|||
if func instanceof Code
|
||||
assign = @ctor = func
|
||||
else
|
||||
@externalCtor = o.classScope.freeVariable 'class'
|
||||
@externalCtor = o.classScope.freeVariable 'ctor'
|
||||
assign = new Assign new IdentifierLiteral(@externalCtor), func
|
||||
else
|
||||
if assign.variable.this
|
||||
func.static = yes
|
||||
else
|
||||
acc = if base.isComplex() then new Index base else new Access base
|
||||
assign.variable = new Value(new IdentifierLiteral(name), [(new Access new IdentifierLiteral 'prototype'), acc])
|
||||
assign.variable = new Value(new IdentifierLiteral(name), [(new Access new PropertyName 'prototype'), acc])
|
||||
if func instanceof Code and func.bound
|
||||
@boundFuncs.push base
|
||||
func.bound = no
|
||||
|
@ -1302,11 +1306,14 @@ exports.Assign = class Assign extends Base
|
|||
obj = obj.variable
|
||||
idx = if isObject
|
||||
# A shorthand `{a, b, @c} = val` pattern-match.
|
||||
if obj.this then obj.properties[0].name else obj
|
||||
if obj.this
|
||||
obj.properties[0].name
|
||||
else
|
||||
new PropertyName obj.unwrap().value
|
||||
else
|
||||
# A regular array pattern-match.
|
||||
new NumberLiteral 0
|
||||
acc = idx.unwrap() instanceof IdentifierLiteral
|
||||
acc = idx.unwrap() instanceof PropertyName
|
||||
value = new Value value
|
||||
value.properties.push new (if acc then Access else Index) idx
|
||||
message = isUnassignable obj.unwrap().value
|
||||
|
@ -1361,12 +1368,15 @@ exports.Assign = class Assign extends Base
|
|||
obj = obj.variable
|
||||
idx = if isObject
|
||||
# A shorthand `{a, b, @c} = val` pattern-match.
|
||||
if obj.this then obj.properties[0].name else obj
|
||||
if obj.this
|
||||
obj.properties[0].name
|
||||
else
|
||||
new PropertyName obj.unwrap().value
|
||||
else
|
||||
# A regular array pattern-match.
|
||||
new Literal expandedIdx or idx
|
||||
name = obj.unwrap().value
|
||||
acc = idx.unwrap() instanceof IdentifierLiteral
|
||||
acc = idx.unwrap() instanceof PropertyName
|
||||
val = new Value new Literal(vvarText), [new (if acc then Access else Index) idx]
|
||||
val = new Op '?', val, defaultValue if defaultValue
|
||||
if name?
|
||||
|
@ -1893,11 +1903,11 @@ exports.Op = class Op extends Base
|
|||
|
||||
compilePower: (o) ->
|
||||
# Make a Math.pow call
|
||||
pow = new Value new IdentifierLiteral('Math'), [new Access new IdentifierLiteral 'pow']
|
||||
pow = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'pow']
|
||||
new Call(pow, [@first, @second]).compileToFragments o
|
||||
|
||||
compileFloorDivision: (o) ->
|
||||
floor = new Value new IdentifierLiteral('Math'), [new Access new IdentifierLiteral 'floor']
|
||||
floor = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'floor']
|
||||
div = new Op '/', @first, @second
|
||||
new Call(floor, [div]).compileToFragments o
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ replDefaults =
|
|||
tokens = CoffeeScript.tokens input
|
||||
# Collect referenced variable names just like in `CoffeeScript.compile`.
|
||||
referencedVars = (
|
||||
token[1] for token in tokens when token.variable
|
||||
token[1] for token in tokens when token[0] is 'IDENTIFIER'
|
||||
)
|
||||
# Generate the AST of the tokens.
|
||||
ast = CoffeeScript.nodes tokens
|
||||
|
|
|
@ -479,11 +479,11 @@ for [left, rite] in BALANCED_PAIRS
|
|||
EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat EXPRESSION_END
|
||||
|
||||
# Tokens that, if followed by an `IMPLICIT_CALL`, indicate a function invocation.
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']
|
||||
|
||||
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||
IMPLICIT_CALL = [
|
||||
'IDENTIFIER', 'NUMBER', 'INFINITY', 'STRING', 'STRING_START', 'JS', 'REGEX', 'REGEX_START'
|
||||
'IDENTIFIER', 'PROPERTY', 'NUMBER', 'INFINITY', 'STRING', 'STRING_START', 'JS', 'REGEX', 'REGEX_START'
|
||||
'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL'
|
||||
'UNDEFINED', 'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW'
|
||||
'@', '->', '=>', '[', '(', '{', '--', '++'
|
||||
|
|
Loading…
Reference in a new issue