Parse and emit for bind

This commit is contained in:
Ron Buckton
2016-11-21 21:45:53 -05:00
parent 60288b7d7b
commit c1c7e20856
8 changed files with 201 additions and 113 deletions
+4
View File
@@ -3242,6 +3242,10 @@ namespace ts {
transformFlags |= TransformFlags.AssertESNext;
break;
case SyntaxKind.BindExpression:
transformFlags |= TransformFlags.AssertESNext;
break;
case SyntaxKind.SuperKeyword:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES2015;
+8
View File
@@ -616,6 +616,8 @@ namespace ts {
return emitPropertyAccessExpression(<PropertyAccessExpression>node);
case SyntaxKind.ElementAccessExpression:
return emitElementAccessExpression(<ElementAccessExpression>node);
case SyntaxKind.BindExpression:
return emitBindExpression(<BindExpression>node);
case SyntaxKind.CallExpression:
return emitCallExpression(<CallExpression>node);
case SyntaxKind.NewExpression:
@@ -1079,6 +1081,12 @@ namespace ts {
write("]");
}
function emitBindExpression(node: BindExpression) {
emitExpression(node.expression);
write("::");
emitExpression(node.targetExpression);
}
function emitCallExpression(node: CallExpression) {
emitExpression(node.expression);
emitTypeArguments(node, node.typeArguments);
+12
View File
@@ -1624,6 +1624,18 @@ namespace ts {
);
}
export function createFunctionBind(func: Expression, thisArg: Expression, argumentsList: Expression[], location?: TextRange) {
return createCall(
createPropertyAccess(func, "bind"),
/*typeArguments*/ undefined,
[
thisArg,
...argumentsList
],
location
);
}
export function createFunctionApply(func: Expression, thisArg: Expression, argumentsExpression: Expression, location?: TextRange) {
return createCall(
createPropertyAccess(func, "apply"),
+8
View File
@@ -4026,6 +4026,14 @@ namespace ts {
continue;
}
if (parseOptional(SyntaxKind.ColonColonToken)) {
const bindExpression = <BindExpression>createNode(SyntaxKind.BindExpression, expression.pos);
bindExpression.expression = expression;
bindExpression.targetExpression = parseMemberExpressionOrHigher();
expression = finishNode(bindExpression);
continue;
}
return <MemberExpression>expression;
}
}
+128 -108
View File
@@ -170,6 +170,7 @@ namespace ts {
"||": SyntaxKind.BarBarToken,
"?": SyntaxKind.QuestionToken,
":": SyntaxKind.ColonToken,
"::": SyntaxKind.ColonColonToken,
"=": SyntaxKind.EqualsToken,
"+=": SyntaxKind.PlusEqualsToken,
"-=": SyntaxKind.MinusEqualsToken,
@@ -1273,8 +1274,8 @@ namespace ts {
return token = SyntaxKind.WhitespaceTrivia;
}
case CharacterCodes.exclamation:
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
if (pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.equals) {
if (pos + 2 < end && text.charCodeAt(pos + 2) === CharacterCodes.equals) {
return pos += 3, token = SyntaxKind.ExclamationEqualsEqualsToken;
}
return pos += 2, token = SyntaxKind.ExclamationEqualsToken;
@@ -1288,17 +1289,19 @@ namespace ts {
case CharacterCodes.backtick:
return token = scanTemplateAndSetTokenValue();
case CharacterCodes.percent:
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
if (pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.PercentEqualsToken;
}
pos++;
return token = SyntaxKind.PercentToken;
case CharacterCodes.ampersand:
if (text.charCodeAt(pos + 1) === CharacterCodes.ampersand) {
return pos += 2, token = SyntaxKind.AmpersandAmpersandToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.AmpersandEqualsToken;
if (pos + 1 < end) {
if (text.charCodeAt(pos + 1) === CharacterCodes.ampersand) {
return pos += 2, token = SyntaxKind.AmpersandAmpersandToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.AmpersandEqualsToken;
}
}
pos++;
return token = SyntaxKind.AmpersandToken;
@@ -1309,23 +1312,27 @@ namespace ts {
pos++;
return token = SyntaxKind.CloseParenToken;
case CharacterCodes.asterisk:
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.AsteriskEqualsToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
return pos += 3, token = SyntaxKind.AsteriskAsteriskEqualsToken;
if (pos + 1 < end) {
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.AsteriskEqualsToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
if (pos + 2 < end && text.charCodeAt(pos + 2) === CharacterCodes.equals) {
return pos += 3, token = SyntaxKind.AsteriskAsteriskEqualsToken;
}
return pos += 2, token = SyntaxKind.AsteriskAsteriskToken;
}
return pos += 2, token = SyntaxKind.AsteriskAsteriskToken;
}
pos++;
return token = SyntaxKind.AsteriskToken;
case CharacterCodes.plus:
if (text.charCodeAt(pos + 1) === CharacterCodes.plus) {
return pos += 2, token = SyntaxKind.PlusPlusToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.PlusEqualsToken;
if (pos + 1 < end) {
if (text.charCodeAt(pos + 1) === CharacterCodes.plus) {
return pos += 2, token = SyntaxKind.PlusPlusToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.PlusEqualsToken;
}
}
pos++;
return token = SyntaxKind.PlusToken;
@@ -1333,81 +1340,86 @@ namespace ts {
pos++;
return token = SyntaxKind.CommaToken;
case CharacterCodes.minus:
if (text.charCodeAt(pos + 1) === CharacterCodes.minus) {
return pos += 2, token = SyntaxKind.MinusMinusToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.MinusEqualsToken;
if (pos + 1 < end) {
if (text.charCodeAt(pos + 1) === CharacterCodes.minus) {
return pos += 2, token = SyntaxKind.MinusMinusToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.MinusEqualsToken;
}
}
pos++;
return token = SyntaxKind.MinusToken;
case CharacterCodes.dot:
if (isDigit(text.charCodeAt(pos + 1))) {
tokenValue = scanNumber();
return token = SyntaxKind.NumericLiteral;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) {
return pos += 3, token = SyntaxKind.DotDotDotToken;
if (pos + 1 < end) {
if (isDigit(text.charCodeAt(pos + 1))) {
tokenValue = scanNumber();
return token = SyntaxKind.NumericLiteral;
}
if (pos + 2 < end && text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) {
return pos += 3, token = SyntaxKind.DotDotDotToken;
}
}
pos++;
return token = SyntaxKind.DotToken;
case CharacterCodes.slash:
// Single-line comment
if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
pos += 2;
if (pos + 1 < end) {
if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
pos += 2;
while (pos < end) {
if (isLineBreak(text.charCodeAt(pos))) {
break;
}
pos++;
while (pos < end) {
if (isLineBreak(text.charCodeAt(pos))) {
break;
}
pos++;
}
if (skipTrivia) {
continue;
}
else {
return token = SyntaxKind.SingleLineCommentTrivia;
}
}
// Multi-line comment
if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
pos += 2;
let commentClosed = false;
while (pos < end) {
const ch = text.charCodeAt(pos);
if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
pos += 2;
commentClosed = true;
break;
}
if (isLineBreak(ch)) {
precedingLineBreak = true;
if (skipTrivia) {
continue;
}
else {
return token = SyntaxKind.SingleLineCommentTrivia;
}
}
// Multi-line comment
if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
pos += 2;
let commentClosed = false;
while (pos < end) {
const ch = text.charCodeAt(pos);
if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
pos += 2;
commentClosed = true;
break;
}
if (isLineBreak(ch)) {
precedingLineBreak = true;
}
pos++;
}
if (!commentClosed) {
error(Diagnostics.Asterisk_Slash_expected);
}
if (skipTrivia) {
continue;
}
else {
tokenIsUnterminated = !commentClosed;
return token = SyntaxKind.MultiLineCommentTrivia;
}
pos++;
}
if (!commentClosed) {
error(Diagnostics.Asterisk_Slash_expected);
}
if (skipTrivia) {
continue;
}
else {
tokenIsUnterminated = !commentClosed;
return token = SyntaxKind.MultiLineCommentTrivia;
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.SlashEqualsToken;
}
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.SlashEqualsToken;
}
pos++;
return token = SyntaxKind.SlashToken;
@@ -1462,8 +1474,12 @@ namespace ts {
tokenValue = scanNumber();
return token = SyntaxKind.NumericLiteral;
case CharacterCodes.colon:
if (pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.colon) {
pos += 2;
return token = SyntaxKind.ColonColonToken;
}
pos++;
return token = SyntaxKind.ColonToken;
return token = SyntaxKind.ColonToken;
case CharacterCodes.semicolon:
pos++;
return token = SyntaxKind.SemicolonToken;
@@ -1477,20 +1493,21 @@ namespace ts {
return token = SyntaxKind.ConflictMarkerTrivia;
}
}
if (text.charCodeAt(pos + 1) === CharacterCodes.lessThan) {
if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
return pos += 3, token = SyntaxKind.LessThanLessThanEqualsToken;
if (pos + 1 < end) {
if (text.charCodeAt(pos + 1) === CharacterCodes.lessThan) {
if (pos + 2 < end && text.charCodeAt(pos + 2) === CharacterCodes.equals) {
return pos += 3, token = SyntaxKind.LessThanLessThanEqualsToken;
}
return pos += 2, token = SyntaxKind.LessThanLessThanToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.LessThanEqualsToken;
}
if (languageVariant === LanguageVariant.JSX &&
text.charCodeAt(pos + 1) === CharacterCodes.slash &&
text.charCodeAt(pos + 2) !== CharacterCodes.asterisk) {
return pos += 2, token = SyntaxKind.LessThanSlashToken;
}
return pos += 2, token = SyntaxKind.LessThanLessThanToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.LessThanEqualsToken;
}
if (languageVariant === LanguageVariant.JSX &&
text.charCodeAt(pos + 1) === CharacterCodes.slash &&
text.charCodeAt(pos + 2) !== CharacterCodes.asterisk) {
return pos += 2, token = SyntaxKind.LessThanSlashToken;
}
pos++;
return token = SyntaxKind.LessThanToken;
@@ -1504,15 +1521,16 @@ namespace ts {
return token = SyntaxKind.ConflictMarkerTrivia;
}
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
return pos += 3, token = SyntaxKind.EqualsEqualsEqualsToken;
if (pos + 1 < end) {
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
if (pos + 2 < end && text.charCodeAt(pos + 2) === CharacterCodes.equals) {
return pos += 3, token = SyntaxKind.EqualsEqualsEqualsToken;
}
return pos += 2, token = SyntaxKind.EqualsEqualsToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
return pos += 2, token = SyntaxKind.EqualsGreaterThanToken;
}
return pos += 2, token = SyntaxKind.EqualsEqualsToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
return pos += 2, token = SyntaxKind.EqualsGreaterThanToken;
}
pos++;
return token = SyntaxKind.EqualsToken;
@@ -1539,7 +1557,7 @@ namespace ts {
pos++;
return token = SyntaxKind.CloseBracketToken;
case CharacterCodes.caret:
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
if (pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.CaretEqualsToken;
}
pos++;
@@ -1548,14 +1566,16 @@ namespace ts {
pos++;
return token = SyntaxKind.OpenBraceToken;
case CharacterCodes.bar:
if (text.charCodeAt(pos + 1) === CharacterCodes.bar) {
return pos += 2, token = SyntaxKind.BarBarToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.BarEqualsToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
return pos += 2, token = SyntaxKind.BarGreaterThanToken;
if (pos + 1 < end) {
if (text.charCodeAt(pos + 1) === CharacterCodes.bar) {
return pos += 2, token = SyntaxKind.BarBarToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.BarEqualsToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
return pos += 2, token = SyntaxKind.BarGreaterThanToken;
}
}
pos++;
return token = SyntaxKind.BarToken;
+21 -2
View File
@@ -71,6 +71,8 @@ namespace ts {
return visitCallExpression(node as CallExpression);
case SyntaxKind.OperatorExpression:
return visitOperatorExpression(node as OperatorExpression);
case SyntaxKind.BindExpression:
return visitBindExpression(node as BindExpression);
default:
return visitEachChild(node, visitor, context);
}
@@ -488,11 +490,11 @@ namespace ts {
positionalParameters,
/*type*/ undefined,
/*equalsGreaterThanToken*/ createToken(SyntaxKind.EqualsGreaterThanToken),
updateCall(node, expression, /*typeArguments*/ undefined, argumentList),
updateCall(node, expression, /*typeArguments*/ undefined, argumentList || node.arguments),
/*location*/ node
);
}
return updateCall(node, expression, /*typeArguments*/ undefined, argumentList);
return updateCall(node, expression, /*typeArguments*/ undefined, argumentList || node.arguments);
}
function visitOperatorExpression(node: OperatorExpression) {
@@ -537,6 +539,23 @@ namespace ts {
node
);
}
function visitBindExpression(node: BindExpression) {
const thisArg = createTempVariable(context.hoistVariableDeclaration);
return inlineExpressions([
createAssignment(
thisArg,
visitNode(node.expression, visitor, isExpression),
node.expression
),
createFunctionBind(
visitNode(node.targetExpression, visitor, isLeftHandSideExpression),
thisArg,
[],
node
)
]);
}
}
const assignHelper: EmitHelper = {
+8
View File
@@ -96,6 +96,7 @@ namespace ts {
BarBarToken,
QuestionToken,
ColonToken,
ColonColonToken,
AtToken,
// Assignments
EqualsToken,
@@ -233,6 +234,7 @@ namespace ts {
ObjectLiteralExpression,
PropertyAccessExpression,
ElementAccessExpression,
BindExpression,
CallExpression,
NewExpression,
TaggedTemplateExpression,
@@ -1417,6 +1419,12 @@ namespace ts {
| SuperElementAccessExpression
;
export interface BindExpression extends MemberExpression {
kind: SyntaxKind.BindExpression;
expression: LeftHandSideExpression;
targetExpression: MemberExpression;
}
export interface CallExpression extends LeftHandSideExpression, Declaration {
kind: SyntaxKind.CallExpression;
expression: LeftHandSideExpression;
+12 -3
View File
@@ -3947,11 +3947,10 @@ namespace ts {
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
}
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
function isMemberExpressionKind(kind: SyntaxKind): boolean {
return kind === SyntaxKind.PropertyAccessExpression
|| kind === SyntaxKind.ElementAccessExpression
|| kind === SyntaxKind.NewExpression
|| kind === SyntaxKind.CallExpression
|| kind === SyntaxKind.BindExpression
|| kind === SyntaxKind.JsxElement
|| kind === SyntaxKind.JsxSelfClosingElement
|| kind === SyntaxKind.TaggedTemplateExpression
@@ -3976,6 +3975,16 @@ namespace ts {
|| kind === SyntaxKind.RawExpression;
}
export function isMemberExpression(node: Node): node is MemberExpression {
return isMemberExpressionKind(skipPartiallyEmittedExpressions(node).kind);
}
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
return kind === SyntaxKind.NewExpression
|| kind === SyntaxKind.CallExpression
|| isMemberExpressionKind(kind);
}
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind);
}