Convert ShadowForStatement to ForJudgment.

Change-Id: I95e70234be97c4d246ac93caf64958bee1cfbe83
Reviewed-on: https://dart-review.googlesource.com/61911
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
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 b4f7c02..0ebe41a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1855,27 +1855,17 @@
     }
   }
 
-  List<VariableDeclaration> buildVariableDeclarations(variableOrExpression) {
-    if (variableOrExpression is Generator) {
-      variableOrExpression = variableOrExpression.buildForEffect();
-    }
+  List<VariableDeclaration> buildForInitVariableDeclarations(
+      variableOrExpression) {
     if (variableOrExpression is VariableDeclaration) {
       return <VariableDeclaration>[variableOrExpression];
-    } else if (variableOrExpression is Expression) {
-      VariableDeclaration variable = new VariableDeclarationJudgment.forEffect(
-          variableOrExpression, functionNestingLevel);
-      return <VariableDeclaration>[variable];
-    } else if (variableOrExpression is ExpressionStatement) {
-      VariableDeclaration variable = new VariableDeclarationJudgment.forEffect(
-          variableOrExpression.expression, functionNestingLevel);
-      return <VariableDeclaration>[variable];
     } else if (forest.isVariablesDeclaration(variableOrExpression)) {
       return forest
           .variablesDeclarationExtractDeclarations(variableOrExpression);
     } else if (variableOrExpression is List<Object>) {
       List<VariableDeclaration> variables = <VariableDeclaration>[];
       for (Object v in variableOrExpression) {
-        variables.addAll(buildVariableDeclarations(v));
+        variables.addAll(buildForInitVariableDeclarations(v));
       }
       return variables;
     } else if (variableOrExpression == null) {
@@ -1884,6 +1874,15 @@
     return null;
   }
 
+  List<ExpressionJudgment> buildForInitExpressions(variableOrExpression) {
+    if (variableOrExpression is ExpressionJudgment) {
+      return <ExpressionJudgment>[variableOrExpression];
+    } else if (variableOrExpression is ExpressionStatementJudgment) {
+      return <ExpressionJudgment>[variableOrExpression.expression];
+    }
+    return null;
+  }
+
   @override
   void endForStatement(Token forKeyword, Token leftParen, Token leftSeparator,
       int updateExpressionCount, Token endToken) {
@@ -1892,12 +1891,16 @@
     List<Expression> updates = popListForEffect(updateExpressionCount);
     Statement conditionStatement = popStatement();
     Object variableOrExpression = pop();
-    List<VariableDeclaration> variables =
-        buildVariableDeclarations(variableOrExpression);
-    if (variables == null) {
-      return unhandled("${variableOrExpression.runtimeType}", "endForStatement",
-          forKeyword.charOffset, uri);
-    }
+
+    variableOrExpression = variableOrExpression is Generator
+        ? variableOrExpression.buildForEffect()
+        : variableOrExpression;
+    List<ExpressionJudgment> initializers =
+        buildForInitExpressions(variableOrExpression);
+    List<VariableDeclaration> variableList = initializers == null
+        ? buildForInitVariableDeclarations(variableOrExpression)
+        : null;
+
     exitLocalScope();
     JumpTarget continueTarget = exitContinueTarget();
     JumpTarget breakTarget = exitBreakTarget();
@@ -1915,8 +1918,8 @@
     Statement result = forest.forStatement(
         forKeyword,
         leftParen,
-        variables,
-        variables,
+        variableList,
+        initializers,
         leftSeparator,
         condition,
         conditionStatement,
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index 0d8e48f..8f4f321 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -88,7 +88,7 @@
         LoadLibraryJudgment,
         NullJudgment,
         ExpressionStatementJudgment,
-        ShadowForStatement,
+        ForJudgment,
         IfJudgment,
         ListLiteralJudgment,
         ShadowLogicalExpression,
@@ -399,14 +399,15 @@
       Token forKeyword,
       Token leftParenthesis,
       List<VariableDeclaration> variableList,
-      covariant initialization,
+      List<Expression> initializers,
       Token leftSeparator,
       Expression condition,
       Statement conditionStatement,
       List<Expression> updaters,
       Token rightParenthesis,
       Statement body) {
-    return new ShadowForStatement(variableList, condition, updaters, body)
+    return new ForJudgment(
+        variableList, initializers, condition, updaters, body)
       ..fileOffset = forKeyword.charOffset;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index e1812ed..0325d02 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -222,7 +222,7 @@
       Token forKeyword,
       Token leftParenthesis,
       covariant variableList,
-      covariant initialization,
+      covariant initializers,
       Token leftSeparator,
       Expression condition,
       Statement conditionStatement,
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 669600c..dc2cf36 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
@@ -73,6 +73,7 @@
         ShadowConstructorInvocation,
         ContinueSwitchJudgment,
         DeferredCheckJudgment,
+        ExpressionJudgment,
         ExpressionStatementJudgment,
         ShadowFactoryConstructorInvocation,
         ShadowFieldInitializer,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 5fab7dd..8b16387 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -1271,29 +1271,50 @@
 }
 
 /// Concrete shadow object representing a classic for loop in kernel form.
-class ShadowForStatement extends ForStatement implements StatementJudgment {
-  ShadowForStatement(List<VariableDeclaration> variables, Expression condition,
-      List<Expression> updates, Statement body)
-      : super(variables, condition, updates, body);
+class ForJudgment extends ForStatement implements StatementJudgment {
+  final List<ExpressionJudgment> initializers;
+
+  ForJudgment(List<VariableDeclaration> variables, this.initializers,
+      ExpressionJudgment condition, List<Expression> updates, Statement body)
+      : super(variables ?? [], condition, updates, body);
+
+  List<VariableDeclarationJudgment> get variableJudgments => variables.cast();
+
+  ExpressionJudgment get conditionJudgment => condition;
+
+  List<ExpressionJudgment> get updateJudgments => updates.cast();
+
+  StatementJudgment get bodyJudgment => body;
 
   @override
   void infer<Expression, Statement, Initializer, Type>(
       ShadowTypeInferrer inferrer,
       Factory<Expression, Statement, Initializer, Type> factory) {
-    for (var variable in variables) {
-      inferrer.inferStatement(factory, variable);
+    var initializers = this.initializers;
+    var conditionJudgment = this.conditionJudgment;
+    if (initializers != null) {
+      for (var initializer in initializers) {
+        variables
+            .add(new VariableDeclaration.forValue(initializer)..parent = this);
+        inferrer.inferExpression(
+            factory, initializer, const UnknownType(), false);
+      }
+    } else {
+      for (var variable in variableJudgments) {
+        inferrer.inferStatement(factory, variable);
+      }
     }
-    if (condition != null) {
+    if (conditionJudgment != null) {
       var expectedType = inferrer.coreTypes.boolClass.rawType;
-      var conditionType = inferrer.inferExpression(
-          factory, condition, expectedType, !inferrer.isTopLevel);
-      inferrer.ensureAssignable(
-          expectedType, conditionType, condition, condition.fileOffset);
+      inferrer.inferExpression(
+          factory, conditionJudgment, expectedType, !inferrer.isTopLevel);
+      inferrer.ensureAssignable(expectedType, conditionJudgment.inferredType,
+          condition, condition.fileOffset);
     }
-    for (var update in updates) {
+    for (var update in updateJudgments) {
       inferrer.inferExpression(factory, update, const UnknownType(), false);
     }
-    inferrer.inferStatement(factory, body);
+    inferrer.inferStatement(factory, bodyJudgment);
     inferrer.listener.forStatement(this, fileOffset, null, null, null, null,
         null, condition, null, updates, null, body);
   }