1
0
Fork 0
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:
Simon Lydell 2016-03-06 10:57:31 +01:00
commit cbc72a29bf
13 changed files with 267 additions and 242 deletions

View file

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

View file

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

View file

@ -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', '}', '::']);

View file

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

View file

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

View file

@ -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 = ['+', '-'];

View file

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

View file

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

View file

@ -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', '}', '::'

View file

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

View file

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

View file

@ -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'
'@', '->', '=>', '[', '(', '{', '--', '++'