Convert ShadowCascadeExpression to CascadeJudgment.

Change-Id: I33d20438a9dd09e41f8db27c37b541a0efc78bd0
Reviewed-on: https://dart-review.googlesource.com/62040
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 2c6602c..d557f90 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -976,14 +976,14 @@
   void beginCascade(Token token) {
     debugEvent("beginCascade");
     Expression expression = popForValue();
-    if (expression is ShadowCascadeExpression) {
+    if (expression is CascadeJudgment) {
       push(expression);
       push(new VariableUseGenerator(this, token, expression.variable));
       expression.extend();
     } else {
       VariableDeclaration variable = new VariableDeclarationJudgment.forValue(
           expression, functionNestingLevel);
-      push(new ShadowCascadeExpression(variable));
+      push(new CascadeJudgment(variable));
       push(new VariableUseGenerator(this, token, variable));
     }
   }
@@ -992,7 +992,7 @@
   void endCascade() {
     debugEvent("endCascade");
     Expression expression = popForEffect();
-    ShadowCascadeExpression cascadeReceiver = pop();
+    CascadeJudgment cascadeReceiver = pop();
     cascadeReceiver.finalize(expression);
     push(cascadeReceiver);
   }
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 55cfbca..c356ea9 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
@@ -69,7 +69,7 @@
         AssertInitializerJudgment,
         AssertStatementJudgment,
         BreakJudgment,
-        ShadowCascadeExpression,
+        CascadeJudgment,
         ComplexAssignmentJudgment,
         ConstructorInvocationJudgment,
         ContinueSwitchJudgment,
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 d8d1e0b..70b9dae 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
@@ -374,21 +374,21 @@
 /// variable"--this is the variable that remembers the value of the expression
 /// preceding the first `..` while the cascades are being evaluated.
 ///
-/// After constructing a [ShadowCascadeExpression], the caller should
+/// After constructing a [CascadeJudgment], the caller should
 /// call [finalize] with an expression representing the expression after the
 /// `..`.  If a further `..` follows that expression, the caller should call
 /// [extend] followed by [finalize] for each subsequent cascade.
-class ShadowCascadeExpression extends Let implements ExpressionJudgment {
+class CascadeJudgment extends Let implements ExpressionJudgment {
   DartType inferredType;
 
   /// Pointer to the last "let" expression in the cascade.
   Let nextCascade;
 
-  /// Creates a [ShadowCascadeExpression] using [variable] as the cascade
+  /// Creates a [CascadeJudgment] using [variable] as the cascade
   /// variable.  Caller is responsible for ensuring that [variable]'s
   /// initializer is the expression preceding the first `..` of the cascade
   /// expression.
-  ShadowCascadeExpression(VariableDeclarationJudgment variable)
+  CascadeJudgment(VariableDeclarationJudgment variable)
       : super(
             variable,
             makeLet(new VariableDeclaration.forValue(new _UnfinishedCascade()),
@@ -396,6 +396,17 @@
     nextCascade = body;
   }
 
+  ExpressionJudgment get targetJudgment => variable.initializer;
+
+  Iterable<ExpressionJudgment> get cascadeJudgments sync* {
+    Let section = body;
+    while (true) {
+      yield section.variable.initializer;
+      if (section.body is! Let) break;
+      section = section.body;
+    }
+  }
+
   /// Adds a new unfinalized section to the end of the cascade.  Should be
   /// called after the previous cascade section has been finalized.
   void extend() {
@@ -420,17 +431,13 @@
       ShadowTypeInferrer inferrer,
       Factory<Expression, Statement, Initializer, Type> factory,
       DartType typeContext) {
-    inferredType = inferrer.inferExpression(
-        factory, variable.initializer, typeContext, true);
+    inferredType =
+        inferrer.inferExpression(factory, targetJudgment, typeContext, true);
     if (inferrer.strongMode) {
       variable.type = inferredType;
     }
-    Let section = body;
-    while (true) {
-      inferrer.inferExpression(
-          factory, section.variable.initializer, const UnknownType(), false);
-      if (section.body is! Let) break;
-      section = section.body;
+    for (var judgment in cascadeJudgments) {
+      inferrer.inferExpression(factory, judgment, const UnknownType(), false);
     }
     inferrer.listener.cascadeExpression(this, fileOffset, inferredType);
     return null;
@@ -3392,7 +3399,7 @@
   bool _isInCascade() {
     TreeNode ancestor = variable.parent;
     while (ancestor is Let) {
-      if (ancestor is ShadowCascadeExpression) {
+      if (ancestor is CascadeJudgment) {
         return true;
       }
       ancestor = ancestor.parent;