Add Forest support for for statements
Change-Id: Ic65a09c01012e8a5d0ab2a4f755950c18b00fa9f
Reviewed-on: https://dart-review.googlesource.com/56000
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
index 8c06134..28b8ae0 100644
--- a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
@@ -141,6 +141,45 @@
astFactory.expressionStatement(expression, semicolon);
@override
+ Statement forStatement(
+ Token forKeyword,
+ Token leftParenthesis,
+ covariant variableList,
+ covariant initialization,
+ Token leftSeparator,
+ Expression condition,
+ Token rightSeparator,
+ List<Expression> updaters,
+ Token rightParenthesis,
+ Statement body) =>
+ astFactory.forStatement(
+ forKeyword,
+ leftParenthesis,
+ variableList,
+ initialization,
+ leftSeparator,
+ condition,
+ rightSeparator,
+ updaters,
+ rightParenthesis,
+ body);
+
+ @override
+ Expression getExpressionFromExpressionStatement(Statement statement) =>
+ (statement as ExpressionStatement).expression;
+
+ @override
+ Token getSemicolon(Statement statement) {
+ if (statement is ExpressionStatement) {
+ return statement.semicolon;
+ }
+ if (statement is EmptyStatement) {
+ return statement.semicolon;
+ }
+ return null;
+ }
+
+ @override
kernel.DartType getTypeAt(TypeArgumentList typeArguments, int index) {
return null; // typeArguments.arguments[index].type.kernelType;
}
@@ -166,9 +205,24 @@
elseStatement);
@override
+ Generator<Expression, Statement, _Arguments> indexedAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ Expression receiver,
+ Expression index,
+ kernel.Procedure getter,
+ kernel.Procedure setter) {
+ // TODO(brianwilkerson): Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
bool isBlock(Object node) => node is Block;
@override
+ bool isEmptyStatement(Statement statement) => statement is EmptyStatement;
+
+ @override
bool isErroneousNode(Object node) => false /* ??? */;
@override
@@ -177,6 +231,10 @@
astFactory.isExpression(expression, isOperator, notOperator, type);
@override
+ bool isExpressionStatement(Statement statement) =>
+ statement is ExpressionStatement;
+
+ @override
bool isThisExpression(Object node) => node is ThisExpression;
@override
@@ -280,12 +338,37 @@
..staticType = _typeProvider?.boolType;
@override
+ Generator<Expression, Statement, _Arguments> nullAwarePropertyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ Expression receiverExpression,
+ kernel.Name name,
+ kernel.Member getter,
+ kernel.Member setter,
+ kernel.DartType type) {
+ // TODO(brianwilkerson): Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Object parenthesizedCondition(Token leftParenthesis, Expression expression,
Token rightParenthesis) =>
astFactory.parenthesizedExpression(
leftParenthesis, expression, rightParenthesis);
@override
+ Generator<Expression, Statement, _Arguments> propertyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ Expression receiver,
+ kernel.Name name,
+ kernel.Member getter,
+ kernel.Member setter) {
+ // TODO(brianwilkerson): Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
int readOffset(AstNode node) => node.offset;
@override
@@ -319,6 +402,17 @@
astFactory.adjacentStrings(strings.cast<StringLiteral>());
@override
+ Generator<Expression, Statement, _Arguments> superPropertyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ kernel.Name name,
+ kernel.Member getter,
+ kernel.Member setter) {
+ // TODO(brianwilkerson): Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Statement syntheticLabeledStatement(Statement statement) => statement;
@override
@@ -326,6 +420,28 @@
astFactory.thisExpression(thisKeyword);
@override
+ Generator<Expression, Statement, _Arguments> thisIndexedAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ Expression index,
+ kernel.Procedure getter,
+ kernel.Procedure setter) {
+ // TODO(brianwilkerson): Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
+ Generator<Expression, Statement, _Arguments> thisPropertyAccessGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token location,
+ kernel.Name name,
+ kernel.Member getter,
+ kernel.Member setter) {
+ // TODO(brianwilkerson): Implement this.
+ throw new UnimplementedError();
+ }
+
+ @override
Expression throwExpression(Token throwKeyword, Expression expression) =>
astFactory.throwExpression(throwKeyword, expression);
@@ -352,6 +468,15 @@
variablesDeclaration.variables.variables;
@override
+ Generator<Expression, Statement, _Arguments> variableUseGenerator(
+ ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
+ Token token,
+ VariableDeclarationStatement variable,
+ kernel.DartType promotedType) {
+ // TODO(brianwilkerson) Implement this.
+ throw new UnimplementedError();
+ }
+
Statement whileStatement(Token whileKeyword,
ParenthesizedExpression condition, Statement body) =>
astFactory.whileStatement(whileKeyword, condition.leftParenthesis,
@@ -364,86 +489,6 @@
Statement yieldStatement(Token yieldKeyword, Token star,
Expression expression, Token semicolon) =>
astFactory.yieldStatement(yieldKeyword, star, expression, semicolon);
-
- @override
- Generator<Expression, Statement, _Arguments> variableUseGenerator(
- ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
- Token token,
- VariableDeclarationStatement variable,
- kernel.DartType promotedType) {
- // TODO(brianwilkerson) Implement this.
- throw new UnimplementedError();
- }
-
- @override
- Generator<Expression, Statement, _Arguments> propertyAccessGenerator(
- ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
- Token token,
- Expression receiver,
- kernel.Name name,
- kernel.Member getter,
- kernel.Member setter) {
- // TODO(brianwilkerson) Implement this.
- throw new UnimplementedError();
- }
-
- @override
- Generator<Expression, Statement, _Arguments> thisPropertyAccessGenerator(
- ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
- Token location,
- kernel.Name name,
- kernel.Member getter,
- kernel.Member setter) {
- // TODO(brianwilkerson) Implement this.
- throw new UnimplementedError();
- }
-
- @override
- Generator<Expression, Statement, _Arguments> nullAwarePropertyAccessGenerator(
- ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
- Token token,
- Expression receiverExpression,
- kernel.Name name,
- kernel.Member getter,
- kernel.Member setter,
- kernel.DartType type) {
- // TODO(brianwilkerson) Implement this.
- throw new UnimplementedError();
- }
-
- @override
- Generator<Expression, Statement, _Arguments> superPropertyAccessGenerator(
- ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
- Token token,
- kernel.Name name,
- kernel.Member getter,
- kernel.Member setter) {
- // TODO(brianwilkerson): Implement this.
- throw new UnimplementedError();
- }
-
- @override
- Generator<Expression, Statement, _Arguments> indexedAccessGenerator(
- ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
- Token token,
- Expression receiver,
- Expression index,
- kernel.Procedure getter,
- kernel.Procedure setter) {
- // TODO(brianwilkerson): Implement this.
- throw new UnimplementedError();
- }
-
- @override
- Generator<Expression, Statement, _Arguments> thisIndexedAccessGenerator(
- ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
- Token token,
- Expression index,
- kernel.Procedure getter,
- kernel.Procedure setter) {
- // TODO(brianwilkerson): Implement this.
- throw new UnimplementedError();
- }
}
/// A data holder used to conform to the [Forest] API.
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 7cb74e5..2fc31e8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1839,14 +1839,6 @@
Statement body = popStatement();
List<Expression> updates = popListForEffect(updateExpressionCount);
Statement conditionStatement = popStatement();
- kernel.Statement kernelConditionStatement =
- toKernelStatement(conditionStatement);
- Expression condition = null;
- if (kernelConditionStatement is ExpressionStatement) {
- condition = toExpression(kernelConditionStatement.expression);
- } else {
- assert(kernelConditionStatement is EmptyStatement);
- }
dynamic variableOrExpression = pop();
List<VariableDeclaration> variables =
buildVariableDeclarations(variableOrExpression);
@@ -1857,22 +1849,36 @@
exitLocalScope();
JumpTarget continueTarget = exitContinueTarget();
JumpTarget breakTarget = exitBreakTarget();
- kernel.Statement kernelBody = toKernelStatement(body);
if (continueTarget.hasUsers) {
- kernelBody = new ShadowLabeledStatement(kernelBody);
- continueTarget.resolveContinues(forest, kernelBody);
+ body = forest.syntheticLabeledStatement(body);
+ continueTarget.resolveContinues(forest, body);
}
- kernel.Statement result = new ShadowForStatement(
+ Expression condition;
+ Token rightSeparator;
+ if (forest.isExpressionStatement(conditionStatement)) {
+ condition =
+ forest.getExpressionFromExpressionStatement(conditionStatement);
+ rightSeparator = forest.getSemicolon(conditionStatement);
+ } else {
+ assert(forest.isEmptyStatement(conditionStatement));
+ rightSeparator = forest.getSemicolon(conditionStatement);
+ }
+ Statement result = forest.forStatement(
+ forKeyword,
+ leftParen,
variables,
- toKernelExpression(condition),
- toKernelExpressionList(updates),
- kernelBody)
- ..fileOffset = forKeyword.charOffset;
+ variables,
+ leftSeparator,
+ condition,
+ rightSeparator,
+ updates,
+ leftParen.endGroup,
+ body);
if (breakTarget.hasUsers) {
- result = new ShadowLabeledStatement(result);
+ result = forest.syntheticLabeledStatement(result);
breakTarget.resolveBreaks(forest, result);
}
- exitLoopOrSwitch(toStatement(result));
+ exitLoopOrSwitch(result);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index f4de49e..1490aff 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -65,6 +65,7 @@
ShadowDoStatement,
ShadowDoubleLiteral,
ShadowExpressionStatement,
+ ShadowForStatement,
ShadowIfStatement,
ShadowIntLiteral,
ShadowIsExpression,
@@ -351,6 +352,22 @@
}
@override
+ Statement forStatement(
+ Token forKeyword,
+ Token leftParenthesis,
+ List<VariableDeclaration> variableList,
+ covariant initialization,
+ Token leftSeparator,
+ Expression condition,
+ Token rightSeparator,
+ List<Expression> updaters,
+ Token rightParenthesis,
+ Statement body) {
+ return new ShadowForStatement(variableList, condition, updaters, body)
+ ..fileOffset = forKeyword.charOffset;
+ }
+
+ @override
Statement ifStatement(Token ifKeyword, Expression condition,
Statement thenStatement, Token elseKeyword, Statement elseStatement) {
return new ShadowIfStatement(condition, thenStatement, elseStatement)
@@ -467,9 +484,20 @@
}
@override
+ Expression getExpressionFromExpressionStatement(Statement statement) {
+ return (statement as ExpressionStatement).expression;
+ }
+
+ @override
+ Token getSemicolon(Statement statement) => null;
+
+ @override
bool isBlock(Object node) => node is Block;
@override
+ bool isEmptyStatement(Statement statement) => statement is EmptyStatement;
+
+ @override
bool isErroneousNode(Object node) {
if (node is ExpressionStatement) {
ExpressionStatement statement = node;
@@ -491,6 +519,10 @@
}
@override
+ bool isExpressionStatement(Statement statement) =>
+ statement is ExpressionStatement;
+
+ @override
bool isThisExpression(Object node) => node is ThisExpression;
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 50f9c48..2589526 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -201,6 +201,19 @@
/// [semicolon].
Statement emptyStatement(Location semicolon);
+ /// Return a representation of a for statement.
+ Statement forStatement(
+ Location forKeyword,
+ Location leftParenthesis,
+ covariant variableList,
+ covariant initialization,
+ Location leftSeparator,
+ Expression condition,
+ Location rightSeparator,
+ List<Expression> updaters,
+ Location rightParenthesis,
+ Statement body);
+
/// Return a representation of an `if` statement.
Statement ifStatement(Location ifKeyword, covariant Expression condition,
Statement thenStatement, Location elseKeyword, Statement elseStatement);
@@ -270,10 +283,25 @@
Statement yieldStatement(Location yieldKeyword, Location star,
Expression expression, Location semicolon);
+ /// Return the expression from the given expression [statement].
+ Expression getExpressionFromExpressionStatement(Statement statement);
+
+ /// Return the semicolon at the end of the given [statement], or `null` if the
+ /// statement is not terminated by a semicolon.
+ Location getSemicolon(Statement statement);
+
bool isBlock(Object node);
+ /// Return `true` if the given [statement] is the representation of an empty
+ /// statement.
+ bool isEmptyStatement(Statement statement);
+
bool isErroneousNode(Object node);
+ /// Return `true` if the given [statement] is the representation of an
+ /// expression statement.
+ bool isExpressionStatement(Statement statement);
+
bool isThisExpression(Object node);
bool isVariablesDeclaration(Object node);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
index 6817deb..33906b3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
@@ -76,7 +76,6 @@
ShadowFactoryConstructorInvocation,
ShadowFieldInitializer,
ShadowForInStatement,
- ShadowForStatement,
ShadowFunctionDeclaration,
ShadowFunctionExpression,
ShadowIfNullExpression,