Added IntermediateValue constant results, EvaluationReferences to store values.

Pre-work for variable declarations and method invocation. Storing values in locations (refs) and having the ability to update the values.

Change-Id: I682c139dfebbc4ef6f5032d4f53f29f08b8ceeb8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/188500
Commit-Queue: Kallen Tu <kallentu@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 0d2f50f..547cc29 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -544,7 +544,7 @@
     if (node.initializer != null) {
       if (node.isConst) {
         final Constant constant = evaluateWithContext(node, node.initializer);
-        constantEvaluator.env.addVariableValue(node, constant);
+        constantEvaluator.env.updateVariableValue(node, constant);
         node.initializer = makeConstantExpression(constant, node.initializer)
           ..parent = node;
 
@@ -1644,14 +1644,14 @@
             // TODO(johnniwinther): This should call [_evaluateSubexpression].
             : _evaluateNullableSubexpression(parameter.initializer);
         if (value is AbortConstant) return value;
-        env.addVariableValue(parameter, value);
+        env.updateVariableValue(parameter, value);
       }
       for (final VariableDeclaration parameter in function.namedParameters) {
         final Constant value = namedArguments[parameter.name] ??
             // TODO(johnniwinther): This should call [_evaluateSubexpression].
             _evaluateNullableSubexpression(parameter.initializer);
         if (value is AbortConstant) return value;
-        env.addVariableValue(parameter, value);
+        env.updateVariableValue(parameter, value);
       }
 
       // Step 2) Run all initializers (including super calls) with environment
@@ -1672,7 +1672,7 @@
           final VariableDeclaration variable = init.variable;
           Constant constant = _evaluateSubexpression(variable.initializer);
           if (constant is AbortConstant) return constant;
-          env.addVariableValue(variable, constant);
+          env.updateVariableValue(variable, constant);
         } else if (init is SuperInitializer) {
           AbortConstant error = checkConstructorConst(init, constructor);
           if (error != null) return error;
@@ -2374,7 +2374,7 @@
   Constant visitLet(Let node) {
     Constant value = _evaluateSubexpression(node.variable.initializer);
     if (value is AbortConstant) return value;
-    env.addVariableValue(node.variable, value);
+    env.updateVariableValue(node.variable, value);
     return _evaluateSubexpression(node.body);
   }
 
@@ -2729,14 +2729,14 @@
             // TODO(johnniwinther): This should call [_evaluateSubexpression].
             : _evaluateNullableSubexpression(parameter.initializer);
         if (value is AbortConstant) return value;
-        env.addVariableValue(parameter, value);
+        env.updateVariableValue(parameter, value);
       }
       for (final VariableDeclaration parameter in function.namedParameters) {
         final Constant value = namedArguments[parameter.name] ??
             // TODO(johnniwinther): This should call [_evaluateSubexpression].
             _evaluateNullableSubexpression(parameter.initializer);
         if (value is AbortConstant) return value;
-        env.addVariableValue(parameter, value);
+        env.updateVariableValue(parameter, value);
       }
       Statement body = function.body;
       if (body is ReturnStatement) {
@@ -3269,9 +3269,9 @@
   final Map<TypeParameter, DartType> _typeVariables =
       <TypeParameter, DartType>{};
 
-  /// The values of the parameters/variables in scope.
-  final Map<VariableDeclaration, Constant> _variables =
-      <VariableDeclaration, Constant>{};
+  /// The references to values of the parameters/variables in scope.
+  final Map<VariableDeclaration, EvaluationReference> _variables =
+      <VariableDeclaration, EvaluationReference>{};
 
   /// The variables that hold unevaluated constants.
   ///
@@ -3288,15 +3288,19 @@
     _typeVariables[parameter] = value;
   }
 
-  void addVariableValue(VariableDeclaration variable, Constant value) {
-    _variables[variable] = value;
+  void updateVariableValue(VariableDeclaration variable, Constant value) {
+    if (!_variables.containsKey(variable)) {
+      _variables[variable] = new EvaluationReference(value);
+    } else {
+      _variables[variable].value = value;
+    }
     if (value is UnevaluatedConstant) {
       _unreadUnevaluatedVariables.add(variable);
     }
   }
 
   Constant lookupVariable(VariableDeclaration variable) {
-    Constant value = _variables[variable];
+    Constant value = _variables[variable]?.value;
     if (value is UnevaluatedConstant) {
       _unreadUnevaluatedVariables.remove(variable);
     }
@@ -3307,7 +3311,7 @@
   Iterable<UnevaluatedConstant> get unevaluatedUnreadConstants {
     if (_unreadUnevaluatedVariables.isEmpty) return const [];
     return _unreadUnevaluatedVariables.map<UnevaluatedConstant>(
-        (VariableDeclaration variable) => _variables[variable]);
+        (VariableDeclaration variable) => _variables[variable].value);
   }
 
   DartType substituteType(DartType type) {
@@ -3333,6 +3337,70 @@
   }
 }
 
+/// Location that stores a value in the [ConstantEvaluator].
+class EvaluationReference {
+  Constant value;
+
+  EvaluationReference(this.value);
+}
+
+/// An intermediate result that is used within the [ConstantEvaluator].
+class IntermediateValue implements Constant {
+  dynamic value;
+
+  IntermediateValue(this.value);
+
+  @override
+  R accept<R>(ConstantVisitor<R> v) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  R acceptReference<R>(Visitor<R> v) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  Expression asExpression() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  DartType getType(StaticTypeContext context) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String leakingDebugToString() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toString() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toStringInternal() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toText(AstTextStrategy strategy) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    throw new UnimplementedError();
+  }
+}
+
 abstract class AbortConstant implements Constant {}
 
 class _AbortDueToErrorConstant extends AbortConstant {